Skip to content

Commit 789a95c

Browse files
authored
feat(otel-hook): autoload registration of otel hook (#25)
* feat(otel-hook): autoload registration of otel hook Signed-off-by: Tom Carrio <[email protected]> * test: implement tests and ensure correct handling of global hook state Signed-off-by: Tom Carrio <[email protected]> * refactor: simulate autoload via self-documenting method call Signed-off-by: Tom Carrio <[email protected]> * test: update to support 7.4+ Signed-off-by: Tom Carrio <[email protected]> * docs: info on autoloading in readme Signed-off-by: Tom Carrio <[email protected]> * test: always require in test case Signed-off-by: Tom Carrio <[email protected]> * test: always assert size 1 Signed-off-by: Tom Carrio <[email protected]> * fix: unused imports Signed-off-by: Tom Carrio <[email protected]> * refactor: rename test case for autoloading Signed-off-by: Tom Carrio <[email protected]> * docs: update all examples and include autoinstrument example Signed-off-by: Tom Carrio <[email protected]> * chore: update all open-feature/sdk to 1.2.0 (latest) Signed-off-by: Tom Carrio <[email protected]> Signed-off-by: Tom Carrio <[email protected]>
1 parent cdad575 commit 789a95c

File tree

17 files changed

+114
-18
lines changed

17 files changed

+114
-18
lines changed

hooks/OpenTelemetry/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ OpenTelemetry is an open specification for distributed tracing, metrics, and log
1212

1313
This package also builds on various PSRs (PHP Standards Recommendations) such as the Logger interfaces (PSR-3) and the Basic and Extended Coding Standards (PSR-1 and PSR-12).
1414

15+
### Autoloading
16+
17+
This package supports Composer autoloading. Thus, simply installing the package is all you need in order to immediately get started with OpenTracing for OpenFeature! Examples are provided that showcase the simple setup as well. Check out the Usage section for more info.
18+
1519
### OpenTelemetry Package Status
1620

1721
The OpenTelemetry package for PHP is still in beta, so there could be changes required. However, it exposes global primitives for span retrieval that should not require any configuration upfront for the provider to just work.
@@ -37,6 +41,8 @@ OpenTelemetryHook::register();
3741

3842
For more information on OpenTelemetry, check out [their documentation](https://opentelemetry.io/docs/instrumentation/php/).
3943

44+
For more examples, see the [examples](./examples/).
45+
4046
## Development
4147

4248
### PHP Versioning

hooks/OpenTelemetry/composer.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
],
2424
"require": {
2525
"php": "^7.4 || ^8",
26-
"open-feature/sdk": "^1.1.0",
26+
"open-feature/sdk": "^1.2.0",
2727
"open-telemetry/api": "^0.0.17"
2828
},
2929
"require-dev": {
@@ -54,7 +54,10 @@
5454
"autoload": {
5555
"psr-4": {
5656
"OpenFeature\\Hooks\\OpenTelemetry\\": "src"
57-
}
57+
},
58+
"files": [
59+
"src/_autoload.php"
60+
]
5861
},
5962
"autoload-dev": {
6063
"psr-4": {
@@ -109,7 +112,7 @@
109112
"dev:test:unit:teardown": "echo 'Tore down for unit tests...'",
110113
"dev:test:integration": [
111114
"@dev:test:integration:setup",
112-
"echo 'No integration tests to run'",
115+
"phpunit --colors=always --testdox --testsuite=integration",
113116
"@dev:test:integration:teardown"
114117
],
115118
"dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# OpenFeature OpenTelemetry Hook example
2+
3+
This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature.
4+
5+
It showcases the auto-instrumentation functionality of OpenFeature and OpenTelemetry, neither of which requiring imperative interactions with OTel to bootstrap, configure, and utilize it.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "open-feature/otel-manual-instrumentation-example",
3+
"description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation",
4+
"type": "project",
5+
"license": "Apache-2.0",
6+
"authors": [
7+
{
8+
"name": "Tom Carrio",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"require": {
13+
"open-telemetry/api": "0.0.17",
14+
"open-feature/sdk": "^1.2.0"
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use OpenFeature\OpenFeatureAPI;
6+
7+
putenv('OTEL_PHP_AUTOLOAD_ENABLED=true');
8+
putenv('OTEL_TRACES_EXPORTER=otlp');
9+
putenv('OTEL_EXPORTER_OTLP_PROTOCOL=grpc');
10+
putenv('OTEL_METRICS_EXPORTER=otlp');
11+
putenv('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=grpc');
12+
putenv('OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317');
13+
putenv('OTEL_PHP_TRACES_PROCESSOR=batch');
14+
putenv('OTEL_PROPAGATORS=b3,baggage,tracecontext');
15+
16+
echo 'autoloading SDK example starting...' . PHP_EOL;
17+
18+
// Composer autoloader will execute SDK/_autoload.php which will register global instrumentation from environment configuration
19+
require dirname(__DIR__) . '/vendor/autoload.php';
20+
21+
$client = OpenFeatureAPI::getInstance()->getClient('dev.openfeature.contrib.php.demo', '1.0.0');
22+
23+
$version = $client->getStringValue('dev.openfeature.contrib.php.version-value', 'unknown');
24+
25+
echo 'Version is ' . $version;
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# OpenFeature OpenTelemetry Hook example
22

33
This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature.
4+
5+
It showcases how you can manually configure the OTel SDK for metrics, tracing, and more. This is then utilized under the hood by OpenFeature within its hook lifecycles to report the feature flag semantic events via the tracer.

hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json

+1-6
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@
33
"description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation",
44
"type": "project",
55
"license": "Apache-2.0",
6-
"autoload": {
7-
"psr-4": {
8-
"OpenFeature\\Providers\\Examples\\OTelManualInstrumentation\\": "src/"
9-
}
10-
},
116
"authors": [
127
{
138
"name": "Tom Carrio",
@@ -22,6 +17,6 @@
2217
"php-di/slim-bridge": "^3.2",
2318
"open-telemetry/api": "0.0.17",
2419
"open-telemetry/sdk": "0.0.17",
25-
"open-feature/sdk": "^1.1"
20+
"open-feature/sdk": "^1.2.0"
2621
}
2722
}

hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
3333
use Slim\Routing\RouteContext;
3434

35-
// Registering the OTel hook requires only the following!
35+
// Manually registering the OTel hook requires only the following!
3636
// The rest of the work is simply using OpenFeature as you normally would
3737
// The current context span will be used to emit trace events.
3838
OpenTelemetryHook::register();

hooks/OpenTelemetry/src/OpenTelemetryHook.php

+18-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public static function register(): void
4242
self::$instance = new OpenTelemetryHook();
4343
}
4444

45-
if (self::$registeredHook) {
45+
if (self::$registeredHook && self::isRegisteredInHooks()) {
4646
return;
4747
}
4848

@@ -88,4 +88,21 @@ public function supportsFlagValueType(string $flagValueType): bool
8888
{
8989
return true;
9090
}
91+
92+
/**
93+
* Hooks can be cleared by other means so we can't simply memoize whether a registration has occurred
94+
*
95+
* However if no registration has yet happened then we can absolutely determine that the hook will
96+
* not be registered yet.
97+
*/
98+
private static function isRegisteredInHooks(): bool
99+
{
100+
foreach (OpenFeatureAPI::getInstance()->getHooks() as $hook) {
101+
if ($hook instanceof OpenTelemetryHook) {
102+
return true;
103+
}
104+
}
105+
106+
return false;
107+
}
91108
}

hooks/OpenTelemetry/src/_autoload.php

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
// automatically registers the OTel hook for OpenFeature
6+
OpenFeature\Hooks\OpenTelemetry\OpenTelemetryHook::register();

hooks/OpenTelemetry/tests/integration/OpenTelemetryHookTest.php

+22-1
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,37 @@
1111

1212
class OpenTelemetryHookTest extends TestCase
1313
{
14+
public function testAutoload(): void
15+
{
16+
// Given
17+
$api = OpenFeatureAPI::getInstance();
18+
$api->clearHooks();
19+
20+
// When
21+
$this->simulateAutoload();
22+
23+
// Then
24+
25+
$this->assertCount(1, $api->getHooks());
26+
$this->assertInstanceOf(Hook::class, $api->getHooks()[0]);
27+
}
28+
1429
public function testCanBeRegistered(): void
1530
{
1631
// Given
1732
$api = OpenFeatureAPI::getInstance();
33+
$api->clearHooks();
1834

1935
// When
2036
OpenTelemetryHook::register();
2137

2238
// Then
23-
$this->assertNotEmpty($api->getHooks());
39+
$this->assertCount(1, $api->getHooks());
2440
$this->assertInstanceOf(Hook::class, $api->getHooks()[0]);
2541
}
42+
43+
private function simulateAutoload(): void
44+
{
45+
require __DIR__ . '/../../src/_autoload.php';
46+
}
2647
}

providers/CloudBees/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
],
2525
"require": {
2626
"php": "^7.4 || ^8",
27-
"open-feature/sdk": "^1.0.0",
27+
"open-feature/sdk": "^1.2.0",
2828
"rollout/rox": "^5.0"
2929
},
3030
"require-dev": {

providers/CloudBees/examples/CloudBees/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616
],
1717
"require": {
18-
"open-feature/sdk": "^0.0.5",
18+
"open-feature/sdk": "^1.2.0",
1919
"open-feature/cloudbees-provider": "^0.0.1"
2020
}
2121
}

providers/Flagd/examples/Grpc/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616
],
1717
"require": {
18-
"open-feature/sdk": "^0.0.5",
18+
"open-feature/sdk": "^1.2.0",
1919
"monolog/monolog": "^2.8"
2020
}
2121
}

providers/Flagd/examples/Http/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
}
1616
],
1717
"require": {
18-
"open-feature/sdk": "^0.0.5"
18+
"open-feature/sdk": "^1.2.0"
1919
}
2020
}

providers/Split/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
],
2424
"require": {
2525
"php": "^7.4 || ^8",
26-
"open-feature/sdk": "^1.1.0",
26+
"open-feature/sdk": "^1.2.0",
2727
"splitsoftware/split-sdk-php": "^7.1"
2828
},
2929
"require-dev": {

providers/Split/examples/SplitSDK/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616
],
1717
"require": {
18-
"open-feature/sdk": "^0.0.5",
18+
"open-feature/sdk": "^1.2.0",
1919
"open-feature/split-provider": "^0.0.1"
2020
}
2121
}

0 commit comments

Comments
 (0)