opentelemetry.io/content/en/docs/languages/php/getting-started.md

501 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Getting Started
description: Get up and running with OpenTelemetry for PHP.
aliases: [getting_started]
weight: 10
cSpell:ignore: darwin myapp PECL pecl rolldice strval
---
OpenTelemetry for PHP can be used to generate and export [traces][], [metrics][]
and [logs][].
This page will show you how to get started with OpenTelemetry in PHP. We will
create a simple "roll the dice" application, then apply both automatic and
manual instrumentation to generate [traces][] and export them to the console. We
will then emit some [logs][] which will also be sent to the console.
## Prerequisites
OpenTelemetry requires PHP 8.0+ for automatic instrumentation, however manual
instrumentation will work with PHP 7.4
Ensure that you have the following installed:
- [PHP 8.0+](https://www.php.net/)
- [PECL](https://pecl.php.net/)
- [composer](https://getcomposer.org/)
Before you get started make sure that you have both available in your shell:
```sh
php -v
composer -v
```
## Example Application
The following example uses a basic
[Slim Framework](https://www.slimframework.com/) application. If you are not
using Slim, that's OK — you can use OpenTelemetry PHP with other web frameworks
as well, such as WordPress, Symfony and Laravel. For a complete list of
libraries for supported frameworks, see the
[registry](/ecosystem/registry/?component=instrumentation&language=php).
### Dependencies
In an empty directory initialize a minimal `composer.json` file:
```sh
composer init \
--no-interaction \
--require slim/slim:"^4" \
--require slim/psr7:"^1"
composer update
```
### Create and launch an HTTP Server
In that same directory, create a file called `index.php` with the following
content:
```php
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) {
$result = random_int(1,6);
$response->getBody()->write(strval($result));
return $response;
});
$app->run();
```
Run the application using the PHP built-in web server:
```shell
php -S localhost:8080
```
Open <http://localhost:8080/rolldice> in your web browser to ensure it is
working.
## Add automatic instrumentation
Next, youll use the OpenTelemetry PHP extension to
[automatically instrument](../automatic/) the application.
1. Since the extension is built from source, you need to install some build
tools
{{< 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 the extension with `PECL`:
```sh
pecl install opentelemetry
```
{{% alert title="Note" color="warning" %}}Alternative methods of installing
the extension are detailed in
[automatic instrumentation](../automatic/#installation). {{% /alert %}}
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 --ri opentelemetry
```
5. Add additional dependencies to your application, which are required for the
automatic instrumentation of your code:
```sh
composer config allow-plugins.php-http/discovery false
composer require \
open-telemetry/sdk \
open-telemetry/opentelemetry-auto-slim
```
With the OpenTelemetry PHP extension set up and an auto-instrumentation package
installed, you can now run your application and generate some traces:
```sh
env OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_TRACES_EXPORTER=console \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
php -S localhost:8080
```
Open <http://localhost:8080/rolldice> in your web browser and reload the page a
few times. After a while you should see the spans printed to your console:
<details>
<summary>View example output</summary>
```json
[
{
"name": "GET /rolldice",
"context": {
"trace_id": "16d7c6da7c021c574205736527816eb7",
"span_id": "268e52331de62e33",
"trace_state": ""
},
"resource": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta10",
"telemetry.auto.version": "1.0.0beta5",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.2.6",
"process.pid": 24435,
"process.executable.path": "/bin/php",
"process.owner": "php",
"os.type": "darwin",
"os.description": "22.4.0",
"os.name": "Darwin",
"os.version": "Darwin Kernel Version 22.4.0: Mon Mar 6 20:59:28 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6000",
"host.name": "OPENTELEMETRY-PHP",
"host.arch": "arm64"
},
"parent_span_id": "",
"kind": "KIND_SERVER",
"start": 1684749478068582482,
"end": 1684749478072715774,
"attributes": {
"code.function": "handle",
"code.namespace": "Slim\\App",
"code.filepath": "/vendor/slim/slim/Slim/App.php",
"code.lineno": 197,
"http.url": "http://localhost:8080/rolldice",
"http.method": "GET",
"http.request_content_length": "",
"http.scheme": "http",
"http.status_code": 200,
"http.flavor": "1.1",
"http.response_content_length": ""
},
"status": {
"code": "Unset",
"description": ""
},
"events": [],
"links": []
}
]
```
</details>
## Add manual instrumentation
### Traces
Manual tracing requires a `TracerProvider`. There are a number of ways to set
one up. In this example we will use the autoloaded TracerProvider, which is
globally available.
Replace `index.php` with the following code:
```php
<?php
use OpenTelemetry\API\Globals;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$tracer = Globals::tracerProvider()->getTracer('demo');
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($tracer) {
$span = $tracer
->spanBuilder('manual-span')
->startSpan();
$result = random_int(1,6);
$response->getBody()->write(strval($result));
$span
->addEvent('rolled dice', ['result' => $result])
->end();
return $response;
});
$app->run();
```
Start the built-in web server again, and browse to
<http://localhost:8080/rolldice>. You should see similar output, but with the
addition of a new span named `manual-span`.
Note that the manual span's `parent_span_id` contains the same value as the
"{closure}" span's `context.span_id`. Manual and automatic instrumentation work
well together, since under the hood they use the same APIs.
### Logging
Now let's add some logging. We will use the popular `monolog` logging library to
do this, via a handler which will emit the logs in the OpenTelemetry format.
First, let's install some more dependencies:
```shell
composer require \
monolog/monolog \
open-telemetry/opentelemetry-logger-monolog
```
Replace the `index.php` file with the following code:
```php
<?php
use Monolog\Logger;
use OpenTelemetry\API\Globals;
use OpenTelemetry\Contrib\Logs\Monolog\Handler;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LogLevel;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$loggerProvider = Globals::loggerProvider();
$handler = new Handler(
$loggerProvider,
LogLevel::INFO
);
$monolog = new Logger('otel-php-monolog', [$handler]);
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($monolog) {
$result = random_int(1,6);
$response->getBody()->write(strval($result));
$monolog->info('dice rolled', ['result' => $result]);
return $response;
});
$app->run();
```
Start the built-in web server with the following command (note the change to
`OTEL_LOGS_EXPORTER`):
```shell
env OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_TRACES_EXPORTER=console \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=console \
php -S localhost:8080
```
This time when browsing to <http://localhost:8080/rolldice> you should see the
automatic instrumentation traces as before, and also a log record which was
generated from the monolog handler.
Note that `trace_id` and `span_id` were added to the log output, and that the
values correspond to the active span at the time the log message was generated.
<details>
<summary>View example output</summary>
```json
[
{
"name": "{closure}",
"context": {
"trace_id": "8b046fc5d43864058b6a5a18e0dfce3f",
"span_id": "9cf24c78c6868bfe",
"trace_state": ""
},
"resource": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta11",
"telemetry.auto.version": "1.0.0beta6",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.0.27",
"process.pid": 2672,
"process.executable.path": "\/usr\/local\/bin\/php",
"process.owner": "root",
"os.type": "linux",
"os.description": "5.15.0-75-generic",
"os.name": "Linux",
"os.version": "#82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023",
"host.name": "f2c0afe83ea9",
"host.arch": "x86_64"
},
"parent_span_id": "df2199a615085705",
"kind": "KIND_INTERNAL",
"start": 1687323704059486500,
"end": 1687323704060820769,
"attributes": {
"code.function": "__invoke",
"code.namespace": "Slim\\Handlers\\Strategies\\RequestResponse",
"code.filepath": "\/usr\/src\/myapp\/vendor\/slim\/slim\/Slim\/Handlers\/Strategies\/RequestResponse.php",
"code.lineno": 28
},
"status": {
"code": "Unset",
"description": ""
},
"events": [],
"links": []
}
]
[
{
"name": "GET \/rolldice",
"context": {
"trace_id": "8b046fc5d43864058b6a5a18e0dfce3f",
"span_id": "df2199a615085705",
"trace_state": ""
},
"resource": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta11",
"telemetry.auto.version": "1.0.0beta6",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.0.27",
"process.pid": 2672,
"process.executable.path": "\/usr\/local\/bin\/php",
"process.owner": "root",
"os.type": "linux",
"os.description": "5.15.0-75-generic",
"os.name": "Linux",
"os.version": "#82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023",
"host.name": "f2c0afe83ea9",
"host.arch": "x86_64"
},
"parent_span_id": "",
"kind": "KIND_SERVER",
"start": 1687323704058191192,
"end": 1687323704060981779,
"attributes": {
"code.function": "handle",
"code.namespace": "Slim\\App",
"code.filepath": "\/usr\/src\/myapp\/vendor\/slim\/slim\/Slim\/App.php",
"code.lineno": 197,
"http.url": "http:\/\/localhost:8080\/rolldice",
"http.method": "GET",
"http.request_content_length": "",
"http.scheme": "http",
"http.status_code": 200,
"http.flavor": "1.1",
"http.response_content_length": ""
},
"status": {
"code": "Unset",
"description": ""
},
"events": [],
"links": []
}
]
{
"resource": {
"attributes": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta11",
"telemetry.auto.version": "1.0.0beta6",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.0.27",
"process.pid": 2672,
"process.executable.path": "\/usr\/local\/bin\/php",
"process.owner": "root",
"os.type": "linux",
"os.description": "5.15.0-75-generic",
"os.name": "Linux",
"os.version": "#82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023",
"host.name": "f2c0afe83ea9",
"host.arch": "x86_64"
},
"dropped_attributes_count": 0
},
"scope": {
"name": "monolog",
"version": null,
"attributes": [],
"dropped_attributes_count": 0,
"schema_url": null,
"logs": [
{
"timestamp": 1687323704059648000,
"observed_timestamp": 1687323704060784128,
"severity_number": 9,
"severity_text": "INFO",
"body": "dice rolled",
"trace_id": "8b046fc5d43864058b6a5a18e0dfce3f",
"span_id": "9cf24c78c6868bfe",
"trace_flags": 1,
"attributes": {
"channel": "otel-php-monolog",
"context": {
"result": 4
}
},
"dropped_attributes_count": 0
}
]
}
}
```
</details>
## What's next?
For more:
- Run this example with another [exporter][] for telemetry data.
- Try [automatic instrumentation](../automatic/) on one of your own apps.
- Learn more about [manual instrumentation][] and try out some
[examples](/docs/languages/php/examples/).
- Take a look at the [OpenTelemetry Demo](/docs/demo/), which includes the PHP
based [Quote Service](/docs/demo/services/quote/).
[traces]: /docs/concepts/signals/traces/
[metrics]: /docs/concepts/signals/metrics/
[logs]: /docs/concepts/signals/logs/
[exporter]: ../exporters/
[manual instrumentation]: ../instrumentation/