Skip to content
Open
13 changes: 13 additions & 0 deletions src/Prometheus/CollectorRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ public function wipeStorage(): void
$this->storageAdapter->wipeStorage();
}

/**
* Removes a specific previously stored metric from underlying storage adapter
*
* @param string $type
* @param string $name
*
* @return void
*/
public function wipeKey(string $type, string $name): void
{
$this->storageAdapter->wipeKey($type, $name);
}

/**
* @return MetricFamilySamples[]
*/
Expand Down
10 changes: 10 additions & 0 deletions src/Prometheus/RegistryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ interface RegistryInterface
*/
public function wipeStorage(): void;

/**
* Removes a specific previously stored metric from underlying storage adapter
*
* @param string $type
* @param string $name
*
* @return void
*/
public function wipeKey(string $type, string $name): void;

/**
* @return MetricFamilySamples[]
*/
Expand Down
8 changes: 8 additions & 0 deletions src/Prometheus/Storage/APC.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,14 @@ public function wipeStorage(): void
}
}

/**
* @inheritDoc
*/
public function wipeKey(string $type, string $key): void
{
// not implemented yet
}

/**
* @param mixed[] $data
* @return string
Expand Down
8 changes: 8 additions & 0 deletions src/Prometheus/Storage/APCng.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ public function wipeStorage(): void
apcu_delete($this->metainfoCacheKey);
}

/**
* @inheritDoc
*/
public function wipeKey(string $type, string $key): void
{
// not implemented yet
}

/**
* Scans the APCu keyspace for all metainfo keys. A new metainfo cache array is built,
* which references all metadata keys in APCu at that moment. This prevents a corner-case
Expand Down
10 changes: 10 additions & 0 deletions src/Prometheus/Storage/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@ public function updateCounter(array $data): void;
* @return void
*/
public function wipeStorage(): void;

/**
* Removes a specific previously stored metric from underlying storage
*
* @param string $type
* @param string $key
* @throws StorageException
* @return void
*/
public function wipeKey(string $type, string $key): void;
}
8 changes: 8 additions & 0 deletions src/Prometheus/Storage/InMemory.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ public function wipeStorage(): void
$this->summaries = [];
}

/**
* @inheritDoc
*/
public function wipeKey(string $type, string $key): void
{
// not implemented yet
}

/**
* @return MetricFamilySamples[]
*/
Expand Down
36 changes: 36 additions & 0 deletions src/Prometheus/Storage/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ public function wipeStorage(): void
);
}

/**
* @inheritDoc
*/
public function wipeKey(string $type, string $key): void
{
$this->ensureOpenConnection();

$searchPattern = "";

$globalPrefix = $this->redis->getOption(\Redis::OPT_PREFIX);
// @phpstan-ignore-next-line false positive, phpstan thinks getOptions returns int
if (is_string($globalPrefix)) {
$searchPattern .= $globalPrefix;
}

$searchPattern .= self::$prefix;
$searchPattern .= ":" . $type . ":" . $key;

$this->redis->eval(
<<<LUA
redis.replicate_commands()
local cursor = "0"
repeat
local results = redis.call('SCAN', cursor, 'MATCH', ARGV[1])
cursor = results[1]
for _, key in ipairs(results[2]) do
redis.call('DEL', key)
end
until cursor == "0"
LUA
,
[$searchPattern],
0
);
}

/**
* @param mixed[] $data
*
Expand Down
37 changes: 37 additions & 0 deletions src/Prometheus/Storage/RedisNg.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,43 @@ public function wipeStorage(): void
);
}

/**
* @inheritDoc
*/
public function wipeKey(string $type, string $key): void
{
$this->ensureOpenConnection();

$searchPattern = "";

$globalPrefix = $this->redis->getOption(\Redis::OPT_PREFIX);
// @phpstan-ignore-next-line false positive, phpstan thinks getOptions returns int
if (is_string($globalPrefix)) {
$searchPattern .= $globalPrefix;
}

$searchPattern .= self::$prefix;
$searchPattern .= ":" . $type . ":" . $key;

$this->redis->eval(
<<<LUA
redis.replicate_commands()
local cursor = "0"
repeat
local results = redis.call('SCAN', cursor, 'MATCH', ARGV[1])
cursor = results[1]
for _, key in ipairs(results[2]) do
redis.call('DEL', key)
end
until cursor == "0"
LUA
,
[$searchPattern],
0
);
}


/**
* @param mixed[] $data
*
Expand Down