Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
LKaemmerling authored Oct 14, 2024
2 parents 257bf8b + 35d5a68 commit 1efbc57
Show file tree
Hide file tree
Showing 27 changed files with 996 additions and 40 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/blackbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
php-version: 8.3
coverage: none

- name: Install dependencies
run: composer install --prefer-dist --no-interaction --no-suggest

- name: Compose Blackbox environment
run: docker-compose up -d
run: docker compose up -d
- name: Run Blackbox with APC
run: docker-compose run phpunit env ADAPTER=apc vendor/bin/phpunit tests/Test/
run: docker compose run phpunit env ADAPTER=apc vendor/bin/phpunit tests/Test/
- name: Run Blackbox with APCng
run: docker-compose run phpunit env ADAPTER=apcng vendor/bin/phpunit tests/Test/
run: docker compose run phpunit env ADAPTER=apcng vendor/bin/phpunit tests/Test/
- name: Run Blackbox with Redis
run: docker-compose run phpunit env ADAPTER=redis vendor/bin/phpunit tests/Test/
run: docker compose run phpunit env ADAPTER=redis vendor/bin/phpunit tests/Test/



5 changes: 2 additions & 3 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
php-version: 8.3
coverage: none

- name: Install dependencies
Expand All @@ -34,10 +34,9 @@ jobs:
fail-fast: false
matrix:
php:
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
name: PHPStan on PHP ${{ matrix.php }}
steps:
- name: Checkout code
Expand Down
27 changes: 23 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@ jobs:
fail-fast: true
matrix:
os: [ ubuntu-latest ]
php: [ 7.4, 8.0, 8.1, 8.2 ]
php: [ 8.1, 8.2, 8.3 ]
dependency-version: [ prefer-lowest, prefer-stable ]
redis-version: [ 6 ]
redis-version: [ 5, 6, 7 ]

name: P${{ matrix.php }} - ${{ matrix.dependency-version }} - ${{ matrix.os }}
name: P${{ matrix.php }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} - ${{ matrix.redis-version }}

env:
# The hostname used to communicate with the Redis service container
REDIS_HOST: redis
# The default Redis port
REDIS_PORT: 6379
# MySQL
DB_DATABASE: test
DB_USER: root
DB_PASSWORD: root

steps:
- name: Checkout code
uses: actions/checkout@v2
Expand All @@ -40,9 +45,23 @@ jobs:

- name: Install dependencies
run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest

- name: Start Redis
uses: supercharge/redis-github-action@1.1.0
with:
redis-version: ${{ matrix.redis-version }}
- name: Execute tests

- name: Execute tests (PDO with Sqlite)
run: vendor/bin/phpunit

