diff --git a/hooks/OpenTelemetry/README.md b/hooks/OpenTelemetry/README.md index 67f80885..ee320e9a 100644 --- a/hooks/OpenTelemetry/README.md +++ b/hooks/OpenTelemetry/README.md @@ -12,6 +12,10 @@ OpenTelemetry is an open specification for distributed tracing, metrics, and log 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). +### Autoloading + +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. + ### OpenTelemetry Package Status 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(); For more information on OpenTelemetry, check out [their documentation](https://opentelemetry.io/docs/instrumentation/php/). +For more examples, see the [examples](./examples/). + ## Development ### PHP Versioning diff --git a/hooks/OpenTelemetry/composer.json b/hooks/OpenTelemetry/composer.json index 456d2aa8..70a3d219 100644 --- a/hooks/OpenTelemetry/composer.json +++ b/hooks/OpenTelemetry/composer.json @@ -23,7 +23,7 @@ ], "require": { "php": "^7.4 || ^8", - "open-feature/sdk": "^1.1.0", + "open-feature/sdk": "^1.2.0", "open-telemetry/api": "^0.0.17" }, "require-dev": { @@ -54,7 +54,10 @@ "autoload": { "psr-4": { "OpenFeature\\Hooks\\OpenTelemetry\\": "src" - } + }, + "files": [ + "src/_autoload.php" + ] }, "autoload-dev": { "psr-4": { @@ -109,7 +112,7 @@ "dev:test:unit:teardown": "echo 'Tore down for unit tests...'", "dev:test:integration": [ "@dev:test:integration:setup", - "echo 'No integration tests to run'", + "phpunit --colors=always --testdox --testsuite=integration", "@dev:test:integration:teardown" ], "dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", diff --git a/hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md new file mode 100644 index 00000000..6162d7f2 --- /dev/null +++ b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md @@ -0,0 +1,5 @@ +# OpenFeature OpenTelemetry Hook example + +This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature. + +It showcases the auto-instrumentation functionality of OpenFeature and OpenTelemetry, neither of which requiring imperative interactions with OTel to bootstrap, configure, and utilize it. diff --git a/hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json new file mode 100644 index 00000000..f2116e92 --- /dev/null +++ b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json @@ -0,0 +1,16 @@ +{ + "name": "open-feature/otel-manual-instrumentation-example", + "description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation", + "type": "project", + "license": "Apache-2.0", + "authors": [ + { + "name": "Tom Carrio", + "email": "tom@carrio.dev" + } + ], + "require": { + "open-telemetry/api": "0.0.17", + "open-feature/sdk": "^1.2.0" + } +} diff --git a/hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php new file mode 100644 index 00000000..a15aa1a3 --- /dev/null +++ b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php @@ -0,0 +1,25 @@ +getClient('dev.openfeature.contrib.php.demo', '1.0.0'); + +$version = $client->getStringValue('dev.openfeature.contrib.php.version-value', 'unknown'); + +echo 'Version is ' . $version; \ No newline at end of file diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md index 9e88acd4..b4cfaad7 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md @@ -1,3 +1,5 @@ # OpenFeature OpenTelemetry Hook example This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature. + +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. \ No newline at end of file diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json index d0b77990..b1121bbb 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json @@ -3,11 +3,6 @@ "description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation", "type": "project", "license": "Apache-2.0", - "autoload": { - "psr-4": { - "OpenFeature\\Providers\\Examples\\OTelManualInstrumentation\\": "src/" - } - }, "authors": [ { "name": "Tom Carrio", @@ -22,6 +17,6 @@ "php-di/slim-bridge": "^3.2", "open-telemetry/api": "0.0.17", "open-telemetry/sdk": "0.0.17", - "open-feature/sdk": "^1.1" + "open-feature/sdk": "^1.2.0" } } diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php index 2be1d732..59ecf457 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php @@ -32,7 +32,7 @@ use Psr\Http\Server\RequestHandlerInterface as RequestHandler; use Slim\Routing\RouteContext; -// Registering the OTel hook requires only the following! +// Manually registering the OTel hook requires only the following! // The rest of the work is simply using OpenFeature as you normally would // The current context span will be used to emit trace events. OpenTelemetryHook::register(); diff --git a/hooks/OpenTelemetry/src/OpenTelemetryHook.php b/hooks/OpenTelemetry/src/OpenTelemetryHook.php index 2f215522..790a6c55 100644 --- a/hooks/OpenTelemetry/src/OpenTelemetryHook.php +++ b/hooks/OpenTelemetry/src/OpenTelemetryHook.php @@ -42,7 +42,7 @@ public static function register(): void self::$instance = new OpenTelemetryHook(); } - if (self::$registeredHook) { + if (self::$registeredHook && self::isRegisteredInHooks()) { return; } @@ -88,4 +88,21 @@ public function supportsFlagValueType(string $flagValueType): bool { return true; } + + /** + * Hooks can be cleared by other means so we can't simply memoize whether a registration has occurred + * + * However if no registration has yet happened then we can absolutely determine that the hook will + * not be registered yet. + */ + private static function isRegisteredInHooks(): bool + { + foreach (OpenFeatureAPI::getInstance()->getHooks() as $hook) { + if ($hook instanceof OpenTelemetryHook) { + return true; + } + } + + return false; + } } diff --git a/hooks/OpenTelemetry/src/_autoload.php b/hooks/OpenTelemetry/src/_autoload.php new file mode 100644 index 00000000..69fb8174 --- /dev/null +++ b/hooks/OpenTelemetry/src/_autoload.php @@ -0,0 +1,6 @@ +clearHooks(); + + // When + $this->simulateAutoload(); + + // Then + + $this->assertCount(1, $api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } + public function testCanBeRegistered(): void { // Given $api = OpenFeatureAPI::getInstance(); + $api->clearHooks(); // When OpenTelemetryHook::register(); // Then - $this->assertNotEmpty($api->getHooks()); + $this->assertCount(1, $api->getHooks()); $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); } + + private function simulateAutoload(): void + { + require __DIR__ . '/../../src/_autoload.php'; + } } diff --git a/providers/CloudBees/composer.json b/providers/CloudBees/composer.json index a3f3c6d8..2a306099 100644 --- a/providers/CloudBees/composer.json +++ b/providers/CloudBees/composer.json @@ -24,7 +24,7 @@ ], "require": { "php": "^7.4 || ^8", - "open-feature/sdk": "^1.0.0", + "open-feature/sdk": "^1.2.0", "rollout/rox": "^5.0" }, "require-dev": { diff --git a/providers/CloudBees/examples/CloudBees/composer.json b/providers/CloudBees/examples/CloudBees/composer.json index 9d2e626d..7ff5ca9e 100644 --- a/providers/CloudBees/examples/CloudBees/composer.json +++ b/providers/CloudBees/examples/CloudBees/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "open-feature/sdk": "^0.0.5", + "open-feature/sdk": "^1.2.0", "open-feature/cloudbees-provider": "^0.0.1" } } diff --git a/providers/Flagd/examples/Grpc/composer.json b/providers/Flagd/examples/Grpc/composer.json index fea77ede..15466ff5 100644 --- a/providers/Flagd/examples/Grpc/composer.json +++ b/providers/Flagd/examples/Grpc/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "open-feature/sdk": "^0.0.5", + "open-feature/sdk": "^1.2.0", "monolog/monolog": "^2.8" } } diff --git a/providers/Flagd/examples/Http/composer.json b/providers/Flagd/examples/Http/composer.json index 767fed55..317e70d5 100644 --- a/providers/Flagd/examples/Http/composer.json +++ b/providers/Flagd/examples/Http/composer.json @@ -15,6 +15,6 @@ } ], "require": { - "open-feature/sdk": "^0.0.5" + "open-feature/sdk": "^1.2.0" } } diff --git a/providers/Split/composer.json b/providers/Split/composer.json index 3eee1b7f..c0083d01 100644 --- a/providers/Split/composer.json +++ b/providers/Split/composer.json @@ -23,7 +23,7 @@ ], "require": { "php": "^7.4 || ^8", - "open-feature/sdk": "^1.1.0", + "open-feature/sdk": "^1.2.0", "splitsoftware/split-sdk-php": "^7.1" }, "require-dev": { diff --git a/providers/Split/examples/SplitSDK/composer.json b/providers/Split/examples/SplitSDK/composer.json index d5a1f317..8fdcef70 100644 --- a/providers/Split/examples/SplitSDK/composer.json +++ b/providers/Split/examples/SplitSDK/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "open-feature/sdk": "^0.0.5", + "open-feature/sdk": "^1.2.0", "open-feature/split-provider": "^0.0.1" } }