Automatic Instrumentation
Automatic instrumentation with PHP requires at least PHP 8.0, and the OpenTelemetry PHP extension. The extension enables registering observer functions (as PHP code) against classes and methods, and executing those functions before and after the observed method runs.
Important
Installing the OpenTelemetry extension by itself will not generate traces. You must also install the SDK and one or more instrumentation packages for the frameworks and libraries that you are using, or alternatively write your own.
You also must use composer autoloading, as this is the mechanism all auto-instrumentation packages use to register themselves.
Example
<?php
use OpenTelemetry\API\Common\Instrumentation\CachedInstrumentation;
use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\Context\Context;
require 'vendor/autoload.php';
class DemoClass
{
public function run(): void
{
echo 'Hello, world';
}
}
OpenTelemetry\Instrumentation\hook(
class: DemoClass::class,
function: 'run',
pre: static function (DemoClass $demo, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
static $instrumentation;
$instrumentation ??= new CachedInstrumentation('example');
$span = $instrumentation->tracer()->spanBuilder('democlass-run')->startSpan();
Context::storage()->attach($span->storeInContext(Context::getCurrent()));
},
post: static function (DemoClass $demo, array $params, $returnValue, ?Throwable $exception) {
$scope = Context::storage()->scope();
$scope->detach();
$span = Span::fromContext($scope->context());
if ($exception) {
$span->recordException($exception);
$span->setStatus(StatusCode::STATUS_ERROR);
}
$span->end();
}
);
$demo = new DemoClass();
$demo->run();
Here, we provide pre
and post
functions, which are executed before and after
DemoClass::run
. The pre
function starts and activates a span, and the post
function ends it. If an exception was thrown by DemoClass::run()
, the post
function will record it, without affecting exception propagation.
Installation
The extension can be installed via pecl, pickle or php-extension-installer (docker specific). There are also packaged versions of the extension available for some Linux package managers.
Linux packages
RPM and APK packages are provided by the following:
- Remi repository - RPM
- Alpine Linux - APK (currently in the testing branch)
#this example is for CentOS 7. The PHP version can be changed by
#enabling remi-<version>, eg "yum config-manager --enable remi-php83"
yum update -y
yum install -y epel-release yum-utils
yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum-config-manager --enable remi-php81
yum install -y php php-pecl-opentelemetry
php --ri opentelemetry
#At the time of writing, PHP 8.1 was the default PHP version. You may need to
#change "php81" if the default changes. You can alternatively choose a PHP
#version with "apk add php<version>", eg "apk add php83".
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
apk add php php81-pecl-opentelemetry@testing
php --ri opentelemetry
PECL
Setup development environment. Installing from source requires proper development environment and some dependencies:
sudo apt-get install gcc make autoconf
brew install gcc make autoconf
Build/install the extension. With your environment set up you can install the extension:
pecl install opentelemetry
php pickle.phar install opentelemetry
install-php-extensions opentelemetry
Add the extension to your
php.ini
file:[opentelemetry] extension=opentelemetry.so
Verify that the extension is installed and enabled:
php -m | grep opentelemetry
Zero-code configuration for automatic instrumentation
When used in conjunction with the OpenTelemetry SDK, you can use environment
variables or php.ini
to configure auto-instrumentation:
OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_SERVICE_NAME=your-service-name \
OTEL_TRACES_EXPORTER=otlp \
OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317 \
OTEL_PROPAGATORS=baggage,tracecontext \
php myapp.php
Manual setup for automatic instrumentation
<?php
OpenTelemetry\API\Globals::registerInitializer(function (Configurator $configurator) {
$propagator = TraceContextPropagator::getInstance();
$spanProcessor = new BatchSpanProcessor(/*params*/);
$tracerProvider = (new TracerProviderBuilder())
->addSpanProcessor($spanProcessor)
->setSampler(new ParentBased(new AlwaysOnSampler()))
->build();
ShutdownHandler::register([$tracerProvider, 'shutdown']);
return $configurator
->withTracerProvider($tracerProvider)
->withPropagator($propagator);
});
//instrumentation libraries can access the configured providers (or a no-op implementation) via `Globals`
$tracer = Globals::tracerProvider()->getTracer('example');
//or, via CachedInstrumentation which uses `Globals` internally
$instrumentation = new CachedInstrumentation('example');
$tracerProvider = $instrumentation->tracer();
Supported libraries and frameworks
Automatic Instrumentation comes with a number of instrumentation libraries for commonly used PHP libraries. For the full list, see instrumentation libraries on packagist.
Next steps
After you have automatic instrumentation configured for your app or service, you might want to add manual instrumentation to collect custom telemetry data.
For more examples, see opentelemetry-php-contrib/examples.