OpenTelemetry for PHP

repository·main·Indexed 21 days ago

https://github.com/open-telemetry/opentelemetry-php

A monorepo containing core components for implementing OpenTelemetry in PHP applications, including the API, SDK, and various exporters. It provides packages for context management, semantic conventions, OTLP exporting via gRPC, and SDK configuration. The project supports all officially supported PHP versions and includes tools for distributed tracing implementation using middleware for Guzzle and Slim.

Tokens
14.5K
Snippets
53
Records
71
Agent score
75%

What's inside opentelemetry-php

  1. Handle removed attributes via deprecation templates

    main

    If an update to semantic conventions results in the removal of attributes, you can maintain backwards compatibility by adding them back as deprecated entries.

    To do this, add the removed attributes to the corresponding templates/<class>_deprecations.php.partial files. The generator will include these partial files in the final output. It is important to mark these attributes as @deprecated to discourage new usage while maintaining compatibility for existing users.

  2. Understand Semantic Convention stability levels

    main

    OpenTelemetry Semantic Conventions are categorized by stability to help instrumentation authors choose the right attributes for their use case:

    • Stable: Located in OpenTelemetry\SemConv\Attributes\* and OpenTelemetry\SemConv\Metrics\*. These are safe for production use.
    • Incubating: Located in OpenTelemetry\SemConv\Incubating\*. These contain both stable and experimental elements. Experimental elements should be used with caution.

    Note on Deprecation: Deprecated conventions are removed in the immediate next release following deprecation. There is no backwards compatibility guarantee for deprecated conventions.

  3. How distributed tracing is implemented in PHP services

    main

    The demo uses two specific middleware patterns to enable distributed tracing in a PHP application (using Slim and Guzzle):

    1. Guzzle Middleware: Responsible for outgoing requests. It wraps each outgoing HTTP request in a span with standard HTTP-based attributes and injects the traceparent (and optionally tracestate) headers into the request to propagate the context.

    2. Slim Middleware: Responsible for incoming requests. It starts the root span for the request. It uses the route pattern for the span name to maintain low cardinality. This middleware also manages the extraction of incoming trace headers to continue existing traces.

  4. Define custom component providers

    main

    To extend the configuration model, implement the ComponentProvider interface. A provider must implement two methods:

    1. getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition: Defines the configuration schema for the component using an ArrayNodeDefinition. This allows you to specify required fields, default values, and constraints (like min()). You can also reference other components in the registry (e.g., an exporter) using $registry->component(...).
    2. createPlugin(array $properties, Context $context): T: Uses the parsed $properties array to instantiate and return the actual component (e.g., a SpanProcessor).
    final class SpanProcessorBatch implements ComponentProvider {
    
        /**
         * @param array{
         *     schedule_delay: int<0, max>,
         *     export_timeout: int<0, max>,
         *     max_queue_size: int<0, max>,
         *     max_export_batch_size: int<0, max>,
         *     exporter: ComponentPlugin<SpanExporter>,
         * } $properties
         */
        public function createPlugin(array $properties, Context $context): SpanProcessor {
            // ...
        }
    
        public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition {
            $node = new ArrayNodeDefinition('batch');
            $node
                ->children()
                    ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end()
                    ->integerNode('export_timeout')->min(0)->defaultValue(30000)->end()
                    ->integerNode('max_queue_size')->min(0)->defaultValue(2048)->end()
                    ->integerNode('max_export_batch_size')->min(0)->defaultValue(512)->end()
                    ->append($registry->component('exporter', SpanExporter::class)->isRequired())
                ->end()
            ;
    
            return $node;
        }
    }
  5. Optimize SDK configuration performance with a cache file

    main

    Parsing and processing configuration files is an expensive operation. In PHP's shared-nothing architecture, it is highly recommended to provide a $cacheFile path to Configuration::parseFile(). This allows the parsed configuration to be cached, significantly improving performance on subsequent requests.

    $configuration = Configuration::parseFile(
        __DIR__ . '/kitchen-sink.yaml',
        __DIR__ . '/var/cache/opentelemetry.php',
    );
    $sdkBuilder = $configuration->create();
  6. How to integrate 3rd party loggers with OpenTelemetry

    main

    The OpenTelemetry Logger API is intended for library developers who want to bridge existing logging frameworks (like Monolog) into OpenTelemetry. To implement a log appender (or handler) that follows the OpenTelemetry logs bridge API specification, follow these steps:

    1. Obtain a LoggerProvider: Accept an OpenTelemetry\API\Logs\LoggerProviderInterface or retrieve the globally registered provider using OpenTelemetry\API\Instrumentation\Globals.
    2. Get a Logger: Use the provider to obtain a Logger instance. You can optionally include resources that should be associated with the emitted logs.
    3. Convert Formats: Transform logs from the 3rd party library's internal format into the OpenTelemetry LogRecord format.
    4. Emit Logs: Send the converted logs to OpenTelemetry by calling Logger::logRecord().
    /* See monolog-otel-integration example for implementation details: 
    /examples/logs/features/monolog-otel-integration.php */
  7. Understand the versioning and stability guarantees of OpenTelemetry PHP

    main

    OpenTelemetry PHP follows semver v2. The project distinguishes between 'Mature' and 'Immature/Experimental' signals to provide stability guarantees for your instrumentation and SDK configuration.

    API and SDK Stability

    • Patch Releases: No existing method names or signatures will change.
    • Minor Releases: Method signatures may only change in a backwards compatible way.
    • Compatibility: Once an API for a signal (spans, logs, metrics, baggage) is released, that API module will function with any SDK that shares the same major version and has an equal or greater minor version.
      • Example: An application instrumented with opentelemetry-api-trace:1.0.1 is compatible with opentelemetry-sdk-trace:1.11.33.
  8. Quickstart: Integrate OpenTelemetry into a Laravel Application

    main

    This guide provides a walkthrough for integrating OpenTelemetry PHP into a Laravel application to enable distributed tracing, metrics, and logs. The example demonstrates how to visualize application exceptions using Zipkin and Jaeger.

    Prerequisites:

    • PHP (example uses 7.4)
    • Composer
    • Docker

    Note: This guide is intended for introductory purposes. The code provided is not production-ready.

    # This is a guide overview. Follow the steps below for implementation.
  9. Use CloudTrace propagator for trace context propagation

    main

    The CloudTrace propagator supports the x-cloud-trace-context header for propagating trace context across service boundaries, compatible with Google Cloud Trace.

    It offers two modes of operation:

    1. One-way mode: Processes incoming headers and returns the correct span context, but does not inject headers for downstream consumption. It attaches to existing X-Cloud-Trace-Context traces without creating new downstream ones.
    2. Bi-directional mode: Processes incoming headers and injects headers for downstream services to consume.

    Use CloudTracePropagator::getOneWayInstance() for one-way propagation and CloudTracePropagator::getInstance() for bi-directional propagation.

    // For one-way CloudTrace
    $propagator = CloudTracePropagator::getOneWayInstance();
    
    // For bi-directional CloudTrace
    $propagator = CloudTracePropagator::getInstance();