adding php context page (#3857)
Co-authored-by: Fabrizio Ferri-Benedetti <fferribenedetti@splunk.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Phillip Carter <pcarter@fastmail.com>
This commit is contained in:
parent
422af61e73
commit
3444430949
|
|
@ -0,0 +1,178 @@
|
||||||
|
---
|
||||||
|
title: Context
|
||||||
|
weight: 55
|
||||||
|
cSpell:ignore: Swoole
|
||||||
|
description: Learn how the context API works in instrumented applications.
|
||||||
|
---
|
||||||
|
|
||||||
|
OpenTelemetry works by storing and propagating telemetry data. For example, when
|
||||||
|
an instrumented application receives a request and a span starts, the span must
|
||||||
|
be available to a component which creates child spans. To address this need,
|
||||||
|
OpenTelemetry stores the span in the active context.
|
||||||
|
|
||||||
|
## PHP execution context
|
||||||
|
|
||||||
|
The context API is globally available within a single PHP execution context, and
|
||||||
|
there can only be one [active context](#active-context) in the current execution
|
||||||
|
context.
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
|
||||||
|
Context can store values (for example, a `Span`), and it uses `Storage` to keep
|
||||||
|
track of the stored values. By default, a generic `ContextStorage` is used.
|
||||||
|
OpenTelemetry for PHP supports other context storage for less common use cases,
|
||||||
|
like asynchronous or concurrent execution with `fibers`.
|
||||||
|
|
||||||
|
## Context keys
|
||||||
|
|
||||||
|
Values as stored in context as key-value pairs. Context keys are used to store
|
||||||
|
and retrieve values from context.
|
||||||
|
|
||||||
|
Keys can be created by calling `OpenTelemetry\Context\Context::createKey()`, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use OpenTelemetry\Context\Context;
|
||||||
|
|
||||||
|
$key1 = Context::createKey('My first key');
|
||||||
|
$key2 = Context::createKey('My second key');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Active context
|
||||||
|
|
||||||
|
The active context is the context which is returned by `Context::getCurrent()`.
|
||||||
|
The context object contains entries which allow telemetry components to
|
||||||
|
communicate with each other. For example, when a span is created it can be
|
||||||
|
activated, which creates a new active context and stores the span. Later, when
|
||||||
|
another span is created it can use the span from the active context as its
|
||||||
|
parent span. If no context is active, the root context is returned, which is
|
||||||
|
just the empty context object.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use OpenTelemetry\Context\Context;
|
||||||
|
|
||||||
|
// Returns the active context
|
||||||
|
// If no context is active, the root context is returned
|
||||||
|
$context = Context::getCurrent();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set and get context values
|
||||||
|
|
||||||
|
Values are stored in Context by using the `$context->with($key, $value)` method.
|
||||||
|
Setting a context entry creates a new context with the new entry in its storage,
|
||||||
|
containing `$value`.
|
||||||
|
|
||||||
|
Context is immutable. Setting a context entry creates a new context with the new
|
||||||
|
entry in its storage: `$context->with($key, $value)`. Retrieve values using
|
||||||
|
`$context->get($key)`, for example:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use OpenTelemetry\Context\Context;
|
||||||
|
|
||||||
|
$key = Context::createKey('some key');
|
||||||
|
|
||||||
|
// add a new entry
|
||||||
|
$ctx2 = Context::getCurrent()->with($key, 'context 2');
|
||||||
|
|
||||||
|
// ctx2 contains the new entry
|
||||||
|
var_dump($ctx2->get($key)); // "context 2"
|
||||||
|
|
||||||
|
// active context is unchanged
|
||||||
|
var_dump(Context::getCurrent()->get($key)); // NULL
|
||||||
|
```
|
||||||
|
|
||||||
|
If a value is not found in the current context, then each parent is checked
|
||||||
|
until either the key is found, or the root context is reached.
|
||||||
|
|
||||||
|
### Activate a context
|
||||||
|
|
||||||
|
A context can be made active by calling `$context->activate()`.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use OpenTelemetry\Context\Context;
|
||||||
|
|
||||||
|
$key = Context::createKey('my-key');
|
||||||
|
$ctx = Context::getCurrent();
|
||||||
|
$ctx2 = $ctx->with($key, 'context 2');
|
||||||
|
$ctx2->activate();
|
||||||
|
assert($ctx2 === Context::getCurrent());
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Scope
|
||||||
|
|
||||||
|
The return value of `$context->activate()` is a `Scope`. You must `detach()` the
|
||||||
|
scope to deactivate that context, which reactivates the previously-active
|
||||||
|
context.
|
||||||
|
|
||||||
|
The return value of `$scope->detach()` is an integer. A return value of `0`
|
||||||
|
means that the scope was successfully detached. A non-zero value means that the
|
||||||
|
call was unexpected. This could happen if the context associated with the scope
|
||||||
|
was:
|
||||||
|
|
||||||
|
- Already detached
|
||||||
|
- Not a part of the current execution context
|
||||||
|
- Not the active context
|
||||||
|
|
||||||
|
#### DebugScope
|
||||||
|
|
||||||
|
To assist developers in locating issues with context and scope, there is
|
||||||
|
`DebugScope`. In a PHP runtime with assertions enabled, an activated `Context`
|
||||||
|
is wrapped in a `DebugScope`. The `DebugScope` keeps track of when the scope was
|
||||||
|
activated, and has a destructor which triggers an error if the scope was not
|
||||||
|
detached. The error output contains a backtrace of which code activated the
|
||||||
|
context.
|
||||||
|
|
||||||
|
The following code would trigger an error, complaining that a scope was not
|
||||||
|
detached, and giving a backtrace of where the scope was created:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use OpenTelemetry\Context\Context;
|
||||||
|
|
||||||
|
$key = Context::createKey('my-key');
|
||||||
|
$scope = Context::getCurrent()->with($key, 'value')->activate();
|
||||||
|
|
||||||
|
//exit without detaching $scope
|
||||||
|
```
|
||||||
|
|
||||||
|
This can be problematic in some situations, particularly in legacy applications
|
||||||
|
which might `exit` or `die`. In that case, active spans are not completed and
|
||||||
|
exported, and the `DebugScope` complains loudly.
|
||||||
|
|
||||||
|
If you understand why `DebugScope` is complaining and accept the risks, then you
|
||||||
|
can disable the feature entirely by setting `OTEL_PHP_DEBUG_SCOPES_DISABLED` to
|
||||||
|
a truthy value.
|
||||||
|
|
||||||
|
### Nested context
|
||||||
|
|
||||||
|
Active context executions can be nested. This is how traces can have nested
|
||||||
|
spans:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use OpenTelemetry\Context\Context;
|
||||||
|
|
||||||
|
$key = Context::createKey('my-key');
|
||||||
|
|
||||||
|
var_dump(Context::getCurrent()->get($key)); //NULL
|
||||||
|
$scope2 = Context::getCurrent()->with($key, 'context 2')->activate();
|
||||||
|
var_dump(Context::getCurrent()->get($key)); //'context 2'
|
||||||
|
$scope3 = Context::getCurrent()->with($key, 'context 3')->activate();
|
||||||
|
var_dump(Context::getCurrent()->get($key)); //'context 3'
|
||||||
|
|
||||||
|
$scope3->detach(); //context 2 is active
|
||||||
|
$scope2->detach(); //original context is active
|
||||||
|
var_dump(Context::getCurrent()->get($key)); //NULL
|
||||||
|
```
|
||||||
|
|
||||||
|
### Context in asynchronous environments
|
||||||
|
|
||||||
|
For asynchronous PHP programming, for example `Swoole` or the Fiber-based
|
||||||
|
`Revolt` event loop, there can be multiple active contexts, but still only one
|
||||||
|
active context per execution context.
|
||||||
|
|
||||||
|
For fiber-based implementations, `Context` is associated with the active fiber,
|
||||||
|
and forks, switches and is destroyed as appropriate by hooking into PHP's fiber
|
||||||
|
initialization, forking, and destruction handlers.
|
||||||
|
|
||||||
|
For other async implementations, custom context storage might be needed to
|
||||||
|
interoperate correctly. Check the [registry](/ecosystem/registry/?language=php)
|
||||||
|
for storage implementations.
|
||||||
Loading…
Reference in New Issue