Report data from PHP applications using OpenTelemetry

更新时间:
复制 MD 格式

After you instrument an application with OpenTelemetry and report traces to Managed Service for OpenTelemetry, Managed Service for OpenTelemetry starts monitoring the application. You can view monitoring data such as application topology, call stacks, abnormal transactions, slow transactions, and SQL analysis. This topic describes how to automatically or manually instrument a PHP application with OpenTelemetry and report data.

Prerequisites

Obtain an endpoint

New console

  1. Log on to the Managed Service for OpenTelemetry console. In the left-side navigation pane, click Integration Center.

  2. On the Integration Center page, click the OpenTelemetry card in the Open Source Frameworks section.

  3. In the OpenTelemetry panel, click the Start Integration tab, and then select a region in which you want to report data.

    Note

    When you access a region for the first time, resources are automatically initialized there.

  4. Configure the Connection Type and Export Protocol parameters and copy an endpoint.

    • Connection Type: If your service is deployed on Alibaba Cloud and resides in the region that you selected, we recommend that you set this parameter to Alibaba Cloud VPC Network. Otherwise, set this parameter to Public Network.

    • Export Protocol: Set this parameter to HTTP (recommended) or gRPC based on the protocol that is supported by the client.

    75.jpg

Old console

  1. Log on to the Managed Service for OpenTelemetry console.

  2. In the left-side navigation pane, click Cluster Configurations. On the page that appears, click the Access point information tab.

  3. In the top navigation bar, select a region in which you want to report data. In the Cluster Information section, turn on Show Token.

  4. Set the Client parameter to OpenTelemetry.

    In the Related Information column of the table, copy an endpoint.ot旧版中.jpg

    Note

    If your application is deployed in an Alibaba Cloud production environment, use a virtual private cloud (VPC) endpoint. Otherwise, use a public endpoint.

Background information

OpenTelemetry PHP supports automatic and manual instrumentation. The following PHP versions are required:

  • Automatic instrumentation: PHP 8.0 or later

  • Manual instrumentation: PHP 7.4 or later

The following is a list of frameworks that support automatic instrumentation. For a complete list, see the OpenTelemetry official documentation.

Expand to view the supported PHP frameworks for monitoring

  • CodeIgniter Framework

  • PHP HTTP Async Client

  • PHP IO

  • Laravel

  • MongoDB

  • PDO

  • PSR-15 middleware

  • PSR-18 HTTP clients

  • PSR-3

  • Slim

  • Symfony

  • WordPress

  • Yii

Demo

Sample code repository: php-opentelemetry-demo

Automatically instrument an application and report traces using the OpenTelemetry PHP extension

The auto-demo is a dice-rolling game application built on the PHP Slim web framework. It uses OpenTelemetry to automatically instrument the application, creating traces, spans, and other trace data. This provides non-intrusive tracing for the PHP application.

In addition to the Slim framework, OpenTelemetry supports automatic instrumentation for many other frameworks. For a complete list, see the official documentation.

Prerequisites

PHP, Composer, and PECL are installed. The PHP version must be 8.0 or later.