- name: Start MySQL
run: |
sudo /etc/init.d/mysql start
mysql -e "CREATE DATABASE IF NOT EXISTS $DB_DATABASE;" -u$DB_USER -p$DB_PASSWORD
- name: Execute PDO tests with MySQL
env:
TEST_PDO_DSN: 'mysql:host=localhost;dbname=test'
TEST_PDO_USERNAME: 'root'
TEST_PDO_PASSWORD: 'root'
run: vendor/bin/phpunit tests/Test/Prometheus/PDO
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ $registry = new CollectorRegistry(new APC());
```
(see the `README.APCng.md` file for more details)

Using the PDO storage:
```php
$registry = new CollectorRegistry(new \PDO('mysql:host=localhost;dbname=prometheus', 'username', 'password'));
or
$registry = new CollectorRegistry(new \PDO('sqlite::memory:'));
```

### Advanced Usage

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"ext-redis": "Required if using Redis.",
"predis/predis": "Required if using Predis.",
"ext-apc": "Required if using APCu.",
"ext-pdo": "Required if using PDO.",
"promphp/prometheus_push_gateway_php": "An easy client for using Prometheus PushGateway.",
"symfony/polyfill-apcu": "Required if you use APCu on PHP8.0+"
},
Expand Down
2 changes: 1 addition & 1 deletion php-fpm/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.1-fpm
FROM php:8.2-fpm

RUN pecl install redis && docker-php-ext-enable redis
RUN pecl install apcu && docker-php-ext-enable apcu
Expand Down
2 changes: 1 addition & 1 deletion src/Prometheus/CollectorRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function wipeStorage(): void
*/
public function getMetricFamilySamples(bool $sortMetrics = true): array
{
return $this->storageAdapter->collect($sortMetrics);
return $this->storageAdapter->collect($sortMetrics); /** @phpstan-ignore-line */
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/Prometheus/MetricFamilySamples.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ public function __construct(array $data)
$this->type = $data['type'];
$this->help = $data['help'];
$this->labelNames = $data['labelNames'];
foreach ($data['samples'] as $sampleData) {
$this->samples[] = new Sample($sampleData);
if (isset($data['samples'])) {
foreach ($data['samples'] as $sampleData) {
$this->samples[] = new Sample($sampleData);
}
}
}

Expand Down
26 changes: 21 additions & 5 deletions src/Prometheus/RenderTextFormat.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
namespace Prometheus;

use RuntimeException;
use Throwable;

class RenderTextFormat implements RendererInterface
{
const MIME_TYPE = 'text/plain; version=0.0.4';

/**
* @param MetricFamilySamples[] $metrics
* @param bool $silent If true, render value errors as comments instead of throwing them.
* @return string
*/
public function render(array $metrics): string
public function render(array $metrics, bool $silent = false): string
{
usort($metrics, function (MetricFamilySamples $a, MetricFamilySamples $b): int {
return strcmp($a->getName(), $b->getName());
Expand All @@ -25,7 +27,20 @@ public function render(array $metrics): string
$lines[] = "# HELP " . $metric->getName() . " {$metric->getHelp()}";
$lines[] = "# TYPE " . $metric->getName() . " {$metric->getType()}";
foreach ($metric->getSamples() as $sample) {
$lines[] = $this->renderSample($metric, $sample);
try {
$lines[] = $this->renderSample($metric, $sample);
} catch (Throwable $e) {
// Redis and RedisNg allow samples with mismatching labels to be stored, which could cause ValueError
// to be thrown when rendering. If this happens, users can decide whether to ignore the error or not.
// These errors will normally disappear after the storage is flushed.
if (!$silent) {
throw $e;
}

$lines[] = "# Error: {$e->getMessage()}";
$lines[] = "# Labels: " . json_encode(array_merge($metric->getLabelNames(), $sample->getLabelNames()));
$lines[] = "# Values: " . json_encode(array_merge($sample->getLabelValues()));
}
}
}
return implode("\n", $lines) . "\n";
Expand All @@ -40,7 +55,7 @@ private function renderSample(MetricFamilySamples $metric, Sample $sample): stri
{
$labelNames = $metric->getLabelNames();
if ($metric->hasLabelNames() || $sample->hasLabelNames()) {
$escapedLabels = $this->escapeAllLabels($labelNames, $sample);
$escapedLabels = $this->escapeAllLabels($metric, $labelNames, $sample);
return $sample->getName() . '{' . implode(',', $escapedLabels) . '} ' . $sample->getValue();
}
return $sample->getName() . ' ' . $sample->getValue();
Expand All @@ -56,19 +71,20 @@ private function escapeLabelValue(string $v): string
}

/**
* @param MetricFamilySamples $metric
* @param string[] $labelNames
* @param Sample $sample
*
* @return string[]
*/
private function escapeAllLabels(array $labelNames, Sample $sample): array
private function escapeAllLabels(MetricFamilySamples $metric, array $labelNames, Sample $sample): array
{
$escapedLabels = [];

$labels = array_combine(array_merge($labelNames, $sample->getLabelNames()), $sample->getLabelValues());

if ($labels === false) {
throw new RuntimeException('Unable to combine labels.');
throw new RuntimeException('Unable to combine labels for metric named ' . $metric->getName());
}

foreach ($labels as $labelName => $labelValue) {
Expand Down
5 changes: 5 additions & 0 deletions src/Prometheus/Sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Prometheus;

use function is_infinite;

class Sample
{
/**
Expand Down Expand Up @@ -67,6 +69,9 @@ public function getLabelValues(): array
*/
public function getValue(): string
{
if (is_float($this->value) && is_infinite($this->value)) {
return $this->value > 0 ? '+Inf' : '-Inf';
}
return (string) $this->value;
}

Expand Down
42 changes: 39 additions & 3 deletions src/Prometheus/Storage/APC.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ public function updateHistogram(array $data): void
$old = apcu_fetch($sumKey);
if ($old !== false) {
$done = apcu_cas($sumKey, $old, $this->toBinaryRepresentationAsInteger($this->fromBinaryRepresentationAsInteger($old) + $data['value']));
} else {
$new = apcu_add($sumKey, $this->toBinaryRepresentationAsInteger(0));

// If sum does not exist, assume a new histogram and store the metadata
if ($new) {
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
}
}
}

Expand Down Expand Up @@ -123,11 +130,32 @@ public function updateSummary(array $data): void
public function updateGauge(array $data): void
{
$valueKey = $this->valueKey($data);
$old = apcu_fetch($valueKey);
if ($data['command'] === Adapter::COMMAND_SET) {
apcu_store($valueKey, $this->toBinaryRepresentationAsInteger($data['value']));
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
$new = $this->toBinaryRepresentationAsInteger($data['value']);
if ($old === false) {
apcu_store($valueKey, $new);
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
return;
} else {
// Taken from https://github.com/prometheus/client_golang/blob/66058aac3a83021948e5fb12f1f408ff556b9037/prometheus/value.go#L91
while (true) {
if ($old !== false) {
if (apcu_cas($valueKey, $old, $new)) {
return;
} else {
$old = apcu_fetch($valueKey);
}
} else {
// Cache got evicted under our feet? Just consider it a fresh/new insert and move on.
apcu_store($valueKey, $new);
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
return;
}
}
}
} else {
if (!apcu_exists($valueKey)) {
if ($old === false) {
$new = apcu_add($valueKey, $this->toBinaryRepresentationAsInteger(0));
if ($new) {
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
Expand All @@ -139,6 +167,11 @@ public function updateGauge(array $data): void
$old = apcu_fetch($valueKey);
if ($old !== false) {
$done = apcu_cas($valueKey, $old, $this->toBinaryRepresentationAsInteger($this->fromBinaryRepresentationAsInteger($old) + $data['value']));
} else {
$new = apcu_add($valueKey, $this->toBinaryRepresentationAsInteger(0));
if ($new) {
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
}
}
}
}
Expand All @@ -162,6 +195,9 @@ public function updateCounter(array $data): void
$old = apcu_fetch($valueKey);
if ($old !== false) {
$done = apcu_cas($valueKey, $old, $this->toBinaryRepresentationAsInteger($this->fromBinaryRepresentationAsInteger($old) + $data['value']));
} else {
apcu_add($this->valueKey($data), 0);
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
}
}
}
Expand Down
32 changes: 27 additions & 5 deletions src/Prometheus/Storage/APCng.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,34 @@ public function updateSummary(array $data): void
public function updateGauge(array $data): void
{
$valueKey = $this->valueKey($data);
$old = apcu_fetch($valueKey);
if ($data['command'] === Adapter::COMMAND_SET) {
apcu_store($valueKey, $this->convertToIncrementalInteger($data['value']), 0);
$this->storeMetadata($data);
$this->storeLabelKeys($data);
$new = $this->convertToIncrementalInteger($data['value']);
if ($old === false) {
apcu_store($valueKey, $new, 0);
$this->storeMetadata($data);
$this->storeLabelKeys($data);

return;
}

for ($loops = 0; $loops < self::MAX_LOOPS; $loops++) {
if (apcu_cas($valueKey, $old, $new)) {
break;
}
$old = apcu_fetch($valueKey);
if ($old === false) {
apcu_store($valueKey, $new, 0);
$this->storeMetadata($data);
$this->storeLabelKeys($data);

return;
}
}

return;
}

$old = apcu_fetch($valueKey);

if ($old === false) {
apcu_add($valueKey, 0, 0);
$this->storeMetadata($data);
Expand Down Expand Up @@ -896,6 +914,10 @@ private function decodeLabelKey(string $str): string
private function storeMetadata(array $data, bool $encoded = true): void
{
$metaKey = $this->metaKey($data);
if (apcu_exists($metaKey)) {
return;
}

$metaData = $this->metaData($data);
$toStore = $metaData;

Expand Down
Loading

0 comments on commit 1efbc57

Please sign in to comment.