Skip to content

Commit df8f474

Browse files
cmontezanohuangdijialimingxinleoyansongdaalbertcht
authoredJan 30, 2024
chore(deps): Bump hyper/metric 3.1 (#11)
* [3.1]Bumps dependencies (#5796) Co-authored-by: 李铭昕 <715557344@qq.com> * Upgrade hyperf packages to version `~3.1.0` (#5801) * Bumps `phpunit` to `10.x` (#5802) Co-authored-by: 李铭昕 <715557344@qq.com> * Remove redundant `setAccessible` methods (#5811) * Remove deprecated codes (#5812) * Removed the deprecated code for metric. (#5847) * Use `StrCache` instead of `Str` in special cases. (#5866) * [feat] Support buffer mechanism in standalone process of metric (#6030) Co-authored-by: 李铭昕 <715557344@qq.com> * Fix the bug that cannot stop the command from terminating gracefully (#6090) * Upgrade actions/checkout to v4 (#6159) * Adds `metric.enable_command_metric` switch (#6272) * Changed the `branch-alias` of all components to `3.1-dev`. (#6320) * update dependencies * Remove unused import --------- Co-authored-by: Deeka Wong <huangdijia@gmail.com> Co-authored-by: 李铭昕 <715557344@qq.com> Co-authored-by: yansongda <yansongda@users.noreply.github.com> Co-authored-by: Albert Chen <albert.cht@gmail.com>
1 parent c92e9fe commit df8f474

24 files changed

+2011
-1360
lines changed
 

‎composer.json

+12-11
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
],
1212
"description": "Drop-in replacement for the Hyperf Metric component.",
1313
"require": {
14-
"php": ">=8.0",
15-
"hyperf/codec": "^3.0",
16-
"hyperf/contract": "^3.0",
17-
"hyperf/engine": "^2.9",
18-
"hyperf/guzzle": "^3.0",
19-
"hyperf/support": "^3.0",
20-
"hyperf/utils": "^3.0",
14+
"php": ">=8.1",
15+
"hyperf/codec": "~3.1.0",
16+
"hyperf/contract": "~3.1.0",
17+
"hyperf/engine": "^2.3",
18+
"hyperf/guzzle": "~3.1.0",
19+
"hyperf/support": "~3.1.0",
20+
"hyperf/utils": "~3.1.0",
21+
"psr/container": "^1.0|^2.0",
2122
"promphp/prometheus_client_php": "^2.7",
22-
"psr/container": "^2.0",
2323
"psr/event-dispatcher": "^1.0",
2424
"psr/http-message": "^1.0|^2.0"
2525
},
@@ -44,13 +44,14 @@
4444
"swoole/ide-helper": "^5.0"
4545
},
4646
"suggest": {
47-
"slickdeals/statsd": "Required to use StatdD driver.",
4847
"influxdb/influxdb-php": "Required to use InfluxDB driver.",
4948
"hyperf/di": "Required to use annotations.",
5049
"hyperf/event": "Required to use listeners for default metrics.",
5150
"hyperf/process": "Required to use standalone process, or you have to roll your own",
5251
"hyperf/retry": "Required to use back-off retry implementation.",
53-
"hyperf/http-server": "Required to capture routes in middleware."
52+
"hyperf/http-server": "Required to capture routes in middleware.",
53+
"promphp/prometheus_client_php": "Required to use Prometheus driver.(2.2.*)",
54+
"slickdeals/statsd": "Required to use StatdD driver."
5455
},
5556
"autoload": {
5657
"psr-4": {
@@ -80,7 +81,7 @@
8081
},
8182
"extra": {
8283
"branch-alias": {
83-
"dev-master": "3.0-dev"
84+
"dev-master": "3.1-dev"
8485
},
8586
"hyperf": {
8687
"config": "Hyperf\\Metric\\ConfigProvider"

‎composer.lock

+1,598-1,254
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎publish/metric.php

+4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
'default' => env('METRIC_DRIVER', 'prometheus'),
1919
'use_standalone_process' => env('METRIC_USE_STANDALONE_PROCESS', false),
2020
'enable_default_metric' => env('METRIC_ENABLE_DEFAULT_METRIC', true),
21+
'enable_command_metric' => env('METRIC_ENABLE_COMMAND_METRIC', true),
2122
'default_metric_interval' => env('DEFAULT_METRIC_INTERVAL', 5),
23+
// only available when use_standalone_process is true
24+
'buffer_interval' => env('METRIC_BUFFER_INTERVAL', 5),
25+
'buffer_size' => env('METRIC_BUFFER_SIZE', 200),
2226
'metric' => [
2327
'prometheus' => [
2428
'driver' => Hyperf\Metric\Adapter\Prometheus\MetricFactory::class,

‎src/Adapter/InfluxDB/MetricFactory.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
use Hyperf\Metric\Contract\GaugeInterface;
2323
use Hyperf\Metric\Contract\HistogramInterface;
2424
use Hyperf\Metric\Contract\MetricFactoryInterface;
25-
use Hyperf\Stringable\Str;
25+
use Hyperf\Stringable\StrCache;
2626
use InfluxDB\Client;
2727
use InfluxDB\Database;
2828
use InfluxDB\Database\RetentionPolicy;
@@ -129,6 +129,6 @@ protected function createPoint(Sample $sample): Point
129129
private function getNamespace(): string
130130
{
131131
$name = $this->config->get("metric.metric.{$this->name}.namespace");
132-
return preg_replace('#[^a-zA-Z0-9:_]#', '_', Str::snake($name));
132+
return preg_replace('#[^a-zA-Z0-9:_]#', '_', StrCache::snake($name));
133133
}
134134
}

‎src/Adapter/Prometheus/MetricFactory.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Hyperf\Metric\Exception\RuntimeException;
3131
use Hyperf\Metric\MetricFactoryPicker;
3232
use Hyperf\Stringable\Str;
33+
use Hyperf\Stringable\StrCache;
3334
use Hyperf\Support\Network;
3435
use Prometheus\CollectorRegistry;
3536
use Prometheus\Exception\MetricsRegistrationException;
@@ -126,6 +127,10 @@ protected function scrapeHandle(): void
126127
}
127128
}
128129

130+
if (CoordinatorManager::until(Coord::WORKER_EXIT)->isClosing()) {
131+
return;
132+
}
133+
129134
$server = $this->factory->make($host, (int) $port);
130135

131136
Coroutine::create(static function () use ($server) {
@@ -171,7 +176,7 @@ protected function customHandle(): void
171176
private function getNamespace(): string
172177
{
173178
$name = $this->config->get("metric.metric.{$this->name}.namespace");
174-
return preg_replace('#[^a-zA-Z0-9:_]#', '_', Str::snake($name));
179+
return preg_replace('#[^a-zA-Z0-9:_]#', '_', StrCache::snake($name));
175180
}
176181

177182
private function getUri(string $address, string $job): string

‎src/Adapter/Prometheus/Redis.php

+3-19
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,9 @@
2222

2323
class Redis implements Adapter
2424
{
25-
/**
26-
* @deprecated since 3.1, use `$metricGatherKeySuffix` instead
27-
*/
28-
public const PROMETHEUS_METRIC_KEYS_SUFFIX = '_METRIC_KEYS';
25+
private static string $metricGatherKeySuffix = ':metric_keys';
2926

30-
/**
31-
* @notice TODO: since 3.1, default value will be changed to ':metric_keys'
32-
*/
33-
private static string $metricGatherKeySuffix = '_METRIC_KEYS';
34-
35-
/**
36-
* @notice TODO: since 3.1, default value will be changed to 'prometheus:' and should be non static
37-
*/
38-
private static string $prefix = 'PROMETHEUS_';
27+
private static string $prefix = 'prometheus:';
3928

4029
/**
4130
* @param \Redis $redis
@@ -354,12 +343,7 @@ protected function collectSamples(string $metricType): array
354343

355344
protected function toMetricKey(array $data): string
356345
{
357-
// TODO: This is a hack, we should remove it since v3.1.
358-
if (! str_ends_with(self::$prefix, ':')) {
359-
$prefix = self::$prefix . ':';
360-
}
361-
362-
return ($prefix ?? self::$prefix) . implode(':', [$data['type'] ?? '', $data['name'] ?? '']) . $this->getRedisTag($data['type'] ?? '');
346+
return self::$prefix . implode(':', [$data['type'] ?? '', $data['name'] ?? '']) . $this->getRedisTag($data['type'] ?? '');
363347
}
364348

365349
protected function getMetricGatherKey(string $metricType): string

‎src/Adapter/Prometheus/RedisStorageFactory.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ public function __invoke(ContainerInterface $container): Redis
2929
$redisFactory = $container->get(RedisFactory::class);
3030

3131
Redis::setPrefix($config->get('metric.metric.prometheus.redis_prefix', $config->get('app_name', 'skeleton')));
32-
// TODO: since 3.1, default value will be changed to ':metric_keys'
33-
Redis::setMetricGatherKeySuffix($config->get('metric.metric.prometheus.redis_gather_key_suffix', '_METRIC_KEYS'));
32+
Redis::setMetricGatherKeySuffix($config->get('metric.metric.prometheus.redis_gather_key_suffix', ':metric_keys'));
3433

3534
return new Redis($redisFactory->get($config->get('metric.metric.prometheus.redis_config', 'default')));
3635
}

‎src/Adapter/RemoteProxy/Counter.php

+6-5
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
*/
1212
namespace Hyperf\Metric\Adapter\RemoteProxy;
1313

14+
use Hyperf\Context\ApplicationContext;
1415
use Hyperf\Metric\Contract\CounterInterface;
15-
use Hyperf\Process\ProcessCollector;
16+
use Hyperf\Metric\Contract\MetricCollectorInterface;
1617

1718
class Counter implements CounterInterface
1819
{
19-
protected const TARGET_PROCESS_NAME = 'metric';
20-
2120
/**
2221
* @var string[]
2322
*/
@@ -38,7 +37,9 @@ public function with(string ...$labelValues): static
3837
public function add(int $delta): void
3938
{
4039
$this->delta = $delta;
41-
$process = ProcessCollector::get(static::TARGET_PROCESS_NAME)[0];
42-
$process->write(serialize($this));
40+
41+
ApplicationContext::getContainer()
42+
->get(MetricCollectorInterface::class)
43+
->add($this);
4344
}
4445
}

‎src/Adapter/RemoteProxy/Gauge.php

+10-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
*/
1212
namespace Hyperf\Metric\Adapter\RemoteProxy;
1313

14+
use Hyperf\Context\ApplicationContext;
1415
use Hyperf\Metric\Contract\GaugeInterface;
15-
use Hyperf\Process\ProcessCollector;
16+
use Hyperf\Metric\Contract\MetricCollectorInterface;
1617

1718
class Gauge implements GaugeInterface
1819
{
19-
protected const TARGET_PROCESS_NAME = 'metric';
20-
2120
/**
2221
* @var string[]
2322
*/
@@ -41,15 +40,19 @@ public function set(float $value): void
4140
{
4241
$this->value = $value;
4342
$this->delta = null;
44-
$process = ProcessCollector::get(static::TARGET_PROCESS_NAME)[0];
45-
$process->write(serialize($this));
43+
44+
ApplicationContext::getContainer()
45+
->get(MetricCollectorInterface::class)
46+
->add($this);
4647
}
4748

4849
public function add(float $delta): void
4950
{
5051
$this->delta = $delta;
5152
$this->value = null;
52-
$process = ProcessCollector::get(static::TARGET_PROCESS_NAME)[0];
53-
$process->write(serialize($this));
53+
54+
ApplicationContext::getContainer()
55+
->get(MetricCollectorInterface::class)
56+
->add($this);
5457
}
5558
}

‎src/Adapter/RemoteProxy/Histogram.php

+6-5
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
*/
1212
namespace Hyperf\Metric\Adapter\RemoteProxy;
1313

14+
use Hyperf\Context\ApplicationContext;
1415
use Hyperf\Metric\Contract\HistogramInterface;
15-
use Hyperf\Process\ProcessCollector;
16+
use Hyperf\Metric\Contract\MetricCollectorInterface;
1617

1718
class Histogram implements HistogramInterface
1819
{
19-
protected const TARGET_PROCESS_NAME = 'metric';
20-
2120
/**
2221
* @var string[]
2322
*/
@@ -38,7 +37,9 @@ public function with(string ...$labelValues): static
3837
public function put(float $sample): void
3938
{
4039
$this->sample = $sample;
41-
$process = ProcessCollector::get(static::TARGET_PROCESS_NAME)[0];
42-
$process->write(serialize($this));
40+
41+
ApplicationContext::getContainer()
42+
->get(MetricCollectorInterface::class)
43+
->add($this);
4344
}
4445
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact group@hyperf.io
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace Hyperf\Metric\Adapter\RemoteProxy;
13+
14+
use Hyperf\Metric\Contract\MetricCollectorInterface;
15+
use Hyperf\Process\ProcessCollector;
16+
17+
class MetricCollector implements MetricCollectorInterface
18+
{
19+
protected const TARGET_PROCESS_NAME = 'metric';
20+
21+
protected array $buffer = [];
22+
23+
public function __construct(
24+
protected int $bufferSize = 200
25+
) {
26+
}
27+
28+
public function add(object $data): void
29+
{
30+
$this->buffer[] = $data;
31+
32+
if (count($this->buffer) >= $this->bufferSize) {
33+
$this->flush();
34+
}
35+
}
36+
37+
public function flush(): void
38+
{
39+
$process = ProcessCollector::get(static::TARGET_PROCESS_NAME)[0];
40+
$buffer = $this->buffer;
41+
$this->buffer = [];
42+
$process->write(serialize($buffer));
43+
}
44+
45+
public function getBuffer(): array
46+
{
47+
return $this->buffer;
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact group@hyperf.io
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace Hyperf\Metric\Adapter\RemoteProxy;
13+
14+
use Hyperf\Contract\ConfigInterface;
15+
use Hyperf\Metric\Contract\MetricCollectorInterface;
16+
use Psr\Container\ContainerExceptionInterface;
17+
use Psr\Container\ContainerInterface;
18+
use Psr\Container\NotFoundExceptionInterface;
19+
20+
class MetricCollectorFactory
21+
{
22+
/**
23+
* @throws ContainerExceptionInterface
24+
* @throws NotFoundExceptionInterface
25+
*/
26+
public function __invoke(ContainerInterface $container): MetricCollectorInterface
27+
{
28+
$config = $container->get(ConfigInterface::class);
29+
30+
return new MetricCollector(
31+
(int) $config->get('metric.buffer_size', 200)
32+
);
33+
}
34+
}

‎src/ConfigProvider.php

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
use Hyperf\Metric\Contract\MetricFactoryInterface;
2222
use Hyperf\Metric\Contract\SqlSanitizerInterface;
2323
use Hyperf\Metric\Listener\DbQueryExecutedMetricListener;
24+
use Hyperf\Metric\Adapter\RemoteProxy\MetricCollectorFactory;
25+
use Hyperf\Metric\Contract\MetricCollectorInterface;
26+
use Hyperf\Metric\Listener\MetricBufferWatcher;
2427
use Hyperf\Metric\Listener\OnBeforeHandle;
2528
use Hyperf\Metric\Listener\OnCoroutineServerStart;
2629
use Hyperf\Metric\Listener\OnMetricFactoryReady;
@@ -45,6 +48,7 @@ public function __invoke(): array
4548
Connection::class => StatsDConnection::class,
4649
DriverInterface::class => Guzzle::class,
4750
SqlSanitizerInterface::class => SqlSanitizer::class,
51+
MetricCollectorInterface::class => MetricCollectorFactory::class,
4852
],
4953
'aspects' => [
5054
CounterAnnotationAspect::class,
@@ -68,6 +72,7 @@ public function __invoke(): array
6872
OnBeforeHandle::class,
6973
OnWorkerStart::class,
7074
OnCoroutineServerStart::class,
75+
MetricBufferWatcher::class,
7176
],
7277
'middlewares' => [
7378
MetricMiddleware::class,
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact group@hyperf.io
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace Hyperf\Metric\Contract;
13+
14+
interface MetricCollectorInterface
15+
{
16+
public function add(object $data): void;
17+
18+
public function flush(): void;
19+
}

‎src/Listener/MetricBufferWatcher.php

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact group@hyperf.io
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace Hyperf\Metric\Listener;
13+
14+
use Hyperf\Contract\ConfigInterface;
15+
use Hyperf\Coordinator\Constants;
16+
use Hyperf\Coordinator\CoordinatorManager;
17+
use Hyperf\Coordinator\Timer;
18+
use Hyperf\Coroutine\Coroutine;
19+
use Hyperf\Event\Contract\ListenerInterface;
20+
use Hyperf\Framework\Event\BeforeWorkerStart;
21+
use Hyperf\Metric\Contract\MetricCollectorInterface;
22+
use Psr\Container\ContainerInterface;
23+
24+
/**
25+
* Collect and handle metrics before worker start.
26+
* Only used for swoole process mode.
27+
*/
28+
class MetricBufferWatcher implements ListenerInterface
29+
{
30+
private ConfigInterface $config;
31+
32+
private MetricCollectorInterface $collector;
33+
34+
private Timer $timer;
35+
36+
public function __construct(protected ContainerInterface $container)
37+
{
38+
$this->config = $container->get(ConfigInterface::class);
39+
$this->collector = $container->get(MetricCollectorInterface::class);
40+
$this->timer = new Timer();
41+
}
42+
43+
/**
44+
* @return string[] returns the events that you want to listen
45+
*/
46+
public function listen(): array
47+
{
48+
return [
49+
BeforeWorkerStart::class,
50+
];
51+
}
52+
53+
/**
54+
* Handle the Event when the event is triggered, all listeners will
55+
* complete before the event is returned to the EventDispatcher.
56+
*/
57+
public function process(object $event): void
58+
{
59+
if ($event->workerId === null) {
60+
return;
61+
}
62+
63+
/*
64+
* Only start buffer watcher in standalone process mode
65+
*/
66+
if (! $this->config->get('metric.use_standalone_process', true)) {
67+
return;
68+
}
69+
70+
$timerInterval = $this->config->get('metric.buffer_interval', 5);
71+
$timerId = $this->timer->tick($timerInterval, function () {
72+
$this->collector->flush();
73+
});
74+
// Clean up timer on worker exit;
75+
Coroutine::create(function () use ($timerId) {
76+
CoordinatorManager::until(Constants::WORKER_EXIT)->yield();
77+
$this->timer->clear($timerId);
78+
});
79+
}
80+
}

‎src/Listener/OnBeforeHandle.php

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public function process(object $event): void
6363
return;
6464
}
6565

66+
if (! $this->config->get('metric.enable_command_metric', true)) {
67+
return;
68+
}
69+
6670
MetricFactoryPicker::$isCommand = true;
6771

6872
if ($this->config->get('metric.use_standalone_process', true)) {

‎src/Listener/OnPipeMessage.php

+42-28
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@
1818
use Hyperf\Metric\Adapter\RemoteProxy\Histogram;
1919
use Hyperf\Metric\Contract\MetricFactoryInterface;
2020
use Hyperf\Process\Event\PipeMessage;
21-
22-
use function Hyperf\Support\make;
21+
use Psr\Container\ContainerInterface;
2322

2423
/**
2524
* Receives messages in metric process.
2625
*/
2726
class OnPipeMessage implements ListenerInterface
2827
{
28+
protected MetricFactoryInterface $factory;
29+
30+
public function __construct(protected ContainerInterface $container)
31+
{
32+
}
33+
2934
/**
3035
* @return string[] returns the events that you want to listen
3136
*/
@@ -42,32 +47,41 @@ public function listen(): array
4247
*/
4348
public function process(object $event): void
4449
{
45-
Coroutine::create(function () use ($event) {
46-
if ($event instanceof PipeMessage) {
47-
$factory = make(MetricFactoryInterface::class);
48-
$inner = $event->data;
49-
switch (true) {
50-
case $inner instanceof Counter:
51-
$counter = $factory->makeCounter($inner->name, $inner->labelNames);
52-
$counter->with(...$inner->labelValues)->add($inner->delta);
53-
break;
54-
case $inner instanceof Gauge:
55-
$gauge = $factory->makeGauge($inner->name, $inner->labelNames);
56-
if (isset($inner->value)) {
57-
$gauge->with(...$inner->labelValues)->set($inner->value);
58-
} else {
59-
$gauge->with(...$inner->labelValues)->add($inner->delta);
60-
}
61-
break;
62-
case $inner instanceof Histogram:
63-
$histogram = $factory->makeHistogram($inner->name, $inner->labelNames);
64-
$histogram->with(...$inner->labelValues)->put($inner->sample);
65-
break;
66-
default:
67-
// Nothing to do
68-
break;
50+
if (! $event instanceof PipeMessage) {
51+
return;
52+
}
53+
54+
$this->factory = $this->container->get(MetricFactoryInterface::class);
55+
$inner = ! is_array($event->data) ? [$event->data] : $event->data;
56+
foreach ($inner as $data) {
57+
Coroutine::create(function () use ($data) {
58+
$this->processData($data);
59+
});
60+
}
61+
}
62+
63+
protected function processData(object $data): void
64+
{
65+
switch (true) {
66+
case $data instanceof Counter:
67+
$counter = $this->factory->makeCounter($data->name, $data->labelNames);
68+
$counter->with(...$data->labelValues)->add($data->delta);
69+
break;
70+
case $data instanceof Gauge:
71+
$gauge = $this->factory->makeGauge($data->name, $data->labelNames);
72+
if (isset($data->value)) {
73+
$gauge->with(...$data->labelValues)->set($data->value);
74+
} else {
75+
$gauge->with(...$data->labelValues)->add($data->delta);
6976
}
70-
}
71-
});
77+
break;
78+
case $data instanceof Histogram:
79+
$histogram = $this->factory->makeHistogram($data->name, $data->labelNames);
80+
$histogram->with(...$data->labelValues)->put($data->sample);
81+
break;
82+
default:
83+
// Nothing to do
84+
break;
85+
}
7286
}
7387
}

‎tests/Adapter/Prometheus/RedisStorageFactoryTest.php

+34-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Hyperf\Redis\RedisFactory;
1919
use Hyperf\Redis\RedisProxy;
2020
use Mockery;
21+
use PHPUnit\Framework\Attributes\CoversNothing;
2122
use PHPUnit\Framework\TestCase;
2223
use Psr\Container\ContainerInterface;
2324
use ReflectionProperty;
@@ -26,6 +27,7 @@
2627
* @internal
2728
* @coversNothing
2829
*/
30+
#[CoversNothing]
2931
class RedisStorageFactoryTest extends TestCase
3032
{
3133
protected string $prePrefix;
@@ -37,10 +39,7 @@ protected function setUp(): void
3739
parent::setUp();
3840

3941
$prefixProperty = new ReflectionProperty(Redis::class, 'prefix');
40-
$prefixProperty->setAccessible(true);
41-
4242
$metricGatherKeySuffix = new ReflectionProperty(Redis::class, 'metricGatherKeySuffix');
43-
$metricGatherKeySuffix->setAccessible(true);
4443

4544
$this->prePrefix = $prefixProperty->getDefaultValue();
4645
$this->preMetricGatherKeySuffix = $metricGatherKeySuffix->getDefaultValue();
@@ -69,14 +68,12 @@ public function testEmptyMetricRedisConfig()
6968
$redis = $factory($container);
7069

7170
$prefixProperty = new ReflectionProperty(Redis::class, 'prefix');
72-
$prefixProperty->setAccessible(true);
7371

7472
$metricGatherKeySuffixProperty = new ReflectionProperty(Redis::class, 'metricGatherKeySuffix');
75-
$metricGatherKeySuffixProperty->setAccessible(true);
7673

7774
self::assertInstanceOf(Redis::class, $redis);
7875
self::assertEquals('skeleton', $prefixProperty->getValue($redis));
79-
self::assertEquals('_METRIC_KEYS', $metricGatherKeySuffixProperty->getValue($redis));
76+
self::assertEquals(':metric_keys', $metricGatherKeySuffixProperty->getValue($redis));
8077
}
8178

8279
public function testNewConfig()
@@ -102,13 +99,42 @@ public function testNewConfig()
10299
$redis = $factory($container);
103100

104101
$prefixProperty = new ReflectionProperty(Redis::class, 'prefix');
105-
$prefixProperty->setAccessible(true);
106102

107103
$metricGatherKeySuffixProperty = new ReflectionProperty(Redis::class, 'metricGatherKeySuffix');
108-
$metricGatherKeySuffixProperty->setAccessible(true);
109104

110105
self::assertInstanceOf(Redis::class, $redis);
111106
self::assertEquals('prometheus:', $prefixProperty->getValue($redis));
112107
self::assertEquals(':metric_keys', $metricGatherKeySuffixProperty->getValue($redis));
113108
}
109+
110+
public function testCustomConfig()
111+
{
112+
$redisFactory = Mockery::mock(RedisFactory::class);
113+
$redisFactory->shouldReceive('get')->with('custom')->andReturn(Mockery::mock(RedisProxy::class));
114+
115+
$container = Mockery::mock(ContainerInterface::class);
116+
$container->shouldReceive('get')->with(ConfigInterface::class)->andReturn(new Config([
117+
'metric' => [
118+
'metric' => [
119+
'prometheus' => [
120+
'redis_config' => 'custom',
121+
'redis_prefix' => 'custom:',
122+
'redis_gather_key_suffix' => ':custom',
123+
],
124+
],
125+
],
126+
]));
127+
$container->shouldReceive('get')->with(RedisFactory::class)->andReturn($redisFactory);
128+
129+
$factory = new RedisStorageFactory();
130+
$redis = $factory($container);
131+
132+
$prefixProperty = new ReflectionProperty(Redis::class, 'prefix');
133+
134+
$metricGatherKeySuffixProperty = new ReflectionProperty(Redis::class, 'metricGatherKeySuffix');
135+
136+
self::assertInstanceOf(Redis::class, $redis);
137+
self::assertEquals('custom:', $prefixProperty->getValue($redis));
138+
self::assertEquals(':custom', $metricGatherKeySuffixProperty->getValue($redis));
139+
}
114140
}

‎tests/Adapter/Prometheus/RedisTest.php

+3-16
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Hyperf\Metric\Adapter\Prometheus\Redis;
1515
use Mockery;
16+
use PHPUnit\Framework\Attributes\CoversNothing;
1617
use PHPUnit\Framework\TestCase;
1718
use Prometheus\Counter;
1819
use Prometheus\Histogram;
@@ -23,6 +24,7 @@
2324
* @internal
2425
* @coversNothing
2526
*/
27+
#[CoversNothing]
2628
class RedisTest extends TestCase
2729
{
2830
protected string $prePrefix;
@@ -34,10 +36,7 @@ protected function setUp(): void
3436
parent::setUp();
3537

3638
$prefixProperty = new ReflectionProperty(Redis::class, 'prefix');
37-
$prefixProperty->setAccessible(true);
38-
3939
$metricGatherKeySuffix = new ReflectionProperty(Redis::class, 'metricGatherKeySuffix');
40-
$metricGatherKeySuffix->setAccessible(true);
4140

4241
$this->prePrefix = $prefixProperty->getDefaultValue();
4342
$this->preMetricGatherKeySuffix = $metricGatherKeySuffix->getDefaultValue();
@@ -62,22 +61,14 @@ public function testToMetricKey()
6261

6362
Redis::setPrefix('prometheus:');
6463
$method = new ReflectionMethod(Redis::class, 'toMetricKey');
65-
$method->setAccessible(true);
6664
self::assertEquals('prometheus:counter:hyperf_metric{counter}', $method->invoke(new Redis(new \Redis()), $data));
67-
68-
// 兼容 < v3.1
69-
Redis::setPrefix('PROMETHEUS_');
70-
$method = new ReflectionMethod(Redis::class, 'toMetricKey');
71-
$method->setAccessible(true);
72-
self::assertEquals('PROMETHEUS_:counter:hyperf_metric{counter}', $method->invoke(new Redis(new \Redis()), $data));
7365
}
7466

7567
public function testGetMetricGatherKey()
7668
{
7769
$method = new ReflectionMethod(Redis::class, 'getMetricGatherKey');
78-
$method->setAccessible(true);
7970

80-
self::assertEquals('PROMETHEUS_counter_METRIC_KEYS{counter}', $method->invoke(new Redis(new \Redis()), Counter::TYPE));
71+
self::assertEquals('prometheus:counter:metric_keys{counter}', $method->invoke(new Redis(new \Redis()), Counter::TYPE));
8172
}
8273

8374
public function testCollectSamples()
@@ -105,7 +96,6 @@ public function testCollectSamples()
10596
);
10697

10798
$method = new ReflectionMethod(Redis::class, 'collectSamples');
108-
$method->setAccessible(true);
10999
$result = $method->invoke(new Redis($redis), Counter::TYPE);
110100

111101
self::assertEquals([
@@ -158,7 +148,6 @@ public function testCollectSamplesLabelNameNotMatch()
158148
);
159149

160150
$method = new ReflectionMethod(Redis::class, 'collectSamples');
161-
$method->setAccessible(true);
162151
$result = $method->invoke(new Redis($redis), Counter::TYPE);
163152

164153
self::assertEquals([
@@ -202,7 +191,6 @@ public function testCollectHistograms()
202191
);
203192

204193
$method = new ReflectionMethod(Redis::class, 'collectHistograms');
205-
$method->setAccessible(true);
206194
$result = $method->invoke(new Redis($redis), Histogram::TYPE);
207195

208196
self::assertEquals([
@@ -307,7 +295,6 @@ public function testCollectHistogramsLabelNotMatch()
307295
);
308296

309297
$method = new ReflectionMethod(Redis::class, 'collectHistograms');
310-
$method->setAccessible(true);
311298
$result = $method->invoke(new Redis($redis), Histogram::TYPE);
312299

313300
self::assertEquals([
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact group@hyperf.io
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace HyperfTest\Metric\Adapter\RemoteProxy;
13+
14+
use Hyperf\Metric\Adapter\RemoteProxy\MetricCollector;
15+
use Hyperf\Process\ProcessCollector;
16+
use Mockery;
17+
use PHPUnit\Framework\Attributes\CoversNothing;
18+
use PHPUnit\Framework\TestCase;
19+
use stdClass;
20+
use Swoole\Process;
21+
22+
/**
23+
* @internal
24+
* @coversNothing
25+
*/
26+
#[CoversNothing]
27+
class MetricCollectorTest extends TestCase
28+
{
29+
protected bool $processMocked = false;
30+
31+
protected function tearDown(): void
32+
{
33+
Mockery::close();
34+
}
35+
36+
public function testAddData()
37+
{
38+
$collector = new MetricCollector(100);
39+
40+
$this->assertSame(0, count($collector->getBuffer()));
41+
42+
$collector->add($data = new stdClass());
43+
44+
$this->assertSame(1, count($collector->getBuffer()));
45+
}
46+
47+
public function testFlush()
48+
{
49+
$this->mockProcessCollector();
50+
51+
$collector = new MetricCollector(100);
52+
$collector->add(new stdClass());
53+
$collector->flush();
54+
55+
$this->assertSame(0, count($collector->getBuffer()));
56+
}
57+
58+
public function testAddDataWithFlush()
59+
{
60+
$this->mockProcessCollector();
61+
62+
$collector = new MetricCollector(1);
63+
$collector->add(new stdClass());
64+
65+
$this->assertSame(0, count($collector->getBuffer()));
66+
}
67+
68+
protected function mockProcessCollector()
69+
{
70+
if ($this->processMocked) {
71+
return;
72+
}
73+
74+
$process = Mockery::mock(Process::class);
75+
$process->shouldReceive('write');
76+
77+
ProcessCollector::add('metric', $process);
78+
79+
$this->processMocked = true;
80+
}
81+
}

‎tests/Cases/MetricFactoryPickerTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
use Hyperf\Metric\MetricFactoryPicker;
2222
use Hyperf\Process\ProcessCollector;
2323
use Mockery;
24+
use PHPUnit\Framework\Attributes\CoversNothing;
2425
use PHPUnit\Framework\TestCase;
2526

2627
/**
2728
* @internal
2829
* @coversNothing
2930
*/
31+
#[CoversNothing]
3032
class MetricFactoryPickerTest extends TestCase
3133
{
3234
protected function tearDown(): void

‎tests/Cases/MetricFactoryTest.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,17 @@
1818
use Hyperf\Metric\Adapter\Prometheus\Constants;
1919
use Hyperf\Metric\Adapter\Prometheus\MetricFactory as PrometheusFactory;
2020
use Mockery;
21+
use PHPUnit\Framework\Attributes\CoversNothing;
2122
use PHPUnit\Framework\TestCase;
2223
use Prometheus\CollectorRegistry;
2324
use ReflectionClass;
2425
use ReflectionMethod;
2526

27+
/**
28+
* @internal
29+
* @coversNothing
30+
*/
31+
#[CoversNothing]
2632
/**
2733
* @internal
2834
* @coversNothing
@@ -55,7 +61,6 @@ public function testPrometheusGetUri()
5561
$p = new PrometheusFactory($config, $r, $c, $l, new ServerFactory($l));
5662
$ref = new ReflectionClass($p);
5763
$method = $ref->getMethod('getUri');
58-
$method->setAccessible(true);
5964
$this->assertStringContainsString('http://127.0.0.1/metrics/job/metric/ip/', $method->invokeArgs($p, ['127.0.0.1', 'metric']));
6065
$this->assertStringContainsString('https://127.0.0.1/metrics/job/metric/ip/', $method->invokeArgs($p, ['https://127.0.0.1', 'metric']));
6166
$this->assertStringContainsString('http://127.0.0.1:8080/metrics/job/metric/ip/', $method->invokeArgs($p, ['127.0.0.1:8080', 'metric']));
@@ -81,7 +86,6 @@ public function testGetNamespace()
8186
$l = Mockery::mock(StdoutLoggerInterface::class);
8287
$p = new PrometheusFactory($config, $r, $c, $l, new ServerFactory($l));
8388
$method = new ReflectionMethod(PrometheusFactory::class, 'getNamespace');
84-
$method->setAccessible(true);
8589
$this->assertEquals('hello__world_', $method->invoke($p));
8690
}
8791
}

‎tests/Cases/OnWorkerStartTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
use Hyperf\Metric\Contract\MetricFactoryInterface;
1919
use Hyperf\Metric\Listener\OnWorkerStart;
2020
use Mockery;
21+
use PHPUnit\Framework\Attributes\CoversNothing;
2122
use PHPUnit\Framework\TestCase;
2223
use Psr\EventDispatcher\EventDispatcherInterface;
2324

2425
/**
2526
* @internal
2627
* @coversNothing
2728
*/
29+
#[CoversNothing]
2830
class OnWorkerStartTest extends TestCase
2931
{
3032
protected function tearDown(): void

‎tests/Cases/TimerTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
use Hyperf\Metric\Contract\MetricFactoryInterface;
1818
use Hyperf\Metric\Timer;
1919
use Mockery;
20+
use PHPUnit\Framework\Attributes\CoversNothing;
2021
use PHPUnit\Framework\TestCase;
2122

2223
/**
2324
* @internal
2425
* @coversNothing
2526
*/
27+
#[CoversNothing]
2628
class TimerTest extends TestCase
2729
{
2830
protected function tearDown(): void

0 commit comments

Comments
 (0)
Please sign in to comment.