Procedure

  1. Create the dice-rolling application.

    1. Initialize the project.

    mkdir <project-name> && cd <project-name>
    
    
    composer init \
     --no-interaction \
     --stability beta \
     --require slim/slim:"^4" \
     --require slim/psr7:"^1"
    composer update
    1. Write the application code.

      In the <project-name> folder, create an index.php file and add the following content.

      This code simulates a dice-rolling game and returns a random number from 1 to 6.

      <?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();

      The application is now complete. Run the php -S localhost:8080 command to start the application. You can access it at http://localhost:8080/rolldice.

  2. Build the OpenTelemetry PHP extension.

    1. Download the tools required to build the OpenTelemetry PHP extension.

      • macOS

        brew install gcc make autoconf
      • Linux (apt)

        sudo apt-get install gcc make autoconf
    2. Use PECL to build the OpenTelemetry PHP extension.

      pecl install opentelemetry

      Note that the last few lines of the output for a successful build are similar to the following (the path may vary):

      Build process completed successfully
      Installing '/opt/homebrew/Cellar/php/8.2.8/pecl/20220829/opentelemetry.so'
      install ok: channel://pecl.php.net/opentelemetry-1.0.0beta6
      Extension opentelemetry enabled in php.ini
    3. (Optional) Enable the OpenTelemetry PHP extension.

      If the output from the previous step includes Extension opentelemetry enabled in php.ini, the extension is already enabled. Skip this step.

      Add the following content to the php.ini file:

      [opentelemetry]
      extension=opentelemetry.so
    4. Verify that the extension is built and enabled.

      • Method 1:

        php -m | grep opentelemetry

        Expected output:

        opentelemetry
      • Method 2

        php --ri opentelemetry

        Expected output:

        opentelemetry
        opentelemetry support => enabled
        extension version => 1.0.0beta6
    5. Add the dependencies required for automatic instrumentation of the dice-rolling application with OpenTelemetry PHP.

      # This step takes a long time to build and prints a lot of content to the console.
      pecl install grpc
      
      
      composer config allow-plugins.php-http/discovery false
      composer require \
        open-telemetry/sdk \
        open-telemetry/opentelemetry-auto-slim \
        open-telemetry/exporter-otlp \
        php-http/guzzle7-adapter \
        open-telemetry/transport-grpc
      • open-telemetry/sdk: The OpenTelemetry PHP software development kit (SDK).

      • open-telemetry/opentelemetry-auto-slim: The automatic instrumentation plugin for the Slim framework in OpenTelemetry PHP.

      • open-telemetry/exporter-otlp: The dependency required to report data over the OpenTelemetry Protocol (OTLP).

  3. Run the application.

    1. Run the following command.

      env OTEL_PHP_AUTOLOAD_ENABLED=true \
       OTEL_SERVICE_NAME=<your-service-name> \
       OTEL_TRACES_EXPORTER=otlp \
       OTEL_METRICS_EXPORTER=none \
       OTEL_LOGS_EXPORTER=none \
       OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
       OTEL_EXPORTER_OTLP_ENDPOINT=<endpoint> \
       OTEL_EXPORTER_OTLP_HEADERS=Authentication=<token> \
       OTEL_PROPAGATORS=baggage,tracecontext \
       php -S localhost:8080
      • <your-service-name>: The application name, such as php-demo.

      • <endpoint>: The gRPC endpoint obtained in the Prerequisites section, such as http://tracing-analysis-dc-hz.aliyuncs.com:8090.

      • <token>: The authentication token obtained in the Prerequisites section.

    2. Access the following URL in a browser.

      http://localhost:8080/rolldice

      Each time you access this page, OpenTelemetry automatically creates a trace and reports it to Alibaba Cloud Managed Service for OpenTelemetry.

    3. You can view trace data.

      Log on to the Managed Service for OpenTelemetry console. On the Applications page, find the application named <your-service-name>, such as php-demo. Click the application name to open the application details page and view the call stack.

Manually instrument an application and report traces using the OpenTelemetry PHP SDK

The manual-demo is a dice-rolling game application built on the PHP Slim web framework. It uses the OpenTelemetry PHP SDK to manually instrument the application. This process involves creating spans and setting their properties, events, and statuses in the code to implement custom tracing for the PHP application.

If automatic instrumentation with the OpenTelemetry PHP extension does not meet your needs, or if you want to add custom business instrumentation, you can use manual instrumentation to report traces.

Prerequisites

PHP, Composer, and PECL are installed. The PHP version must be 7.4 or later.

