Skip to content

Commit fec9a78

Browse files
authored
Allows API packages to specify file-based and env-based config (#1621)
* Move `ComponentProvider` and related classes to API * Use API `ComponentProvider` * Use API `ComponentProvider` in tests * Add `EnvComponentLoader` API * Add `EnvComponentLoader` example * Ignore deptrac violations * Remove namespace from `ComponentProvider` BC layer * Add API requirement to config package * Fix/suppress unrelated phpstan errors caused by `google/protobuf` `^4.31`
1 parent 4e3bb38 commit fec9a78

File tree

10 files changed

+381
-1
lines changed

10 files changed

+381
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration\Config;
6+
7+
use function class_alias;
8+
use OpenTelemetry\API\Configuration\Context;
9+
10+
/**
11+
* A component plugin that can be used to create a component.
12+
*
13+
* @template T
14+
*/
15+
interface ComponentPlugin
16+
{
17+
/**
18+
* Creates the component that is provided by this plugin.
19+
*
20+
* @param Context $context context used for creation
21+
* @return T created component
22+
*/
23+
public function create(Context $context): mixed;
24+
}
25+
26+
/** @phpstan-ignore-next-line @phan-suppress-next-line PhanUndeclaredClassReference */
27+
class_alias(ComponentPlugin::class, \OpenTelemetry\Config\SDK\Configuration\ComponentPlugin::class);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration\Config;
6+
7+
use function class_alias;
8+
use OpenTelemetry\API\Configuration\Context;
9+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
10+
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
11+
12+
/**
13+
* A component provider is responsible for interpreting configuration and returning an
14+
* implementation of a particular type.
15+
*
16+
* @template T
17+
*/
18+
interface ComponentProvider
19+
{
20+
/**
21+
* @param array $properties properties provided for this component provider
22+
* @param Context $context context that should be used to resolve component plugins
23+
* @return T created component, typehint has to specify the component type that is
24+
* provided by this component provider
25+
*
26+
* @see ComponentPlugin::create()
27+
*/
28+
public function createPlugin(array $properties, Context $context): mixed;
29+
30+
/**
31+
* Returns an array node describing the properties of this component provider.
32+
*
33+
* @param ComponentProviderRegistry $registry registry containing all available component providers
34+
* @param NodeBuilder $builder node builder used to create configuration nodes
35+
* @return ArrayNodeDefinition array node describing the properties
36+
*
37+
* @see ComponentProviderRegistry::component()
38+
* @see ComponentProviderRegistry::componentList()
39+
* @see ComponentProviderRegistry::componentNames()
40+
*/
41+
public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition;
42+
}
43+
44+
/** @phpstan-ignore-next-line @phan-suppress-next-line PhanUndeclaredClassReference */
45+
class_alias(ComponentProvider::class, \OpenTelemetry\Config\SDK\Configuration\ComponentProvider::class);
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration\Config;
6+
7+
use function class_alias;
8+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
9+
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
10+
11+
/**
12+
* A registry of component providers.
13+
*/
14+
interface ComponentProviderRegistry
15+
{
16+
/**
17+
* Creates a node to specify a component plugin.
18+
*
19+
* `$name: ?ComponentPlugin<$type>`
20+
*
21+
* ```
22+
* $name:
23+
* provider1:
24+
* property: value
25+
* anotherProperty: value
26+
* ```
27+
*
28+
* @param string $name name of configuration node
29+
* @param string $type type of the component plugin
30+
*/
31+
public function component(string $name, string $type): NodeDefinition;
32+
33+
/**
34+
* Creates a node to specify a list of component plugin.
35+
*
36+
* `$name: list<ComponentPlugin<$type>>`
37+
*
38+
* ```
39+
* $name:
40+
* - provider1:
41+
* property: value
42+
* anotherProperty: value
43+
* - provider2:
44+
* property: value
45+
* anotherProperty: value
46+
* ```
47+
*
48+
* @param string $name name of configuration node
49+
* @param string $type type of the component plugin
50+
*/
51+
public function componentList(string $name, string $type): ArrayNodeDefinition;
52+
53+
/**
54+
* Creates a node to specify a map of component plugin.
55+
*
56+
* `$name: list<ComponentPlugin<$type>>`
57+
*
58+
* ```
59+
* $name:
60+
* provider1:
61+
* property: value
62+
* anotherProperty: value
63+
* provider2:
64+
* property: value
65+
* anotherProperty: value
66+
* ```
67+
*
68+
* @param string $name name of configuration node
69+
* @param string $type type of the component plugin
70+
*/
71+
public function componentMap(string $name, string $type): ArrayNodeDefinition;
72+
73+
/**
74+
* Creates a node to specify a list of component plugin names.
75+
*
76+
* The providers cannot have required properties.
77+
*
78+
* `$name: list<ComponentPlugin<$type>>`
79+
*
80+
* ```
81+
* $name: [provider1, provider2]
82+
* ```
83+
*
84+
* @param string $name name of configuration node
85+
* @param string $type type of the component plugin
86+
*/
87+
public function componentNames(string $name, string $type): ArrayNodeDefinition;
88+
}
89+
90+
/** @phpstan-ignore-next-line @phan-suppress-next-line PhanUndeclaredClassReference */
91+
class_alias(ComponentProviderRegistry::class, \OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry::class);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration\ConfigEnv;
6+
7+
use OpenTelemetry\API\Configuration\Context;
8+
9+
/**
10+
* @template T
11+
*/
12+
interface EnvComponentLoader
13+
{
14+
/**
15+
* @psalm-return T
16+
*/
17+
public function load(EnvResolver $env, EnvComponentLoaderRegistry $registry, Context $context): mixed;
18+
19+
public function name(): string;
20+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration\ConfigEnv;
6+
7+
use OpenTelemetry\API\Configuration\Context;
8+
9+
interface EnvComponentLoaderRegistry
10+
{
11+
/**
12+
* @template T
13+
* @param class-string<T> $type
14+
* @return T
15+
*/
16+
public function load(string $type, string $name, EnvResolver $env, Context $context): mixed;
17+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration\ConfigEnv;
6+
7+
/**
8+
* Helper class to access environment-based configuration.
9+
*/
10+
interface EnvResolver
11+
{
12+
/**
13+
* Resolves a string-valued environment variable.
14+
*
15+
* @param string $name environment variable name
16+
* @return string|null value of the environment variable, or null if not set or invalid
17+
*
18+
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#string
19+
*/
20+
public function string(string $name): ?string;
21+
22+
/**
23+
* Resolves an enum-valued environment variable.
24+
*
25+
* @param string $name environment variable name
26+
* @param list<string> $values list of permissible enum values
27+
* @return string|null value of the environment variable, of null if not set or invalid
28+
*
29+
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#enum
30+
*/
31+
public function enum(string $name, array $values): ?string;
32+
33+
/**
34+
* Resolves a boolean-valued environment variable.
35+
*
36+
* Allowed values:
37+
* - case-insensitive "true"
38+
* - case-insensitive "false"
39+
*
40+
* @param string $name environment variable name
41+
* @return bool|null value of the environment variable, or null if not set or invalid
42+
*
43+
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#boolean-value
44+
*/
45+
public function bool(string $name): ?bool;
46+
47+
/**
48+
* Resolves an integer-valued environment variable.
49+
*
50+
* @param string $name environment variable name
51+
* @param int|null $min lower limit (inclusive), defaults to 0
52+
* @param int|null $max upper limit (inclusive), defaults to 2^31-1
53+
* @return int|null value of the environment variable, or null if not set or invalid
54+
*
55+
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#numeric-value
56+
*/
57+
public function int(string $name, ?int $min = 0, ?int $max = ~(-1 << 31)): int|null;
58+
59+
/**
60+
* Resolves a numeric-valued environment variable.
61+
*
62+
* @param string $name environment variable name
63+
* @param int|float|null $min lower limit (inclusive), defaults to 0
64+
* @param int|float|null $max upper limit (inclusive), defaults to 2^31-1
65+
* @return int|float|null value of the environment variable, or null if not set or invalid
66+
*
67+
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#numeric-value
68+
*/
69+
public function numeric(string $name, int|float|null $min = 0, int|float|null $max = ~(-1 << 31)): float|int|null;
70+
71+
/**
72+
* Resolves a list-valued environment variable.
73+
*
74+
* @param string $name environment variable name
75+
* @return list<string>|null value of the environment variable, or null if not set or invalid
76+
*/
77+
public function list(string $name): ?array;
78+
79+
/**
80+
* Resolves a map-valued environment variable.
81+
*
82+
* @param string $name environment variable name
83+
* @return array<string, string>|null value of the environment variable, or null if not set or invalid
84+
*/
85+
public function map(string $name): ?array;
86+
}

Configuration/Context.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Configuration;
6+
7+
use function class_alias;
8+
use OpenTelemetry\API\Logs\LoggerProviderInterface;
9+
use OpenTelemetry\API\Logs\NoopLoggerProvider;
10+
use OpenTelemetry\API\Metrics\MeterProviderInterface;
11+
use OpenTelemetry\API\Metrics\Noop\NoopMeterProvider;
12+
use OpenTelemetry\API\Trace\NoopTracerProvider;
13+
use OpenTelemetry\API\Trace\TracerProviderInterface;
14+
use Psr\Log\LoggerInterface;
15+
use Psr\Log\NullLogger;
16+
17+
final class Context
18+
{
19+
public function __construct(
20+
public readonly TracerProviderInterface $tracerProvider = new NoopTracerProvider(),
21+
public readonly MeterProviderInterface $meterProvider = new NoopMeterProvider(),
22+
public readonly LoggerProviderInterface $loggerProvider = new NoopLoggerProvider(),
23+
public readonly LoggerInterface $logger = new NullLogger(),
24+
) {
25+
}
26+
}
27+
28+
/** @phpstan-ignore-next-line @phan-suppress-next-line PhanUndeclaredClassReference */
29+
class_alias(Context::class, \OpenTelemetry\Config\SDK\Configuration\Context::class);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Instrumentation\Configuration\General\ConfigEnv;
6+
7+
use OpenTelemetry\API\Configuration\ConfigEnv\EnvComponentLoader;
8+
use OpenTelemetry\API\Configuration\ConfigEnv\EnvComponentLoaderRegistry;
9+
use OpenTelemetry\API\Configuration\ConfigEnv\EnvResolver;
10+
use OpenTelemetry\API\Configuration\Context;
11+
use OpenTelemetry\API\Instrumentation\AutoInstrumentation\GeneralInstrumentationConfiguration;
12+
use OpenTelemetry\API\Instrumentation\Configuration\General\HttpConfig;
13+
14+
/**
15+
* @implements EnvComponentLoader<GeneralInstrumentationConfiguration>
16+
*/
17+
final class EnvComponentLoaderHttpConfig implements EnvComponentLoader
18+
{
19+
public function load(EnvResolver $env, EnvComponentLoaderRegistry $registry, Context $context): GeneralInstrumentationConfiguration
20+
{
21+
return new HttpConfig([
22+
'client' => [
23+
'request_captured_headers' => $env->list('OTEL_PHP_INSTRUMENTATION_HTTP_REQUEST_HEADERS') ?? [],
24+
'response_captured_headers' => $env->list('OTEL_PHP_INSTRUMENTATION_HTTP_RESPONSE_HEADERS') ?? [],
25+
],
26+
'server' => [
27+
'request_captured_headers' => $env->list('OTEL_PHP_INSTRUMENTATION_HTTP_REQUEST_HEADERS') ?? [],
28+
'response_captured_headers' => $env->list('OTEL_PHP_INSTRUMENTATION_HTTP_RESPONSE_HEADERS') ?? [],
29+
],
30+
]);
31+
}
32+
33+
public function name(): string
34+
{
35+
return HttpConfig::class;
36+
}
37+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenTelemetry\API\Instrumentation\Configuration\General\ConfigEnv;
6+
7+
use OpenTelemetry\API\Configuration\ConfigEnv\EnvComponentLoader;
8+
use OpenTelemetry\API\Configuration\ConfigEnv\EnvComponentLoaderRegistry;
9+
use OpenTelemetry\API\Configuration\ConfigEnv\EnvResolver;
10+
use OpenTelemetry\API\Configuration\Context;
11+
use OpenTelemetry\API\Instrumentation\AutoInstrumentation\GeneralInstrumentationConfiguration;
12+
use OpenTelemetry\API\Instrumentation\Configuration\General\PeerConfig;
13+
14+
/**
15+
* @implements EnvComponentLoader<GeneralInstrumentationConfiguration>
16+
*/
17+
final class EnvComponentLoaderPeerConfig implements EnvComponentLoader
18+
{
19+
public function load(EnvResolver $env, EnvComponentLoaderRegistry $registry, Context $context): GeneralInstrumentationConfiguration
20+
{
21+
return new PeerConfig([]);
22+
}
23+
24+
public function name(): string
25+
{
26+
return PeerConfig::class;
27+
}
28+
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
},
3636
"extra": {
3737
"branch-alias": {
38-
"dev-main": "1.1.x-dev"
38+
"dev-main": "1.4.x-dev"
3939
},
4040
"spi": {
4141
"OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [

0 commit comments

Comments
 (0)