opentelemetry.io/content/en/docs/zero-code/php.md

236 lines
7.3 KiB
Markdown

---
title: PHP zero-code instrumentation
linkTitle: PHP
weight: 30
aliases: [/docs/languages/php/automatic]
# prettier-ignore
cSpell:ignore: centos configurator democlass epel myapp pecl phar remi unindented userland
---
Automatic instrumentation with PHP requires at least PHP 8.0, and the
[OpenTelemetry PHP extension](https://github.com/open-telemetry/opentelemetry-php-instrumentation).
The extension enables registering observer functions (as PHP code) against
classes and methods, and executing those functions before and after the observed
method runs.
{{% alert title="Important" color="warning" %}}Installing the OpenTelemetry
extension by itself will not generate traces. You must also install the
[SDK](https://packagist.org/packages/open-telemetry/sdk) **and** one or more
[instrumentation libraries](/ecosystem/registry/?component=instrumentation&language=php)
for the frameworks and libraries that you are using, or alternatively write your
own.
You also _must_ use
[composer autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading),
as this is the mechanism all instrumentation libraries use to register
themselves. {{% /alert %}}
## Example
```php
<?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();
```
In the example above we define `DemoClass`, then register `pre` and `post` hook
functions on its `run` method. The hook functions will run before and after each
execution of the `DemoClass::run()` method. 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](https://github.com/FriendsOfPHP/pickle) or
[php-extension-installer](https://github.com/mlocati/docker-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](https://blog.remirepo.net/pages/PECL-extensions-RPM-status) -
RPM
- [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=*pecl-opentelemetry) -
APK (currently in the
[_testing_ branch](https://wiki.alpinelinux.org/wiki/Repositories#Testing))
{{< tabpane text=true >}} {{% tab "RPM" %}}
```sh
#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
```
{{% /tab %}} {{% tab "APK" %}}
```sh
#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
```
{{% /tab %}} {{< /tabpane >}}
### PECL
1. Setup development environment. Installing from source requires proper
development environment and some dependencies:
{{< tabpane text=true >}} {{% tab "Linux (apt)" %}}
```sh
sudo apt-get install gcc make autoconf
```
{{% /tab %}} {{% tab "macOS (homebrew)" %}}
```sh
brew install gcc make autoconf
```
{{% /tab %}} {{< /tabpane >}}
2. Build/install the extension. With your environment set up you can install the
extension:
{{< tabpane text=true >}} {{% tab pecl %}}
```sh
pecl install opentelemetry
```
{{% /tab %}} {{% tab pickle %}}
```sh
php pickle.phar install opentelemetry
```
{{% /tab %}} {{% tab "php-extension-installer (docker)" %}}
```sh
install-php-extensions opentelemetry
```
{{% /tab %}} {{< /tabpane >}}
3. Add the extension to your `php.ini` file:
```ini
[opentelemetry]
extension=opentelemetry.so
```
4. Verify that the extension is installed and enabled:
```sh
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:
```sh
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
<?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');
$tracer = $instrumentation->tracer();
```
## Supported libraries and frameworks
Automatic Instrumentation is available for a number of instrumentation libraries
for commonly used PHP libraries. For the full list, see
[instrumentation libraries on packagist](https://packagist.org/search/?query=open-telemetry&tags=instrumentation).
## Next steps
After you have automatic instrumentation configured for your app or service, you
might want to add [manual instrumentation](/docs/languages/php/instrumentation)
to collect custom telemetry data.
For more examples, see
[opentelemetry-php-contrib/examples](https://github.com/open-telemetry/opentelemetry-php-contrib/tree/main/examples).