Skip to content

Commit ffeba7a

Browse files
committed
allow for metric-only instrumentation, fix for duplicate instrument registration
1 parent 5cc5758 commit ffeba7a

File tree

2 files changed

+92
-10
lines changed

2 files changed

+92
-10
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use OpenTelemetry\SDK\Metrics\Data\Temporality;
6+
use OpenTelemetry\SDK\Metrics\MeterProvider;
7+
use OpenTelemetry\SDK\Metrics\MetricExporter\ConsoleMetricExporter;
8+
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
9+
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
10+
use OpenTelemetry\SDK\Sdk;
11+
use Psr\Http\Message\ResponseInterface;
12+
use React\Http\Browser;
13+
use React\Http\Message\Request;
14+
use React\Http\Message\ResponseException;
15+
16+
require_once dirname(__DIR__) . '/vendor/autoload.php';
17+
18+
$exporter = new ConsoleMetricExporter(Temporality::CUMULATIVE);
19+
20+
$meterProvider = MeterProvider::builder()
21+
->addReader(new ExportingReader($exporter))
22+
->setResource(ResourceInfoFactory::emptyResource())
23+
->build();
24+
25+
Sdk::builder()
26+
->setMeterProvider($meterProvider)
27+
->setAutoShutdown(true)
28+
->buildAndRegisterGlobal();
29+
30+
try {
31+
$browser = new Browser();
32+
33+
$requests = [
34+
new Request('GET', 'https://postman-echo.com/get'),
35+
new Request('GET', 'https://postman-echo.com/stream/33554432'),
36+
new Request('POST', 'https://postman-echo.com/post', ['Content-Type' => 'application/json'], '{}'),
37+
new Request('CUSTOM', 'http://postman-echo.com:443/get'),
38+
new Request('GET', 'unknown://postman-echo.com/get'),
39+
new Request('GET', 'https://postman-echo.com/delay/2'),
40+
];
41+
42+
foreach ($requests as $request) {
43+
$browser
44+
->request($request->getMethod(), $request->getUri())
45+
->then(function (ResponseInterface $response) use ($request) {
46+
echo sprintf(
47+
'[HTTP/%s %d %s] %s%s',
48+
$response->getProtocolVersion(),
49+
$response->getStatusCode(),
50+
$response->getReasonPhrase(),
51+
$request->getUri(),
52+
PHP_EOL
53+
);
54+
}, function (Throwable $t) use ($request) {
55+
if (is_a($t, ResponseException::class)) {
56+
$response = $t->getResponse();
57+
echo sprintf(
58+
'[HTTP/%s %d %s] %s%s',
59+
$response->getProtocolVersion(),
60+
$response->getStatusCode(),
61+
$response->getReasonPhrase(),
62+
$request->getUri(),
63+
PHP_EOL
64+
);
65+
} else {
66+
echo sprintf(
67+
'[%d: %s] %s%s',
68+
$t->getCode(),
69+
$t->getMessage(),
70+
$request->getUri(),
71+
PHP_EOL
72+
);
73+
}
74+
});
75+
}
76+
} finally {
77+
$meterProvider->forceFlush();
78+
}

src/Instrumentation/ReactPHP/src/ReactPHPInstrumentation.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use OpenTelemetry\API\Common\Time\ClockInterface;
1111
use OpenTelemetry\API\Globals;
1212
use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
13+
use OpenTelemetry\API\Metrics\Noop\NoopHistogram;
1314
use OpenTelemetry\API\Trace\Span;
1415
use OpenTelemetry\API\Trace\SpanKind;
1516
use OpenTelemetry\API\Trace\StatusCode;
@@ -83,6 +84,9 @@ class ReactPHPInstrumentation
8384

8485
public static function register(): void
8586
{
87+
/** @var \OpenTelemetry\API\Metrics\HistogramInterface|null */
88+
static $histogram;
89+
8690
$instrumentation = new CachedInstrumentation(
8791
self::INSTRUMENTATION_LIBRARY_NAME,
8892
InstalledVersions::getPrettyVersion(self::COMPOSER_NAME),
@@ -159,7 +163,7 @@ public static function register(): void
159163

160164
return [$request];
161165
},
162-
post: static function (Transaction $transaction, array $params, PromiseInterface $promise) use ($instrumentation): PromiseInterface {
166+
post: static function (Transaction $transaction, array $params, PromiseInterface $promise) use (&$histogram, $instrumentation): PromiseInterface {
163167
$scope = Context::storage()->scope();
164168
$scope?->detach();
165169

@@ -169,26 +173,26 @@ public static function register(): void
169173

170174
$span = Span::fromContext($scope->context());
171175

172-
if (!$span->isRecording()) {
173-
return $promise;
174-
}
175-
176176
//https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#http-client
177-
$requestDurationHistogram = $instrumentation->meter()->createHistogram(
177+
$histogram ??= $instrumentation->meter()->createHistogram(
178178
'http.client.request.duration',
179179
's',
180180
'Duration of HTTP client requests.',
181181
['ExplicitBucketBoundaries' => [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10]]
182182
);
183183

184+
if (!$span->isRecording() && is_a($histogram, NoopHistogram::class)) {
185+
return $promise;
186+
}
187+
184188
/** @var array{'http.request.method':non-empty-string|null,'server.address':non-empty-string,'server.port':int} $requestMeta */
185189
$requestMeta = $scope->offsetGet('requestMeta');
186190
$requestMeta['http.request.method'] ??= '_OTHER';
187191
/** @var int $requestStart */
188192
$requestStart = $scope->offsetGet('requestStart');
189193

190194
return $promise->then(
191-
onFulfilled: function (ResponseInterface $response) use ($requestDurationHistogram, $requestMeta, $requestStart, $span) {
195+
onFulfilled: function (ResponseInterface $response) use ($histogram, $requestMeta, $requestStart, $span) {
192196
$requestEnd = Clock::getDefault()->now();
193197
/** @var array{'http.response.status_code':int,'network.protocol.version':non-empty-string,'error.type'?:non-empty-string} $responseMeta */
194198
$responseMeta = [
@@ -218,14 +222,14 @@ public static function register(): void
218222

219223
$span->end($requestEnd);
220224

221-
$requestDurationHistogram->record(
225+
$histogram->record(
222226
(float) (($requestEnd - $requestStart) / ClockInterface::NANOS_PER_SECOND),
223227
array_merge($requestMeta, $responseMeta)
224228
);
225229

226230
return $response;
227231
},
228-
onRejected: function (Throwable $t) use ($requestDurationHistogram, $requestMeta, $requestStart, $span) {
232+
onRejected: function (Throwable $t) use ($histogram, $requestMeta, $requestStart, $span) {
229233
$requestEnd = Clock::getDefault()->now();
230234
$span->recordException($t);
231235
if (is_a($t, ResponseException::class)) {
@@ -262,7 +266,7 @@ public static function register(): void
262266

263267
$span->end($requestEnd);
264268

265-
$requestDurationHistogram->record(
269+
$histogram->record(
266270
(float) (($requestEnd - $requestStart) / ClockInterface::NANOS_PER_SECOND),
267271
array_merge($requestMeta, $responseMeta)
268272
);

0 commit comments

Comments
 (0)