Skip to content

Commit

Permalink
Add traceresponse propagator
Browse files Browse the repository at this point in the history
Cleanup dependencies

Add PHPStan config and clean code

Allow PHP 7 compatible symfony/http-client

Add TraceResponse to .gitsplit

Fix test method casing
  • Loading branch information
cedricziel committed Apr 7, 2023
1 parent f897e94 commit 24632e7
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
'Instrumentation/PDO',
'Instrumentation/Symfony',
'Instrumentation/Laravel',
'Propagation/TraceResponse',
'Symfony'
]
exclude:
Expand Down
2 changes: 2 additions & 0 deletions .gitsplit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ splits:
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/context-swoole.git"
- prefix: "src/AutoInstrumentationInstaller"
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-instrumentation-installer.git"
- prefix: "src/Propagation/TraceResponse"
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-propagator-traceresponse.git"

# List of references to split (defined as regexp)
origins:
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"OpenTelemetry\\Contrib\\Symfony\\": "src/Symfony/src",
"OpenTelemetry\\Contrib\\Instrumentation\\Psr15\\": "src/Instrumentation/Psr15/src",
"OpenTelemetry\\Contrib\\Instrumentation\\Slim\\": "src/Instrumentation/Slim/src",
"OpenTelemetry\\Contrib\\Instrumentation\\Wordpress\\": "src/Instrumentation/Wordpress/src"
"OpenTelemetry\\Contrib\\Instrumentation\\Wordpress\\": "src/Instrumentation/Wordpress/src",
"OpenTelemetry\\Contrib\\Propagation\\TraceResponse\\": "src/Propagation/TraceResponse/src"
}
},
"config": {
Expand Down
43 changes: 43 additions & 0 deletions src/Propagation/TraceResponse/.php-cs-fixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
$finder = PhpCsFixer\Finder::create()
->exclude('vendor')
->exclude('var/cache')
->in(__DIR__);

$config = new PhpCsFixer\Config();
return $config->setRules([
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'none'],
'is_null' => true,
'modernize_types_casting' => true,
'ordered_imports' => true,
'php_unit_construct' => true,
'single_line_comment_style' => true,
'yoda_style' => false,
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => true,
'cast_spaces' => true,
'declare_strict_types' => true,
'function_typehint_space' => true,
'include' => true,
'lowercase_cast' => true,
'new_with_braces' => true,
'no_extra_blank_lines' => true,
'no_leading_import_slash' => true,
'echo_tag_syntax' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'phpdoc_order' => true,
'phpdoc_scalar' => true,
'phpdoc_types' => true,
'short_scalar_cast' => true,
'single_blank_line_before_namespace' => true,
'single_quote' => true,
'trailing_comma_in_multiline' => true,
])
->setRiskyAllowed(true)
->setFinder($finder);

56 changes: 56 additions & 0 deletions src/Propagation/TraceResponse/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# OpenTelemetry TraceResponse Propagator

**Note:** This package is experimental as `traceresponse` is currently an editors' draft.

This package provides a [Trace Context HTTP Response Headers Format](https://w3c.github.io/trace-context/#trace-context-http-response-headers-format)
propagator to inject the current span context into Response datastructures.

The main goal is to allow client-side technology (Real User Monitoring, HTTP Clients) to record
the server side context in order to allow referencing it.

## Requirements

* OpenTelemetry SDK and exporters (required to actually export traces)

Optional:
* OpenTelemetry extension (Some instrumentations can automatically use the `TraceResponsePropagator`)

## Usage

Assuming there is an active `SpanContext`, you can inject it into your response as follows:

```php
// your framework probably provides a datastructure to model HTTP responses
// and allows you to hook into the end of a request / listen to a matching event.
$response = new Response();

// get the current scope, bail out if none
$scope = Context::storage()->scope();
if (null === $scope) {
return;
}

// create a PropagationSetterInterface that knows how to inject response headers
$propagationSetter = new class implements OpenTelemetry\Context\Propagation\PropagationSetterInterface {
public function set(&$carrier, string $key, string $value) : void {
$carrier->headers->set($key, $value);
}
};
$propagator = new TraceResponseProgator();
$propagator->inject($response, $propagationSetter, $scope->context());
```

## Installation via composer

```bash
$ composer require open-telemetry/opentelemetry-propagation-traceresponse
```

## Installing dependencies and executing tests

From TraceResponse subdirectory:

```bash
$ composer install
$ ./vendor/bin/phpunit tests
```
39 changes: 39 additions & 0 deletions src/Propagation/TraceResponse/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "open-telemetry/opentelemetry-propagation-traceresponse",
"description": "OpenTelemetry traceresponse propagator.",
"keywords": ["opentelemetry", "otel", "open-telemetry", "propagator", "traceresponse"],
"type": "library",
"homepage": "https://opentelemetry.io/docs/php",
"readme": "./README.md",
"license": "Apache-2.0",
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^7.0|^8.0",
"open-telemetry/context": "^1.0"
},
"autoload": {
"psr-4": {
"OpenTelemetry\\Contrib\\Propagation\\TraceResponse\\": "src/"
}
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3",
"phan/phan": "^5.0",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"psalm/plugin-phpunit": "^0.16",
"open-telemetry/sdk": "^1.0",
"phpunit/phpunit": "^9.5",
"vimeo/psalm": "^4.0",
"symfony/http-client": "^5.4|^6.0",
"guzzlehttp/promises": "^1.5",
"php-http/message-factory": "^1.0",
"nyholm/psr7": "^1.5"
},
"config": {
"allow-plugins": {
"php-http/discovery": true
}
}
}
9 changes: 9 additions & 0 deletions src/Propagation/TraceResponse/phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon

parameters:
tmpDir: var/cache/phpstan
level: 5
paths:
- src
- tests
44 changes: 44 additions & 0 deletions src/Propagation/TraceResponse/phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
cacheResult="false"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
timeoutForSmallTests="1"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
verbose="true">

<coverage processUncoveredFiles="true" disableCodeCoverageIgnore="false">
<include>
<directory>src</directory>
</include>
</coverage>

<php>
<ini name="date.timezone" value="UTC" />
<ini name="display_errors" value="On" />
<ini name="display_startup_errors" value="On" />
<ini name="error_reporting" value="E_ALL" />
</php>

<testsuites>
<testsuite name="unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>

</phpunit>
15 changes: 15 additions & 0 deletions src/Propagation/TraceResponse/psalm.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<psalm
errorLevel="3"
cacheDirectory="var/cache/psalm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd">
<projectFiles>
<directory name="src"/>
<directory name="tests"/>
</projectFiles>
<plugins>
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
</plugins>
</psalm>
24 changes: 24 additions & 0 deletions src/Propagation/TraceResponse/src/ResponsePropagator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\Contrib\Propagation\TraceResponse;

use OpenTelemetry\Context\ContextInterface;
use OpenTelemetry\Context\Propagation\PropagationSetterInterface;

/**
* This propagator type is used to inject the trace-context into HTTP responses.
*/
interface ResponsePropagator
{
/**
* Injects specific values from the provided {@see ContextInterface} into the provided carrier
* via an {@see PropagationSetterInterface}.
*
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#textmap-inject
*
* @param mixed $carrier
*/
public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void;
}
50 changes: 50 additions & 0 deletions src/Propagation/TraceResponse/src/TraceResponsePropagator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\Contrib\Propagation\TraceResponse;

use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\ContextInterface;
use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter;
use OpenTelemetry\Context\Propagation\PropagationSetterInterface;

/**
* Provides a ResponsePropagator for the Trace Context HTTP Response Headers Format
*
* @see https://w3c.github.io/trace-context/#trace-context-http-response-headers-format
*/
final class TraceResponsePropagator implements ResponsePropagator
{
const IS_SAMPLED = '1';
const NOT_SAMPLED = '0';
const SUPPORTED_VERSION = '00';
const TRACERESPONSE = 'traceresponse';

public function fields(): array
{
return [
self::TRACERESPONSE,
];
}

public function inject(&$carrier, ?PropagationSetterInterface $setter = null, ?ContextInterface $context = null): void
{
$setter = $setter ?? ArrayAccessGetterSetter::getInstance();
$context = $context ?? Context::getCurrent();
$spanContext = Span::fromContext($context)->getContext();

if (!$spanContext->isValid()) {
return;
}

$traceId = $spanContext->getTraceId();
$spanId = $spanContext->getSpanId();

$samplingFlag = $spanContext->isSampled() ? self::IS_SAMPLED : self::NOT_SAMPLED;

$header = self::SUPPORTED_VERSION . '-' . $traceId . '-' . $spanId . '-' . $samplingFlag;
$setter->set($carrier, self::TRACERESPONSE, $header);
}
}
Loading

0 comments on commit 24632e7

Please sign in to comment.