Procedure

  1. Create the dice-rolling application.

    1. Initialize the project.

    mkdir <project-name> && cd <project-name>
    
    
    composer init \
     --no-interaction \
     --stability beta \
     --require slim/slim:"^4" \
     --require slim/psr7:"^1"
    composer update
    1. Write the application code.

      In the <project-name> folder, create an index.php file and add the following content.

      This code simulates a dice-rolling game and returns a random number from 1 to 6.

      <?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();

      The application is now complete. Run the php -S localhost:8080 command to start the application. You can access it at http://localhost:8080/rolldice.

  2. Import the dependencies required for the OpenTelemetry PHP SDK.

    gRPC reporting

    1. Download the PHP HTTP client library to report traces.

      composer require guzzlehttp/guzzle
    2. Download the OpenTelemetry PHP SDK.

      composer require \
       open-telemetry/sdk \
       open-telemetry/exporter-otlp
    3. Download the dependencies required to report data using gRPC.

      pecl install grpc # If you have already downloaded gRPC, you can skip this step.
      composer require open-telemetry/transport-grpc

    HTTP reporting

    1. Download the PHP HTTP client library to report traces.

      composer require guzzlehttp/guzzle
    2. Download the OpenTelemetry PHP SDK.

      composer require \
       open-telemetry/sdk \
       open-telemetry/exporter-otlp
  3. Write the OpenTelemetry initialization utility class.

    1. In the same folder as the index.php file, create an opentelemetry_util.php file.

    2. Add the following code to the file.

      gRPC reporting

      <?php
      use OpenTelemetry\API\Common\Instrumentation\Globals;
      use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
      use OpenTelemetry\Contrib\Otlp\SpanExporter;
      use OpenTelemetry\SDK\Common\Attribute\Attributes;
      use OpenTelemetry\SDK\Common\Export\Stream\StreamTransportFactory;
      use OpenTelemetry\SDK\Resource\ResourceInfo;
      use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
      use OpenTelemetry\SDK\Sdk;
      use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
      use OpenTelemetry\SDK\Trace\Sampler\ParentBased;
      use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
      use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessorBuilder;
      use OpenTelemetry\SDK\Trace\TracerProvider;
      use OpenTelemetry\SemConv\ResourceAttributes;
      use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory;
      use OpenTelemetry\Contrib\Otlp\OtlpUtil;
      use OpenTelemetry\API\Signals;
      // OpenTelemetry initialization configuration (must be done when the PHP application is initialized).
      function initOpenTelemetry()
      { 
          // 1. Set the OpenTelemetry resource information.
          $resource = ResourceInfoFactory::emptyResource()->merge(ResourceInfo::create(Attributes::create([
              ResourceAttributes::SERVICE_NAME => '<your-service-name>', # Application name, required.
              ResourceAttributes::HOST_NAME => '<your-host-name>' # Hostname, optional.
          ])));
      
          // 2. (Optional) Create a SpanExporter to output spans to the console.
          // $spanExporter = new SpanExporter(
          //     (new StreamTransportFactory())->create('php://stdout', 'application/json')
          // );
      
          // 2. Create a SpanExporter to report spans over gRPC.
          $headers = [
              'Authentication' => "<your-token>",
          ];
          $transport = (new GrpcTransportFactory())->create('<grpc-endpoint>' . OtlpUtil::method(Signals::TRACE), 'application/x-protobuf', $headers);
          $spanExporter = new SpanExporter($transport);
      
          // 3. Create a global TracerProvider to create tracers.
          $tracerProvider = TracerProvider::builder()
              ->addSpanProcessor(
                  (new BatchSpanProcessorBuilder($spanExporter))->build()
              )
              ->setResource($resource)
              ->setSampler(new ParentBased(new AlwaysOnSampler()))
              ->build();
      
          Sdk::builder()
              ->setTracerProvider($tracerProvider)
              ->setPropagator(TraceContextPropagator::getInstance())
              ->setAutoShutdown(true)  // Automatically shut down the tracerProvider after the PHP program exits to ensure all traces are reported.
              ->buildAndRegisterGlobal(); // Add the tracerProvider to the global scope.
      }
      ?>
      • <your-service-name>: The application name.

      • <your-host-name>: The hostname.

      • <your-token>: The authentication token for reporting data over gRPC.

      • <grpc-endpoint>: The endpoint for reporting data over gRPC.

      HTTP reporting

      <?php
      use OpenTelemetry\API\Common\Instrumentation\Globals;
      use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
      use OpenTelemetry\Contrib\Otlp\SpanExporter;
      use OpenTelemetry\SDK\Common\Attribute\Attributes;
      use OpenTelemetry\SDK\Common\Export\Stream\StreamTransportFactory;
      use OpenTelemetry\SDK\Resource\ResourceInfo;
      use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
      use OpenTelemetry\SDK\Sdk;
      use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
      use OpenTelemetry\SDK\Trace\Sampler\ParentBased;
      use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
      use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessorBuilder;
      use OpenTelemetry\SDK\Trace\TracerProvider;
      use OpenTelemetry\SemConv\ResourceAttributes;
      use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;
      use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
      
      // OpenTelemetry initialization configuration (must be done when the PHP application is initialized).
      function initOpenTelemetry()
      { 
          // 1. Set the OpenTelemetry resource information.
          $resource = ResourceInfoFactory::emptyResource()->merge(ResourceInfo::create(Attributes::create([
              ResourceAttributes::SERVICE_NAME => '<your-service-name>', # Application name, required.
              ResourceAttributes::HOST_NAME => '<your-host-name>' # Hostname, optional.
          ])));
      
          // 2. (Optional) Create a SpanExporter to output spans to the console.
          // $spanExporter = new SpanExporter(
          //     (new StreamTransportFactory())->create('php://stdout', 'application/json')
          // );
      
          
          // 2. Create a SpanExporter to report spans over HTTP.
          $transport = (new OtlpHttpTransportFactory())->create('<http-endpoint>','application/x-protobuf');
          $spanExporter = new SpanExporter($transport);
      
          // 3. Create a global TracerProvider to create tracers.
          $tracerProvider = TracerProvider::builder()
              ->addSpanProcessor(
                  (new BatchSpanProcessorBuilder($spanExporter))->build()
              )
              ->setResource($resource)
              ->setSampler(new ParentBased(new AlwaysOnSampler()))
              ->build();
      
          Sdk::builder()
              ->setTracerProvider($tracerProvider)
              ->setPropagator(TraceContextPropagator::getInstance())
              ->setAutoShutdown(true)  // Automatically shut down the tracerProvider after the PHP program exits to ensure all traces are reported.
              ->buildAndRegisterGlobal(); // Add the tracerProvider to the global scope.
      }
      ?>
      • <your-service-name>: The application name.

      • <your-host-name>: The hostname.

      • <http-endpoint>: The endpoint for reporting data over HTTP.

  4. Modify the application code to create spans using the OpenTelemetry API.

    1. In the index.php file, import the required packages.

      <?php
      
      use OpenTelemetry\API\Common\Instrumentation\Globals;
      use OpenTelemetry\SDK\Common\Attribute\Attributes;
      use OpenTelemetry\SDK\Trace\TracerProvider;
      
      require __DIR__ . '/opentelemetry_util.php';
    2. Call the initOpenTelemetry method to complete the initialization. The OpenTelemetry initialization must be configured when the PHP application starts.

      // Initialize OpenTelemetry. This includes setting the application name, trace export method, and trace reporting endpoint, and creating a global TraceProvider.
      initOpenTelemetry();
    3. Create a span in the rolldice interface.

      /**
       * 1. Interface function: Simulates rolling a die and returns a random positive integer from 1 to 6.
       * Also demonstrates how to create a span, set properties, set events, and set events with properties.
       */
      $app->get('/rolldice', function (Request $request, Response $response) {
       // Get the tracer.
       $tracer = \OpenTelemetry\API\Globals::tracerProvider()->getTracer('my-tracer');
       // Create a span.
       $span = $tracer->spanBuilder("/rolldice")->startSpan();
       // Set a property for the span.
       $span->setAttribute("http.method", "GET");
       // Set an event for the span.
       $span->addEvent("Init");
       // Set an event with properties.
       $eventAttributes = Attributes::create([
       "key1" => "value",
       "key2" => 3.14159,
       ]);
      
       // Business logic.
       $result = random_int(1,6);
       $response->getBody()->write(strval($result));
      
       $span->addEvent("End");
       // End the span.
       $span->end();
      
       return $response;
      });
    4. Create a nested span.

      Create a new rolltwodices interface to simulate rolling two dice and return two random integers from 1 to 6.

      The following code shows how to create a nested span.

      $app->get('/rolltwodices', function (Request $request, Response $response) {
       // Get the tracer.
       $tracer = \OpenTelemetry\API\Globals::tracerProvider()->getTracer('my-tracer');
       // Create a span.
       $parentSpan = $tracer->spanBuilder("/rolltwodices/parent")->startSpan();
       $scope = $parentSpan->activate();
      
       $value1 = random_int(1,6);
      
       $childSpan = $tracer->spanBuilder("/rolltwodices/parent/child")->startSpan();
       
       // Business logic.
       $value2 = random_int(1,6);
       $result = "dice1: " . $value1 . ", dice2: " . $value2; 
      
       // End the spans.
       $childSpan->end();
       $parentSpan->end();
       $scope->detach();
      
       $response->getBody()->write(strval($result));
       return $response;
      });
    5. Use a span to record exceptions that occur in the code.

      Create a new error interface to simulate an interface exception.

      The following code shows how to use a span to record the status when an exception occurs.

      $app->get('/error', function (Request $request, Response $response) {
       // Get the tracer.
       $tracer = \OpenTelemetry\API\Globals::tracerProvider()->getTracer('my-tracer');
       // Create a span.
       $span3 = $tracer->spanBuilder("/error")->startSpan();
       try {
       // Simulate an exception in the code.
       throw new \Exception('exception!');
       } catch (\Throwable $t) {
       // Set the span status to error.
       $span3->setStatus(\OpenTelemetry\API\Trace\StatusCode::STATUS_ERROR, "exception in span3!");
       // Record the exception stack trace.
       $span3->recordException($t, ['exception.escaped' => true]);
       } finally {
       $span3->end();
       $response->getBody()->write("error");
       return $response;
       }
      });
  5. Run the application.

    1. Run the following command

      php -S localhost:8080
    2. Access the following URLs in a browser:

      http://localhost:8080/rolldice
      http://localhost:8080/rolltwodices
      http://localhost:8080/error

      Each time you access a page, OpenTelemetry creates a trace and reports it to Alibaba Cloud Managed Service for OpenTelemetry.

    3. View the trace data.

      Log on to the Managed Service for OpenTelemetry console. On the Applications page, find the application named <your-service-name>, such as php-manual-demo. Click the application name to open the application details page and view the call stack.