I’m working on a library that uses the OpenTelemetry PHP SDK, and I ran into some issues while trying to test metrics. The way the OTel SDK is set up—using global state, _register files, Composer, and autoload—made it tricky to see the metrics output. I needed the metrics to show up in the console for debugging instead of being sent off to some remote system.
Figuring out how to tweak things to get what I needed was a bit of a challenge, but I managed to find a way to make it work for local testing and debugging. If you’re in a similar situation, you might need to get creative with how you configure the SDK.
Here is the code:
<?php
use OpenTelemetry\API\Common\Time\Clock;
use OpenTelemetry\API\Globals;
use OpenTelemetry\API\Logs\NoopEventLoggerProvider;
use OpenTelemetry\API\Logs\NoopLoggerProvider;
use OpenTelemetry\API\Trace\NoopTracerProvider;
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
use OpenTelemetry\SDK\Common\Attribute\Attributes;
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\AllExemplarFilter;
use OpenTelemetry\SDK\Metrics\MeterProvider;
use OpenTelemetry\SDK\Metrics\MetricExporter\ConsoleMetricExporter;
use OpenTelemetry\SDK\Metrics\MetricFactory\StreamFactory;
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
use OpenTelemetry\SDK\Metrics\StalenessHandler\NoopStalenessHandlerFactory;
use OpenTelemetry\SDK\Metrics\View\CriteriaViewRegistry;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
$consoleExporter = new ConsoleMetricExporter();
$metricReader = new ExportingReader($consoleExporter);
// create console exporting metter provider
$meterProvider = new MeterProvider(
null,
ResourceInfoFactory::emptyResource(),
Clock::getDefault(),
Attributes::factory(),
new InstrumentationScopeFactory(Attributes::factory()),
[$metricReader],
new CriteriaViewRegistry(),
new AllExemplarFilter(),
new NoopStalenessHandlerFactory(),
new StreamFactory(),
Configurator::meter(),
);
$tracerProvider = new NoopTracerProvider();
$loggerProvider = new NoopLoggerProvider();
$eventLoggerProvider = new NoopEventLoggerProvider();
$textMapPropagator = new NoopTextMapPropagator();
$g = new Globals(
$tracerProvider,
$meterProvider,
$loggerProvider,
$eventLoggerProvider,
$textMapPropagator
);
$ref = new \ReflectionClass(Globals::class);
$ref->setStaticPropertyValue('globals', $g);
// then this will return prepared meter provider that is in this case outputting everything to the console.
Globals::meterProvider()
ob_start();
// test code
$content = ob_get_clean();
You can use similar approach to replace other parts like TraceProvider
or LoggerProvider
.
I hope this will save you some time 🙂
Leave a Reply