Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve open-telemetry/context documentation #830

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .phan/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@
'PhanAccessClassInternal',
'PhanAccessMethodInternal',
'PhanAccessPropertyInternal',
'PhanTemplateTypeNotUsedInFunctionReturn',
],

// A regular expression to match files to be excluded
Expand Down
66 changes: 55 additions & 11 deletions src/Context/ContextInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,83 @@

namespace OpenTelemetry\Context;

/**
* Immutable execution scoped propagation mechanism.
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#context
*/
interface ContextInterface
{
/**
* @param non-empty-string $key
* Creates a new context key.
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/context.md#create-a-key
* @param non-empty-string $key name of the key
* @return ContextKeyInterface created key
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#create-a-key
*/
public static function createKey(string $key): ContextKeyInterface;

/**
* Returns the current context.
*
* @return ContextInterface current context
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#get-current-context
*/
public static function getCurrent(): ContextInterface;

/**
* Makes `$this` the currently active {@see ContextInterface}.
* Attaches this context as active context.
*
* The returned scope has to be {@link ScopeInterface::detach()}ed. In most
* cases this should be done using a `try-finally` statement:
* ```php
* $scope = $context->activate();
* try {
* // ...
* } finally {
* $scope->detach();
* }
* ```
*
* @return ScopeInterface scope to detach the context and restore the previous
* context
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#attach-context
*/
public function activate(): ScopeInterface;

/**
* This adds a key/value pair to this Context.
* Returns a context with the given key set to the given value.
*
* @template T
* @param ContextKeyInterface<T> $key key to set
* @param T|null $value value to set
* @return ContextInterface a context with the given key set to `$value`
*
* @psalm-template T
* @psalm-param ContextKeyInterface<T> $key
* @psalm-param T|null $value
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#set-value
*/
public function with(ContextKeyInterface $key, $value): ContextInterface;

/**
* Returns a context with the given value set.
*
* @param ImplicitContextKeyedInterface $value value to set
* @return ContextInterface a context with the given `$value`
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#set-value
*/
public function withContextValue(ImplicitContextKeyedInterface $value): ContextInterface;

/**
* Fetch a value from the Context given a key value.
* Returns the value assigned to the given key.
*
* @template T
* @param ContextKeyInterface<T> $key key to get
* @return T|null value assigned to `$key`, or null if no such value exists
*
* @psalm-template T
* @psalm-param ContextKeyInterface<T> $key
* @psalm-return T|null
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#get-value
*/
public function get(ContextKeyInterface $key);
}
18 changes: 18 additions & 0 deletions src/Context/ContextStorageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,27 @@

interface ContextStorageInterface
{
/**
* Returns the current scope.
*
* @return ContextStorageScopeInterface|null current scope, or null if no
* scope was attached in the current execution unit
*/
public function scope(): ?ContextStorageScopeInterface;

/**
* Returns the current context.
*
* @return ContextInterface current context
*/
public function current(): ContextInterface;

/**
* Attaches the context as active context.
*
* @param ContextInterface $context context to attach
* @return ContextStorageScopeInterface scope to detach the context and
* restore the previous context
*/
public function attach(ContextInterface $context): ContextStorageScopeInterface;
}
5 changes: 5 additions & 0 deletions src/Context/ContextStorageScopeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

interface ContextStorageScopeInterface extends ScopeInterface, ArrayAccess
{
/**
* Returns the context associated with this scope.
*
* @return ContextInterface associated context
*/
public function context(): ContextInterface;

/**
Expand Down
51 changes: 51 additions & 0 deletions src/Context/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,52 @@
# OpenTelemetry Context

Immutable execution scoped propagation mechanism, for further details see [opentelemetry-specification][1].

## Installation

```shell
composer require open-telemetry/context
```

## Usage

### Implicit propagation

```php
$context = Context::getCurrent();
// modify context
$scope = $context->activate();
try {
// run within new context
} finally {
$scope->detach();
}
```

It is recommended to use a `try-finally` statement after `::activate()` to ensure that the created scope is properly `::detach()`ed.

## Async applications

### Fiber support

Requires `PHP >= 8.1`, `ext-ffi` and setting the environment variable `OTEL_PHP_FIBERS_ENABLED` to a truthy value. Additionally `vendor/autoload.php` has to be preloaded for non-CLI SAPIs if [`ffi.enable`](https://www.php.net/manual/en/ffi.configuration.php#ini.ffi.enable) is set to `preload`.

### Event loops

Event loops have to restore the original context on callback execution. A basic implementation could look like the following, though implementations should avoid keeping unnecessary references to arguments if possible:

```php
function bindContext(Closure $closure): Closure {
$context = Context::getCurrent();
return static function (mixed ...$args) use ($closure, $context): mixed {
$scope = $context->activate();
try {
return $closure(...$args);
} finally {
$scope->detach();
}
};
}
```

[1]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#context
5 changes: 4 additions & 1 deletion src/Context/ScopeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@

interface ScopeInterface
{
/** Already detached. */
public const DETACHED = 1 << (PHP_INT_SIZE << 3) - 1;
/** Execution context inactive. */
public const INACTIVE = 1 << (PHP_INT_SIZE << 3) - 2;
/** Not current context. */
public const MISMATCH = 1 << (PHP_INT_SIZE << 3) - 3;

/**
Expand All @@ -23,7 +26,7 @@ interface ScopeInterface
* @see self::INACTIVE
* @see self::MISMATCH
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/specification/context/context.md#detach-context
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md#detach-context
*/
public function detach(): int;
}
2 changes: 1 addition & 1 deletion src/Context/composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "open-telemetry/context",
"description": "Context implementation for OpenTelemetry PHP.",
"keywords": ["opentelemetry", "otel", "metrics", "tracing", "logging", "apm", "context"],
"keywords": ["opentelemetry", "otel", "context"],
"type": "library",
"license": "Apache-2.0",
"authors": [
Expand Down