From 100e517d1d4fdd327dbc7e5b62116b9563787d19 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 1 Mar 2023 23:23:39 +1100 Subject: [PATCH] Adding PHP documentation for exporters, resources, propagation (#2415) --- .../en/docs/instrumentation/php/exporters.md | 128 ++++++++++++++++++ .../instrumentation/php/getting-started.md | 2 +- content/en/docs/instrumentation/php/manual.md | 55 +------- .../docs/instrumentation/php/propagation.md | 96 +++++++++++++ .../en/docs/instrumentation/php/resources.md | 85 ++++++++++++ static/refcache.json | 8 ++ 6 files changed, 322 insertions(+), 52 deletions(-) create mode 100644 content/en/docs/instrumentation/php/exporters.md create mode 100644 content/en/docs/instrumentation/php/propagation.md create mode 100644 content/en/docs/instrumentation/php/resources.md diff --git a/content/en/docs/instrumentation/php/exporters.md b/content/en/docs/instrumentation/php/exporters.md new file mode 100644 index 000000000..9ff4fc852 --- /dev/null +++ b/content/en/docs/instrumentation/php/exporters.md @@ -0,0 +1,128 @@ +--- +title: Exporters +weight: 5 +--- + +In order to visualize and analyze your telemetry, you will need to export it to +a backend. OpenTelemetry PHP provides exporters for some common open source +backends. + +## OTLP + +To send trace data to a OTLP endpoint (like the [collector](/docs/collector) or +Jaeger) you'll need to use the `open-telemetry/exporter-otlp` package: + +```shell +composer require open-telemetry/exporter-otlp +``` + +If you use gRPC, you will also need to install the +`open-telemetry/transport-grpc` package: + +```shell +composer require open-telemetry/transport-grpc +``` + +Next, configure the exporter with an OTLP endpoint. For example, you can update +`GettingStarted.php` from [Getting Started](../getting-started/) like the +following: + + +{{< tabpane >}} +{{< tab gRPC >}} +use OpenTelemetry\API\Common\Signal\Signals; +use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; +use OpenTelemetry\Contrib\Otlp\OtlpUtil; +use OpenTelemetry\Contrib\Otlp\SpanExporter; +use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; +use OpenTelemetry\SDK\Trace\TracerProvider; + +$transport = (new GrpcTransportFactory())->create('http://collector:4317' . OtlpUtil::method(Signals::TRACE)); +$exporter = new SpanExporter($transport); +{{< /tab >}} +{{< tab protobuf >}} +use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory; +use OpenTelemetry\Contrib\Otlp\SpanExporter; +use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; +use OpenTelemetry\SDK\Trace\TracerProvider; + +$transport = (new OtlpHttpTransportFactory())->create('http://collector:4318/v1/traces', 'application/x-protobuf'); +$exporter = new SpanExporter($transport); +{{< /tab>}} +{{< tab json >}} +use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory; +use OpenTelemetry\Contrib\Otlp\SpanExporter; +use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; +use OpenTelemetry\SDK\Trace\TracerProvider; + +$transport = (new OtlpHttpTransportFactory())->create('http://collector:4318/v1/traces', 'application/json'); +$exporter = new SpanExporter($transport); +{{< /tab >}} +{{< tab nd-json >}} +/* newline-delimited JSON */ +use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory; +use OpenTelemetry\Contrib\Otlp\SpanExporter; +use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; +use OpenTelemetry\SDK\Trace\TracerProvider; + +$transport = (new OtlpHttpTransportFactory())->create('http://collector:4318/v1/traces', 'application/x-ndjson'); +$exporter = new SpanExporter($transport); +{{< /tab >}} +{{< /tabpane >}} + + +Then, register the exporter in a tracer provider: + +```php +$tracerProvider = new TracerProvider( + new SimpleSpanProcessor($exporter) +); +$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php'); +``` + +To try out the example locally, you can run +[Jaeger](https://www.jaegertracing.io/) in a docker container: + +```shell +docker run -d --name jaeger \ + -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ + -e COLLECTOR_OTLP_ENABLED=true \ + -p 6831:6831/udp \ + -p 6832:6832/udp \ + -p 5778:5778 \ + -p 16686:16686 \ + -p 4317:4317 \ + -p 4318:4318 \ + -p 14250:14250 \ + -p 14268:14268 \ + -p 14269:14269 \ + -p 9411:9411 \ + jaegertracing/all-in-one:latest +``` + +## Zipkin + +If you're using [Zipkin](https://zipkin.io/) to visualize traces, you'll need to +set it up first. Here's how to run it locally in a docker container. + +```shell +docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin +``` + +Install the exporter package as a dependency for your application: + +```shell +composer require open-telemetry/exporter-zipkin +``` + +Update the example to use the Zipkin exporter and to send data to your zipkin +backend: + +```php +$transport = PsrTransportFactory::discover()->create('http://zipkin:9411/api/v2/spans', 'application/json'); +$zipkinExporter = new ZipkinExporter($transport); +$tracerProvider = new TracerProvider( + new SimpleSpanProcessor($zipkinExporter) +); +$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php'); +``` diff --git a/content/en/docs/instrumentation/php/getting-started.md b/content/en/docs/instrumentation/php/getting-started.md index 0f4b0f7b7..be162b0ed 100644 --- a/content/en/docs/instrumentation/php/getting-started.md +++ b/content/en/docs/instrumentation/php/getting-started.md @@ -80,7 +80,7 @@ composer require "php-http/guzzle7-adapter" Now you can install the OpenTelemetry SDK: ```sh -composer require open-telemetry/opentelemetry +composer require open-telemetry/sdk ``` The example uses the `ConsoleSpanExporter`, which prints Spans to stdout. A Span diff --git a/content/en/docs/instrumentation/php/manual.md b/content/en/docs/instrumentation/php/manual.md index d0e89f94d..daa4cc262 100644 --- a/content/en/docs/instrumentation/php/manual.md +++ b/content/en/docs/instrumentation/php/manual.md @@ -78,8 +78,8 @@ To do [Tracing](/docs/concepts/signals/traces/) you'll need to acquire a **Note:** Methods of the OpenTelemetry SDK should never be called. First, a `Tracer` must be acquired, which is responsible for creating spans and -interacting with the [Context](#context-propagation). A tracer is acquired by -using the OpenTelemetry API specifying the name and version of the [library +interacting with the [Context](../propagation/). A tracer is acquired by using +the OpenTelemetry API specifying the name and version of the [library instrumenting][instrumentation library] the [instrumented library] or application to be monitored. More information is available in the specification chapter [Obtaining a Tracer]. @@ -120,7 +120,7 @@ Most of the time, we want to correlate [spans](/docs/concepts/signals/traces/#spans-in-opentelemetry) for nested operations. OpenTelemetry supports tracing within processes and across remote processes. For more details how to share context between remote processes, see -[Context Propagation](#context-propagation). +[Context Propagation](../propagation/). For a method `a` calling a method `b`, the spans could be manually linked in the following way: @@ -210,7 +210,7 @@ $span = $tracer->spanBuilder("span-with-links") ``` For more details how to read context from remote processes, see -[Context Propagation](#context-propagation). +[Context Propagation](../propagation/). ### Set span status and record exceptions @@ -240,53 +240,6 @@ try { } ``` -### Context Propagation - -OpenTelemetry provides a text-based approach to propagate context to remote -services using the [W3C Trace Context](https://www.w3.org/TR/trace-context/) -HTTP headers. - -The following presents an example of an outgoing HTTP request: - -```php -$request = new Request('GET', 'http://localhost:8080/resource'); -$outgoing = $tracer->spanBuilder('/resource')->setSpanKind(SpanKind::CLIENT)->startSpan(); -$outgoing->setAttribute(TraceAttributes::HTTP_METHOD, $request->getMethod()); -$outgoing->setAttribute(TraceAttributes::HTTP_URL, (string) $request->getUri()); - -$carrier = []; -TraceContextPropagator::getInstance()->inject($carrier); -foreach ($carrier as $name => $value) { - $request = $request->withAddedHeader($name, $value); -} -try { - $response = $client->send($request); -} finally { - $outgoing->end(); -} -``` - -Similarly, the text-based approach can be used to read the W3C Trace Context -from incoming requests. The following presents an example of processing an -incoming HTTP request: - -```php -$request = ServerRequestCreator::createFromGlobals(); -$context = TraceContextPropagator::getInstance()->extract($request->getHeaders()); -$root = $tracer->spanBuilder('HTTP ' . $request->getMethod()) - ->setStartTimestamp((int) ($request->getServerParams()['REQUEST_TIME_FLOAT'] * 1e9)) - ->setParent($context) - ->setSpanKind(SpanKind::KIND_SERVER) - ->startSpan(); -$scope = $root->activate(); -try { - /* do stuff */ -} finally { - $root->end(); - $scope->detach(); -} -``` - #### Sampler It is not always feasible to trace and export every user request in an diff --git a/content/en/docs/instrumentation/php/propagation.md b/content/en/docs/instrumentation/php/propagation.md new file mode 100644 index 000000000..cdd2fd7b1 --- /dev/null +++ b/content/en/docs/instrumentation/php/propagation.md @@ -0,0 +1,96 @@ +--- +title: Propagation +description: Context propagation for the PHP API +weight: 7 +--- + +Propagation is the mechanism that moves data between services and processes. +Although not limited to tracing, it is what allows traces to build causal +information about a system across services that are arbitrarily distributed +across process and network boundaries. + +OpenTelemetry provides a text-based approach to propagate context to remote +services using the [W3C Trace Context](https://www.w3.org/TR/trace-context/) +HTTP headers. + +## Context propagation with frameworks and libraries + +Auto-instrumentation exists for some popular PHP frameworks (eg Symfony, +Laravel, Slim) and HTTP libraries propagate context for incoming and outgoing +HTTP requests. + +**We highly recommend that you use auto-instrumentation or instrumentation +libraries to propagate context**. Although it is possible to propagate context +manually, the PHP auto-instrumentation and instrumentation libraries are +well-tested and easier to use. + +### Incoming + +Auto-instrumentation for frameworks which implement the +[PSR-15](https://www.php-fig.org/psr/psr-15/) `RequestHandlerInterface` will +automatically extract W3C tracecontext headers, create a root span, and set a +remote parent for the root span. + +```shell +composer require open-telemetry/opentelemetry-auto-psr15 +``` + +### Outgoing + +[PSR-18](https://www.php-fig.org/psr/psr-18/) auto-instrumentation will +automatically apply W3C tracecontext headers to outgoing HTTP requests for any +library which implements the PSR-18 interface. + +```shell +open-telemetry/opentelemetry-auto-psr18 +``` + +## Manual W3C Trace Context Propagation + +In some cases, it is not possible to propagate context with an instrumentation +library. There may not be an instrumentation library that matches a library +you're using to have services communicate with one another. Or you many have +requirements that instrumentation libraries cannot fulfill, even if they exist. + +When you must propagate context manually, you can use the context api. + +The following presents an example of an outgoing HTTP request: + +```php +$request = new Request('GET', 'http://localhost:8080/resource'); +$outgoing = $tracer->spanBuilder('/resource')->setSpanKind(SpanKind::CLIENT)->startSpan(); +$outgoing->setAttribute(TraceAttributes::HTTP_METHOD, $request->getMethod()); +$outgoing->setAttribute(TraceAttributes::HTTP_URL, (string) $request->getUri()); + +$carrier = []; +TraceContextPropagator::getInstance()->inject($carrier); +foreach ($carrier as $name => $value) { + $request = $request->withAddedHeader($name, $value); +} +try { + $response = $client->send($request); +} finally { + $outgoing->end(); +} +``` + +Similarly, the text-based approach can be used to read the W3C Trace Context +from incoming requests. The following presents an example of processing an +incoming HTTP request: + +```php +$request = ServerRequestCreator::createFromGlobals(); +$context = TraceContextPropagator::getInstance()->extract($request->getHeaders()); +$root = $tracer->spanBuilder('HTTP ' . $request->getMethod()) + ->setStartTimestamp((int) ($request->getServerParams()['REQUEST_TIME_FLOAT'] * 1e9)) + ->setParent($context) + ->setSpanKind(SpanKind::KIND_SERVER) + ->startSpan(); +$scope = $root->activate(); +try { + /* do stuff */ +} finally { + $root->end(); + $scope->detach(); +} +``` diff --git a/content/en/docs/instrumentation/php/resources.md b/content/en/docs/instrumentation/php/resources.md new file mode 100644 index 000000000..5bcb53b67 --- /dev/null +++ b/content/en/docs/instrumentation/php/resources.md @@ -0,0 +1,85 @@ +--- +title: Resources +weight: 6 +--- + +A resource represents the entity producing telemetry as resource attributes. For +example, a process producing telemetry that is running in a container on +Kubernetes has a Pod name, a namespace, and possibly a deployment name. All +three of these attributes can be included in the resource. + +In your observability backend, you can use resource information to better +investigate interesting behavior. For example, if your trace or metrics data +indicate latency in your system, you can narrow it down to a specific container, +pod, or Kubernetes deployment. + +## Resource Detection + +The PHP SDK detects resources from a variety of sources, and by default will use +all available resource detectors: + +- environment (`OTEL_RESOURCE_ATTRIBUTES`, `OTEL_SERVICE_NAME`) +- host information +- host operating system +- current process +- runtime + +## Disabling resource detection + +By default, all SDK resource detectors are used, but you can use the environment +variable `OTEL_PHP_RESOURCE_DETECTORS` to enable only certain detectors, or +completely disable them: + +- `env` +- `host` +- `os` +- `process` +- `process_runtime` +- `sdk` +- `sdk_provided` +- `all` - enable all resource detectors +- `none` - disable resource detection + +For example, to enable only the `env`, `host` and `sdk` detectors: + +```shell +env OTEL_PHP_RESOURCE_DETECTORS=env,host,sdk \ +php example.php +``` + +## Adding resources with environment variables + +If there is not an SDK detector for the resource you need, you can add arbitrary +resources via the `OTEL_RESOURCE_ATTRIBUTES` environment variable, which is +interpreted by the `env` detector. This variable takes a comma-separated list of +key=value pairs, for example: + +```shell +env OTEL_RESOURCE_ATTRIBUTES="service.name=my_service,service.namespace=demo,service.version=1.0,deployment.environment=development" \ +php example.php +``` + +## Adding resources in code + +Custom resources can also be configured in your code. Here, the default +resources (detected as described above) are merged with custom resources. The +resources are then passed to the tracer provider, where they will be associated +with all generated spans. + +```php +$resource = ResourceInfoFactory::merge(ResourceInfo::create(Attributes::create([ + ResourceAttributes::SERVICE_NAMESPACE => 'foo', + ResourceAttributes::SERVICE_NAME => 'bar', + ResourceAttributes::SERVICE_INSTANCE_ID => 1, + ResourceAttributes::SERVICE_VERSION => '0.1', + ResourceAttributes::DEPLOYMENT_ENVIRONMENT => 'development', +])), ResourceInfoFactory::defaultResource()); + +$tracerProvider = new TracerProvider( + new SimpleSpanProcessor( + (new ConsoleSpanExporterFactory())->create() + ), + null, + $resource +); +``` diff --git a/static/refcache.json b/static/refcache.json index a10968143..4830d0a46 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -3739,6 +3739,14 @@ "StatusCode": 200, "LastSeen": "2023-02-18T13:46:19.448057-05:00" }, + "https://www.php-fig.org/psr/psr-15/": { + "StatusCode": 206, + "LastSeen": "2023-02-28T03:33:34.741771102Z" + }, + "https://www.php-fig.org/psr/psr-18/": { + "StatusCode": 206, + "LastSeen": "2023-02-28T03:33:35.061283512Z" + }, "https://www.python.org/dev/peps/pep-3333/": { "StatusCode": 206, "LastSeen": "2023-02-18T13:41:14.813514-05:00"