refactor environment configuration (#859)
refactoring Environment access to allow configuration from multiple sources. Initially, the sources are env ($_SERVER) and php.ini, but this should allow us to add more sources in future without changing the API. do not modify OTEL_EXPORTER_OTLP_TRACES_PROTOCOL allow resolvers to return mixed
This commit is contained in:
parent
92e7a0d070
commit
f083b10909
|
|
@ -5,10 +5,8 @@ require __DIR__ . '/../../../vendor/autoload.php';
|
|||
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use OpenTelemetry\Contrib\Otlp\SpanExporter;
|
||||
use OpenTelemetry\SDK\Common\Log\LoggerHolder;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
|
||||
use OpenTelemetry\SDK\Trace\TracerProvider;
|
||||
use OpenTelemetry\SDK\Trace\TracerProviderFactory;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
echo 'Starting SettingUpLogging example' . PHP_EOL;
|
||||
|
|
@ -18,13 +16,11 @@ echo 'Starting SettingUpLogging example' . PHP_EOL;
|
|||
LoggerHolder::set(
|
||||
new Logger('otel-php', [new StreamHandler(STDOUT, LogLevel::DEBUG)])
|
||||
);
|
||||
$transport = (new \OpenTelemetry\Contrib\Grpc\GrpcTransportFactory())->create();
|
||||
putenv('OTEL_EXPORTER_OTLP_ENDPOINT=http://does-not-exist/endpoint'); //invalid endpoint, export will fail
|
||||
putenv('OTEL_EXPORTER_OTLP_PROTOCOL=grpc');
|
||||
$factory = new TracerProviderFactory('otlp-logging-demo');
|
||||
$tracerProvider = $factory->create();
|
||||
|
||||
$tracerProvider = new TracerProvider(
|
||||
new SimpleSpanProcessor(
|
||||
new SpanExporter($transport) //default endpoint unavailable, so exporting will fail
|
||||
)
|
||||
);
|
||||
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
|
||||
$span = $tracer->spanBuilder('root-span')->startSpan();
|
||||
$span->end();
|
||||
|
|
|
|||
|
|
@ -11,3 +11,9 @@ parameters:
|
|||
# - ./examples TODO: Uncomment this once examples are updated
|
||||
excludePaths:
|
||||
- tests/TraceContext/W3CTestService
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#Call to an undefined method .*#"
|
||||
paths:
|
||||
- tests/Unit/SDK/Common/Configuration/Resolver/PhpIniResolverTest.php
|
||||
- tests/Unit/SDK/Common/Configuration/Resolver/CompositeResolverTest.php
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
backupGlobals="true"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="./tests/bootstrap.php"
|
||||
cacheResult="false"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\Contrib\Otlp;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class Protocols
|
||||
|
|
|
|||
|
|
@ -6,22 +6,36 @@ namespace OpenTelemetry\Contrib\Otlp;
|
|||
|
||||
use OpenTelemetry\API\Common\Signal\Signals;
|
||||
use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Behavior\LogsMessagesTrait;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Defaults;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use OpenTelemetry\SDK\Common\Otlp\HttpEndpointResolver;
|
||||
use OpenTelemetry\SDK\Trace\SpanExporterInterface;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class SpanExporterFactory
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private ?TransportFactoryInterface $transportFactory;
|
||||
|
||||
private const DEFAULT_COMPRESSION = 'none';
|
||||
private const FACTORIES = [
|
||||
KnownValues::VALUE_GRPC => GrpcTransportFactory::class,
|
||||
KnownValues::VALUE_HTTP_PROTOBUF => OtlpHttpTransportFactory::class,
|
||||
KnownValues::VALUE_HTTP_JSON => OtlpHttpTransportFactory::class,
|
||||
KnownValues::VALUE_HTTP_NDJSON => OtlpHttpTransportFactory::class,
|
||||
];
|
||||
|
||||
public function __construct(?TransportFactoryInterface $transportFactory = null)
|
||||
{
|
||||
$this->transportFactory = $transportFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress ArgumentTypeCoercion
|
||||
*/
|
||||
|
|
@ -37,31 +51,56 @@ class SpanExporterFactory
|
|||
*/
|
||||
private function buildTransport(): TransportInterface
|
||||
{
|
||||
$protocol = EnvironmentVariables::has(Env::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) ?
|
||||
EnvironmentVariables::getEnum(Env::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) :
|
||||
EnvironmentVariables::getEnum(Env::OTEL_EXPORTER_OTLP_PROTOCOL);
|
||||
$protocol = $this->getProtocol();
|
||||
$contentType = Protocols::contentType($protocol);
|
||||
$endpoint = $this->getEndpoint($protocol);
|
||||
$headers = $this->getHeaders();
|
||||
$compression = $this->getCompression();
|
||||
|
||||
$endpoint = EnvironmentVariables::has(Env::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
|
||||
? EnvironmentVariables::getString(Env::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
|
||||
: EnvironmentVariables::getString(Env::OTEL_EXPORTER_OTLP_ENDPOINT);
|
||||
if (!$this->transportFactory && !array_key_exists($protocol, self::FACTORIES)) {
|
||||
throw new UnexpectedValueException('Unknown OTLP protocol: ' . $protocol);
|
||||
}
|
||||
$factoryClass = self::FACTORIES[$protocol];
|
||||
$factory = $this->transportFactory ?: new $factoryClass();
|
||||
|
||||
return $factory->create($endpoint, $contentType, $headers, $compression);
|
||||
}
|
||||
|
||||
private function getProtocol(): string
|
||||
{
|
||||
return Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) ?
|
||||
Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) :
|
||||
Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_PROTOCOL);
|
||||
}
|
||||
|
||||
private function getEndpoint(string $protocol): string
|
||||
{
|
||||
if (Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)) {
|
||||
return Configuration::getString(Variables::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);
|
||||
}
|
||||
$endpoint = Configuration::has(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
|
||||
? Configuration::getString(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
|
||||
: Defaults::OTEL_EXPORTER_OTLP_ENDPOINT;
|
||||
if ($protocol === Protocols::GRPC) {
|
||||
$endpoint .= OtlpUtil::method(Signals::TRACE);
|
||||
} else {
|
||||
$endpoint = HttpEndpointResolver::create()->resolveToString($endpoint, Signals::TRACE);
|
||||
return $endpoint . OtlpUtil::method(Signals::TRACE);
|
||||
}
|
||||
|
||||
$headers = EnvironmentVariables::has(Env::OTEL_EXPORTER_OTLP_TRACES_HEADERS) ?
|
||||
EnvironmentVariables::getMap(Env::OTEL_EXPORTER_OTLP_TRACES_HEADERS) :
|
||||
EnvironmentVariables::getMap(Env::OTEL_EXPORTER_OTLP_HEADERS);
|
||||
$headers += OtlpUtil::getUserAgentHeader();
|
||||
return HttpEndpointResolver::create()->resolveToString($endpoint, Signals::TRACE);
|
||||
}
|
||||
|
||||
$compression = EnvironmentVariables::has(Env::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION) ?
|
||||
EnvironmentVariables::getEnum(Env::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION) :
|
||||
EnvironmentVariables::getEnum(Env::OTEL_EXPORTER_OTLP_COMPRESSION, self::DEFAULT_COMPRESSION);
|
||||
private function getHeaders(): array
|
||||
{
|
||||
$headers = Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_HEADERS) ?
|
||||
Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_TRACES_HEADERS) :
|
||||
Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_HEADERS);
|
||||
|
||||
$factoryClass = self::FACTORIES[$protocol];
|
||||
return $headers + OtlpUtil::getUserAgentHeader();
|
||||
}
|
||||
|
||||
return (new $factoryClass())->create($endpoint, $contentType, $headers, $compression);
|
||||
private function getCompression(): string
|
||||
{
|
||||
return Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION) ?
|
||||
Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION) :
|
||||
Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_COMPRESSION, self::DEFAULT_COMPRESSION);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Parser\BooleanParser;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Parser\ListParser;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Parser\MapParser;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Parser\RatioParser;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Resolver\CompositeResolver;
|
||||
use OpenTelemetry\SDK\Common\Util\ClassConstantAccessor;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Configuration can come from one or more of the following sources (from highest to lowest priority):
|
||||
* - values defined in php.ini
|
||||
* - environment variable ($_SERVER)
|
||||
* - configuration file (todo)
|
||||
*/
|
||||
class Configuration
|
||||
{
|
||||
public static function has(string $name): bool
|
||||
{
|
||||
return CompositeResolver::instance()->hasVariable($name);
|
||||
}
|
||||
|
||||
public static function getInt(string $key, int $default = null): int
|
||||
{
|
||||
return (int) self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::INTEGER),
|
||||
$default
|
||||
),
|
||||
FILTER_VALIDATE_INT
|
||||
);
|
||||
}
|
||||
|
||||
public static function getString(string $key, string $default = ''): string
|
||||
{
|
||||
return (string) self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::STRING),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getBoolean(string $key, bool $default = null): bool
|
||||
{
|
||||
return BooleanParser::parse(
|
||||
self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::BOOL),
|
||||
null === $default ? $default : ($default ? 'true' : 'false')
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getMixed(string $key, string $default = null)
|
||||
{
|
||||
return self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
$key,
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getMap(string $key, string $default = null): array
|
||||
{
|
||||
return MapParser::parse(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::MAP),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getList(string $key, string $default = null): array
|
||||
{
|
||||
return ListParser::parse(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::LIST),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getEnum(string $key, string $default = null): string
|
||||
{
|
||||
return (string) self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::ENUM),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getFloat(string $key, string $default = null): float
|
||||
{
|
||||
return (float) self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::FLOAT),
|
||||
$default
|
||||
),
|
||||
FILTER_VALIDATE_FLOAT
|
||||
);
|
||||
}
|
||||
|
||||
public static function getRatio(string $key, float $default = null): float
|
||||
{
|
||||
return RatioParser::parse(
|
||||
self::validateVariableValue(
|
||||
CompositeResolver::instance()->resolve(
|
||||
self::validateVariableType($key, VariableTypes::RATIO),
|
||||
$default
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getKnownValues(string $variableName): ?array
|
||||
{
|
||||
return ClassConstantAccessor::getValue(KnownValues::class, $variableName);
|
||||
}
|
||||
|
||||
public static function getDefault(string $variableName)
|
||||
{
|
||||
return ClassConstantAccessor::getValue(Defaults::class, $variableName);
|
||||
}
|
||||
|
||||
public static function getType(string $variableName): ?string
|
||||
{
|
||||
return ClassConstantAccessor::getValue(ValueTypes::class, $variableName);
|
||||
}
|
||||
|
||||
public static function isEmpty($value): bool
|
||||
{
|
||||
// don't use 'empty()', since '0' is not considered to be empty
|
||||
return $value === null || $value === '';
|
||||
}
|
||||
|
||||
private static function validateVariableType(string $variableName, string $type): string
|
||||
{
|
||||
$variableType = self::getType($variableName);
|
||||
|
||||
if ($variableType !== null && $variableType !== $type && $variableType !== VariableTypes::MIXED) {
|
||||
throw new UnexpectedValueException(
|
||||
sprintf('Variable "%s" is not supposed to be of type "%s" but type "%s"', $variableName, $type, $variableType)
|
||||
);
|
||||
}
|
||||
|
||||
return $variableName;
|
||||
}
|
||||
|
||||
private static function validateVariableValue($value, ?int $filterType = null)
|
||||
{
|
||||
if ($filterType !== null && filter_var($value, $filterType) === false) {
|
||||
throw new UnexpectedValueException(sprintf('Value has invalid type "%s"', gettype($value)));
|
||||
}
|
||||
|
||||
if ($value === null || $value === '') {
|
||||
throw new UnexpectedValueException(
|
||||
'Variable must not be null or empty'
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration;
|
||||
|
||||
/**
|
||||
* Default values for environment variables defined by the OpenTelemetry specification and language specific variables for the PHP SDK.
|
||||
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration;
|
||||
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* "Known values" for OpenTelemetry environment variables.
|
||||
* "Known values" for OpenTelemetry configurataion variables.
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md
|
||||
* Notice: Values specific to the PHP SDK have been added
|
||||
*/
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
|
@ -20,8 +20,14 @@ class BooleanParser
|
|||
'0',
|
||||
];
|
||||
|
||||
public static function parse(string $value): bool
|
||||
/**
|
||||
* @param string|bool $value
|
||||
*/
|
||||
public static function parse($value): bool
|
||||
{
|
||||
if (is_bool($value)) {
|
||||
return $value;
|
||||
}
|
||||
if (in_array(strtolower($value), self::TRUTHY_VALUES)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Parser;
|
||||
|
||||
class ListParser
|
||||
{
|
||||
private const DEFAULT_SEPARATOR = ',';
|
||||
|
||||
/**
|
||||
* @param string|array $value
|
||||
*/
|
||||
public static function parse($value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
if (trim($value) === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(
|
||||
fn ($value) => trim($value),
|
||||
explode(self::DEFAULT_SEPARATOR, $value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
|
@ -11,11 +11,14 @@ class MapParser
|
|||
private const VARIABLE_SEPARATOR = ',';
|
||||
private const KEY_VALUE_SEPARATOR = '=';
|
||||
|
||||
public static function parse(string $value): array
|
||||
public static function parse($value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
$result = [];
|
||||
|
||||
if (trim($value) === '') {
|
||||
if (null === $value || trim($value) === '') {
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use RangeException;
|
||||
|
|
@ -12,7 +12,7 @@ class RatioParser
|
|||
private const MAX_VALUE = 1;
|
||||
private const MIN_VALUE = 0;
|
||||
|
||||
public static function parse(string $value): float
|
||||
public static function parse($value): float
|
||||
{
|
||||
if (filter_var($value, FILTER_VALIDATE_FLOAT) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Resolver;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
|
||||
/**
|
||||
* @interal
|
||||
*/
|
||||
class CompositeResolver
|
||||
{
|
||||
// @var array<ResolverInterface>
|
||||
private array $resolvers = [];
|
||||
|
||||
public static function instance(): self
|
||||
{
|
||||
static $instance;
|
||||
$instance ??= new self([
|
||||
new PhpIniResolver(),
|
||||
new EnvironmentResolver(),
|
||||
]);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public function __construct($resolvers)
|
||||
{
|
||||
foreach ($resolvers as $resolver) {
|
||||
$this->addResolver($resolver);
|
||||
}
|
||||
}
|
||||
|
||||
public function addResolver(ResolverInterface $resolver): void
|
||||
{
|
||||
$this->resolvers[] = $resolver;
|
||||
}
|
||||
|
||||
public function getResolvers(): array
|
||||
{
|
||||
return $this->resolvers;
|
||||
}
|
||||
|
||||
public function resolve(string $variableName, $default = '')
|
||||
{
|
||||
foreach ($this->resolvers as $resolver) {
|
||||
if ($resolver->hasVariable($variableName)) {
|
||||
return $resolver->retrieveValue($variableName);
|
||||
}
|
||||
}
|
||||
|
||||
return Configuration::isEmpty($default)
|
||||
? Configuration::getDefault($variableName)
|
||||
: $default;
|
||||
}
|
||||
|
||||
public function hasVariable(string $variableName): bool
|
||||
{
|
||||
foreach ($this->resolvers as $resolver) {
|
||||
if ($resolver->hasVariable($variableName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Resolver;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class EnvironmentResolver implements ResolverInterface
|
||||
{
|
||||
public function hasVariable(string $variableName): bool
|
||||
{
|
||||
if (!Configuration::isEmpty($_SERVER[$variableName] ?? null)) {
|
||||
return true;
|
||||
}
|
||||
$env = getenv($variableName);
|
||||
if ($env === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !Configuration::isEmpty($env);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidReturnStatement
|
||||
* @psalm-suppress InvalidReturnType
|
||||
*/
|
||||
public function retrieveValue(string $variableName)
|
||||
{
|
||||
$value = getenv($variableName);
|
||||
if ($value === false) {
|
||||
$value = $_SERVER[$variableName] ?? null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Resolver;
|
||||
|
||||
class PhpIniAccessor
|
||||
{
|
||||
/**
|
||||
* Mockable accessor for php.ini values
|
||||
* @internal
|
||||
* @return array|false|string
|
||||
*/
|
||||
public function get(string $variableName)
|
||||
{
|
||||
return get_cfg_var($variableName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Resolver;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
|
||||
/**
|
||||
* @interal
|
||||
* @psalm-suppress TypeDoesNotContainType
|
||||
*/
|
||||
class PhpIniResolver implements ResolverInterface
|
||||
{
|
||||
private PhpIniAccessor $accessor;
|
||||
|
||||
public function __construct(?PhpIniAccessor $accessor = null)
|
||||
{
|
||||
$this->accessor = $accessor ?? new PhpIniAccessor();
|
||||
}
|
||||
|
||||
public function retrieveValue(string $variableName)
|
||||
{
|
||||
$value = $this->accessor->get($variableName) ?: '';
|
||||
if (is_array($value)) {
|
||||
return implode(',', $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function hasVariable(string $variableName): bool
|
||||
{
|
||||
$value = $this->accessor->get($variableName);
|
||||
if ($value === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $value !== false && !Configuration::isEmpty($value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Configuration\Resolver;
|
||||
|
||||
interface ResolverInterface
|
||||
{
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function retrieveValue(string $variableName);
|
||||
|
||||
public function hasVariable(string $variableName): bool;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration;
|
||||
|
||||
/**
|
||||
* Environment variables defined by the OpenTelemetry specification and language specific variables for the PHP SDK.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration;
|
||||
|
||||
interface VariableTypes
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
namespace OpenTelemetry\SDK\Common\Configuration;
|
||||
|
||||
/**
|
||||
* Environment variables defined by the OpenTelemetry specification and language specific variables for the PHP SDK.
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\BooleanParser;
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\ListParser;
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\MapParser;
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\RatioParser;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class Accessor
|
||||
{
|
||||
public static function getString(string $variableName, string $default = null): string
|
||||
{
|
||||
return (string) self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::STRING),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getBool(string $variableName, string $default = null): bool
|
||||
{
|
||||
return BooleanParser::parse(
|
||||
self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::BOOL),
|
||||
$default
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getInt(string $variableName, string $default = null): int
|
||||
{
|
||||
return (int) self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::INTEGER),
|
||||
$default
|
||||
),
|
||||
FILTER_VALIDATE_INT
|
||||
);
|
||||
}
|
||||
|
||||
public static function getFloat(string $variableName, string $default = null): float
|
||||
{
|
||||
return (float) self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::FLOAT),
|
||||
$default
|
||||
),
|
||||
FILTER_VALIDATE_FLOAT
|
||||
);
|
||||
}
|
||||
|
||||
public static function getRatio(string $variableName, string $default = null): float
|
||||
{
|
||||
return RatioParser::parse(
|
||||
self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::RATIO),
|
||||
$default
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getEnum(string $variableName, string $default = null): string
|
||||
{
|
||||
return (string) self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::ENUM),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getList(string $variableName, string $default = null): array
|
||||
{
|
||||
return ListParser::parse(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::LIST),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getMap(string $variableName, string $default = null): array
|
||||
{
|
||||
return MapParser::parse(
|
||||
Resolver::resolveValue(
|
||||
self::validateVariableType($variableName, VariableTypes::MAP),
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getMixed(string $variableName, string $default = null, ?string $type = null)
|
||||
{
|
||||
return self::validateVariableValue(
|
||||
Resolver::resolveValue(
|
||||
$variableName,
|
||||
$default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static function validateVariableType(string $variableName, string $type): string
|
||||
{
|
||||
$variableType = Resolver::getType($variableName);
|
||||
|
||||
if ($variableType !== null && $variableType !== $type && $variableType !== VariableTypes::MIXED) {
|
||||
throw new UnexpectedValueException(
|
||||
sprintf('Variable "%s" is not supposed to be of type "%s" but type "%s"', $variableName, $type, $variableType)
|
||||
);
|
||||
}
|
||||
|
||||
return $variableName;
|
||||
}
|
||||
|
||||
private static function validateVariableValue($value, ?int $filterType = null)
|
||||
{
|
||||
if ($filterType !== null && filter_var($value, $filterType) === false) {
|
||||
throw new UnexpectedValueException(sprintf('Value has invalid type "%s"', gettype($value)));
|
||||
}
|
||||
|
||||
if ($value === null || $value === '') {
|
||||
throw new UnexpectedValueException(
|
||||
'Variable must not be null or empty'
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
|
||||
/**
|
||||
* Centralized methods for retrieving environment variables
|
||||
*/
|
||||
class EnvironmentVariables
|
||||
{
|
||||
/**
|
||||
* Retrieve an integer value from an environment variable
|
||||
*/
|
||||
public static function getInt(string $key, int $default): int
|
||||
{
|
||||
return Accessor::getInt($key, (string) $default);
|
||||
}
|
||||
|
||||
public static function getString(string $key, string $default = ''): string
|
||||
{
|
||||
return Accessor::getString($key, $default);
|
||||
}
|
||||
|
||||
public static function getBoolean(string $key, bool $default = null): bool
|
||||
{
|
||||
return Accessor::getBool($key, null === $default ? null : ($default ? 'true' : 'false'));
|
||||
}
|
||||
|
||||
public static function getMap(string $key, string $default = null): array
|
||||
{
|
||||
return Accessor::getMap($key, $default);
|
||||
}
|
||||
|
||||
public static function getList(string $key, string $default = null): array
|
||||
{
|
||||
return Accessor::getList($key, $default);
|
||||
}
|
||||
|
||||
public static function getEnum(string $key, string $default = null): string
|
||||
{
|
||||
return Accessor::getEnum($key, $default);
|
||||
}
|
||||
|
||||
public static function getRatio(string $key, float $default = null): float
|
||||
{
|
||||
return Accessor::getRatio($key, $default ? (string) $default : null);
|
||||
}
|
||||
|
||||
public static function has(string $key): bool
|
||||
{
|
||||
return Resolver::hasVariable($key);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment\Parser;
|
||||
|
||||
class ListParser
|
||||
{
|
||||
private const DEFAULT_SEPARATOR = ',';
|
||||
|
||||
public static function parse(string $value, string $separator = self::DEFAULT_SEPARATOR): array
|
||||
{
|
||||
if (trim($value) === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(
|
||||
fn ($value) => trim($value),
|
||||
explode(self::DEFAULT_SEPARATOR, $value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\Environment;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Util\ClassConstantAccessor;
|
||||
|
||||
class Resolver
|
||||
{
|
||||
public static function resolveValue(string $variableName, $default = null): string
|
||||
{
|
||||
$value = self::getValue($variableName);
|
||||
|
||||
if (self::isEmpty($value)) {
|
||||
return self::isEmpty($default) ? (string) self::getDefault($variableName) : (string) $default;
|
||||
}
|
||||
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
public static function getValue(string $variableName): ?string
|
||||
{
|
||||
$value = self::getRawValue($variableName);
|
||||
|
||||
return $value ? trim($value) : $value;
|
||||
}
|
||||
|
||||
public static function getRawValue(string $variableName): ?string
|
||||
{
|
||||
/** @psalm-suppress FalsableReturnStatement **/
|
||||
return self::hasVariable($variableName) ? self::retrieveValue($variableName) : null;
|
||||
}
|
||||
|
||||
public static function hasVariable(string $variableName): bool
|
||||
{
|
||||
return getenv($variableName) !== false || isset($_ENV[$variableName]);
|
||||
}
|
||||
|
||||
public static function getDefault(string $variableName)
|
||||
{
|
||||
return ClassConstantAccessor::getValue(Defaults::class, $variableName);
|
||||
}
|
||||
|
||||
public static function getType(string $variableName): ?string
|
||||
{
|
||||
return ClassConstantAccessor::getValue(ValueTypes::class, $variableName);
|
||||
}
|
||||
|
||||
public static function getKnownValues(string $variableName): ?array
|
||||
{
|
||||
return ClassConstantAccessor::getValue(KnownValues::class, $variableName);
|
||||
}
|
||||
|
||||
private static function isEmpty($value): bool
|
||||
{
|
||||
// don't use 'empty()', since '0' is not considered to be empty
|
||||
return $value === null || $value === '';
|
||||
}
|
||||
|
||||
private static function retrieveValue(string $variableName)
|
||||
{
|
||||
$value = getenv($variableName);
|
||||
if ($value === false) {
|
||||
$value = $_ENV[$variableName] ?? false;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Resource\Detectors;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
use OpenTelemetry\SDK\Resource\ResourceDetectorInterface;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use OpenTelemetry\SemConv\ResourceAttributes;
|
||||
|
|
@ -18,12 +18,14 @@ final class Environment implements ResourceDetectorInterface
|
|||
{
|
||||
public function getResource(): ResourceInfo
|
||||
{
|
||||
$attributes = EnvironmentVariables::getMap(Env::OTEL_RESOURCE_ATTRIBUTES, '');
|
||||
$attributes = Configuration::has(Variables::OTEL_RESOURCE_ATTRIBUTES)
|
||||
? Configuration::getMap(Variables::OTEL_RESOURCE_ATTRIBUTES, '')
|
||||
: [];
|
||||
|
||||
//@see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#general-sdk-configuration
|
||||
$serviceName = EnvironmentVariables::has(Env::OTEL_SERVICE_NAME) ?
|
||||
EnvironmentVariables::getString(Env::OTEL_SERVICE_NAME) :
|
||||
null;
|
||||
$serviceName = Configuration::has(Variables::OTEL_SERVICE_NAME)
|
||||
? Configuration::getString(Variables::OTEL_SERVICE_NAME)
|
||||
: null;
|
||||
if ($serviceName) {
|
||||
$attributes[ResourceAttributes::SERVICE_NAME] = $serviceName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ namespace OpenTelemetry\SDK\Resource;
|
|||
|
||||
use function in_array;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Environment\Accessor;
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables as Env;
|
||||
|
||||
class ResourceInfoFactory
|
||||
{
|
||||
|
|
@ -33,7 +33,7 @@ class ResourceInfoFactory
|
|||
|
||||
public static function defaultResource(): ResourceInfo
|
||||
{
|
||||
$detectors = Accessor::getList(Env::OTEL_PHP_DETECTORS);
|
||||
$detectors = Configuration::getList(Env::OTEL_PHP_DETECTORS);
|
||||
|
||||
if (in_array(Values::VALUE_ALL, $detectors)) {
|
||||
return (new Detectors\Composite([
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ namespace OpenTelemetry\SDK;
|
|||
use OpenTelemetry\API\Metrics\MeterProviderInterface;
|
||||
use OpenTelemetry\API\Trace\TracerProviderInterface;
|
||||
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
|
||||
class Sdk
|
||||
{
|
||||
|
|
@ -28,7 +28,7 @@ class Sdk
|
|||
|
||||
public static function isDisabled(): bool
|
||||
{
|
||||
return EnvironmentVariables::getBoolean(Variables::OTEL_SDK_DISABLED);
|
||||
return Configuration::getBoolean(Variables::OTEL_SDK_DISABLED);
|
||||
}
|
||||
|
||||
public static function builder(): SdkBuilder
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Trace;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Dsn\DsnInterface;
|
||||
use OpenTelemetry\SDK\Common\Dsn\Parser;
|
||||
use OpenTelemetry\SDK\Common\Dsn\ParserInterface;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
|
||||
class ExporterFactory
|
||||
{
|
||||
|
|
@ -78,7 +78,7 @@ class ExporterFactory
|
|||
|
||||
public function fromEnvironment(): ?SpanExporterInterface
|
||||
{
|
||||
$envValue = EnvironmentVariables::getString(Env::OTEL_TRACES_EXPORTER, '');
|
||||
$envValue = Configuration::getString(Env::OTEL_TRACES_EXPORTER, '');
|
||||
$exporters = explode(',', $envValue);
|
||||
//TODO "The SDK MAY accept a comma-separated list to enable setting multiple exporters"
|
||||
if (1 !== count($exporters)) {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Trace;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables as Env;
|
||||
use OpenTelemetry\SDK\Trace\Sampler\AlwaysOffSampler;
|
||||
use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
|
||||
use OpenTelemetry\SDK\Trace\Sampler\ParentBased;
|
||||
|
|
@ -19,10 +19,10 @@ class SamplerFactory
|
|||
|
||||
public function fromEnvironment(): SamplerInterface
|
||||
{
|
||||
$name = EnvironmentVariables::getString(Env::OTEL_TRACES_SAMPLER);
|
||||
$name = Configuration::getString(Env::OTEL_TRACES_SAMPLER);
|
||||
|
||||
if (strpos($name, self::TRACEIDRATIO_PREFIX) !== false) {
|
||||
$arg = EnvironmentVariables::getRatio(Env::OTEL_TRACES_SAMPLER_ARG);
|
||||
$arg = Configuration::getRatio(Env::OTEL_TRACES_SAMPLER_ARG);
|
||||
|
||||
switch ($name) {
|
||||
case Values::VALUE_TRACE_ID_RATIO:
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ namespace OpenTelemetry\SDK\Trace;
|
|||
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Attribute\FilteredAttributesFactory;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables as Env;
|
||||
use OpenTelemetry\SemConv\TraceAttributes;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
|
|
@ -111,17 +111,17 @@ class SpanLimitsBuilder
|
|||
public function build(): SpanLimits
|
||||
{
|
||||
$attributeCountLimit = $this->attributeCountLimit
|
||||
?: EnvironmentVariables::getInt(Env::OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_ATTRIBUTE_COUNT_LIMIT);
|
||||
?: Configuration::getInt(Env::OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_ATTRIBUTE_COUNT_LIMIT);
|
||||
$attributeValueLengthLimit = $this->attributeValueLengthLimit
|
||||
?: EnvironmentVariables::getInt(Env::OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, SpanLimits::DEFAULT_SPAN_ATTRIBUTE_LENGTH_LIMIT);
|
||||
?: Configuration::getInt(Env::OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, SpanLimits::DEFAULT_SPAN_ATTRIBUTE_LENGTH_LIMIT);
|
||||
$eventCountLimit = $this->eventCountLimit
|
||||
?: EnvironmentVariables::getInt(Env::OTEL_SPAN_EVENT_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_EVENT_COUNT_LIMIT);
|
||||
?: Configuration::getInt(Env::OTEL_SPAN_EVENT_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_EVENT_COUNT_LIMIT);
|
||||
$linkCountLimit = $this->linkCountLimit
|
||||
?: EnvironmentVariables::getInt(Env::OTEL_SPAN_LINK_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_LINK_COUNT_LIMIT);
|
||||
?: Configuration::getInt(Env::OTEL_SPAN_LINK_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_LINK_COUNT_LIMIT);
|
||||
$attributePerEventCountLimit = $this->attributePerEventCountLimit
|
||||
?: EnvironmentVariables::getInt(Env::OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_EVENT_ATTRIBUTE_COUNT_LIMIT);
|
||||
?: Configuration::getInt(Env::OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_EVENT_ATTRIBUTE_COUNT_LIMIT);
|
||||
$attributePerLinkCountLimit = $this->attributePerLinkCountLimit
|
||||
?: EnvironmentVariables::getInt(Env::OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_LINK_ATTRIBUTE_COUNT_LIMIT);
|
||||
?: Configuration::getInt(Env::OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_LINK_ATTRIBUTE_COUNT_LIMIT);
|
||||
|
||||
if ($attributeValueLengthLimit === PHP_INT_MAX) {
|
||||
$attributeValueLengthLimit = null;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Trace;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues as Values;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Time\ClockFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\NoopSpanProcessor;
|
||||
|
|
@ -21,16 +21,16 @@ class SpanProcessorFactory
|
|||
return new NoopSpanProcessor();
|
||||
}
|
||||
|
||||
$name = EnvironmentVariables::getEnum(Env::OTEL_PHP_TRACES_PROCESSOR);
|
||||
$name = Configuration::getEnum(Env::OTEL_PHP_TRACES_PROCESSOR);
|
||||
switch ($name) {
|
||||
case Values::VALUE_BATCH:
|
||||
return new BatchSpanProcessor(
|
||||
$exporter,
|
||||
ClockFactory::getDefault(),
|
||||
EnvironmentVariables::getInt(Env::OTEL_BSP_MAX_QUEUE_SIZE, BatchSpanProcessor::DEFAULT_MAX_QUEUE_SIZE),
|
||||
EnvironmentVariables::getInt(Env::OTEL_BSP_SCHEDULE_DELAY, BatchSpanProcessor::DEFAULT_SCHEDULE_DELAY),
|
||||
EnvironmentVariables::getInt(Env::OTEL_BSP_EXPORT_TIMEOUT, BatchSpanProcessor::DEFAULT_EXPORT_TIMEOUT),
|
||||
EnvironmentVariables::getInt(Env::OTEL_BSP_MAX_EXPORT_BATCH_SIZE, BatchSpanProcessor::DEFAULT_MAX_EXPORT_BATCH_SIZE),
|
||||
Configuration::getInt(Env::OTEL_BSP_MAX_QUEUE_SIZE, BatchSpanProcessor::DEFAULT_MAX_QUEUE_SIZE),
|
||||
Configuration::getInt(Env::OTEL_BSP_SCHEDULE_DELAY, BatchSpanProcessor::DEFAULT_SCHEDULE_DELAY),
|
||||
Configuration::getInt(Env::OTEL_BSP_EXPORT_TIMEOUT, BatchSpanProcessor::DEFAULT_EXPORT_TIMEOUT),
|
||||
Configuration::getInt(Env::OTEL_BSP_MAX_EXPORT_BATCH_SIZE, BatchSpanProcessor::DEFAULT_MAX_EXPORT_BATCH_SIZE),
|
||||
);
|
||||
case Values::VALUE_SIMPLE:
|
||||
return new SimpleSpanProcessor($exporter);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Contrib\Otlp;
|
||||
|
||||
use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
|
||||
use OpenTelemetry\Contrib\Otlp\SpanExporterFactory;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\Contrib\Otlp\SpanExporterFactory
|
||||
* @psalm-suppress UndefinedInterfaceMethod
|
||||
*/
|
||||
class SpanExporterFactoryTest extends TestCase
|
||||
{
|
||||
use EnvironmentVariables;
|
||||
|
||||
private TransportFactoryInterface $transportFactory;
|
||||
private TransportInterface $transport;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->transportFactory = $this->createMock(TransportFactoryInterface::class);
|
||||
$this->transport = $this->createMock(TransportInterface::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->restoreEnvironmentVariables();
|
||||
}
|
||||
|
||||
public function test_unknown_protocol_exception(): void
|
||||
{
|
||||
$this->expectException(\UnexpectedValueException::class);
|
||||
$this->setEnvironmentVariable(Variables::OTEL_EXPORTER_OTLP_PROTOCOL, 'foo');
|
||||
$factory = new SpanExporterFactory();
|
||||
$factory->fromEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider fromEnvironmentProvider
|
||||
*/
|
||||
public function test_create_from_environment(array $env, string $endpoint, string $protocol, string $compression, array $headerKeys = []): void
|
||||
{
|
||||
foreach ($env as $k => $v) {
|
||||
$this->setEnvironmentVariable($k, $v);
|
||||
}
|
||||
$factory = new SpanExporterFactory($this->transportFactory);
|
||||
// @phpstan-ignore-next-line
|
||||
$this->transportFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with(
|
||||
$this->equalTo($endpoint),
|
||||
$this->equalTo($protocol),
|
||||
$this->callback(function ($headers) use ($headerKeys) {
|
||||
$this->assertEqualsCanonicalizing($headerKeys, array_keys($headers));
|
||||
|
||||
return true;
|
||||
}),
|
||||
$this->equalTo($compression)
|
||||
)
|
||||
->willReturn($this->transport);
|
||||
// @phpstan-ignore-next-line
|
||||
$this->transport->method('contentType')->willReturn($protocol);
|
||||
|
||||
$factory->fromEnvironment();
|
||||
}
|
||||
|
||||
public function fromEnvironmentProvider(): array
|
||||
{
|
||||
$defaultHeaderKeys = ['User-Agent'];
|
||||
|
||||
return [
|
||||
'signal-specific endpoint unchanged' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL => KnownValues::VALUE_GRPC,
|
||||
Variables::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT => 'http://collector:4317', //should not be changed, per spec
|
||||
],
|
||||
'endpoint' => 'http://collector:4317',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'endpoint has path appended' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL => KnownValues::VALUE_GRPC,
|
||||
Variables::OTEL_EXPORTER_OTLP_ENDPOINT => 'http://collector:4317',
|
||||
],
|
||||
'endpoint' => 'http://collector:4317/opentelemetry.proto.collector.trace.v1.TraceService/Export',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'protocol' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_PROTOCOL => KnownValues::VALUE_HTTP_NDJSON,
|
||||
],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/x-ndjson',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'signal-specific protocol' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_PROTOCOL => KnownValues::VALUE_HTTP_JSON,
|
||||
],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/json',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'defaults' => [
|
||||
'env' => [],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'compression' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_COMPRESSION => 'gzip',
|
||||
],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'gzip',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'signal-specific compression' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION => 'gzip',
|
||||
],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'gzip',
|
||||
'headerKeys' => $defaultHeaderKeys,
|
||||
],
|
||||
'headers' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_HEADERS => 'key1=foo,key2=bar',
|
||||
],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => array_merge($defaultHeaderKeys, ['key1', 'key2']),
|
||||
],
|
||||
'signal-specific headers' => [
|
||||
'env' => [
|
||||
Variables::OTEL_EXPORTER_OTLP_TRACES_HEADERS => 'key3=foo,key4=bar',
|
||||
],
|
||||
'endpoint' => 'http://localhost:4318/v1/traces',
|
||||
'protocol' => 'application/x-protobuf',
|
||||
'compression' => 'none',
|
||||
'headerKeys' => array_merge($defaultHeaderKeys, ['key3', 'key4']),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,456 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration;
|
||||
|
||||
use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
|
||||
use Exception;
|
||||
use Generator;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Defaults;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
use OpenTelemetry\SDK\Common\Configuration\VariableTypes;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Configuration
|
||||
*/
|
||||
class ConfigurationTest extends TestCase
|
||||
{
|
||||
use EnvironmentVariables;
|
||||
|
||||
private const ALLOW_EMPTY = [
|
||||
VariableTypes::LIST,
|
||||
VariableTypes::MAP,
|
||||
VariableTypes::MIXED,
|
||||
];
|
||||
|
||||
private const METHOD_NAMES = [
|
||||
VariableTypes::STRING => ['getString'],
|
||||
VariableTypes::BOOL => ['getBoolean'],
|
||||
VariableTypes::INTEGER => ['getInt'],
|
||||
VariableTypes::FLOAT => ['getFloat'],
|
||||
VariableTypes::RATIO => ['getRatio'],
|
||||
VariableTypes::ENUM => ['getEnum'],
|
||||
VariableTypes::LIST => ['getList'],
|
||||
VariableTypes::MAP => ['getMap'],
|
||||
VariableTypes::MIXED => ['getMixed'],
|
||||
];
|
||||
|
||||
private const TYPES = [
|
||||
VariableTypes::STRING => [Variables::OTEL_SERVICE_NAME],
|
||||
VariableTypes::BOOL => [Variables::OTEL_EXPORTER_OTLP_INSECURE],
|
||||
VariableTypes::INTEGER => [Variables::OTEL_EXPORTER_JAEGER_AGENT_PORT],
|
||||
VariableTypes::ENUM => [Variables::OTEL_LOG_LEVEL],
|
||||
VariableTypes::LIST => [Variables::OTEL_PROPAGATORS],
|
||||
VariableTypes::MAP => [Variables::OTEL_RESOURCE_ATTRIBUTES],
|
||||
VariableTypes::MIXED => [Variables::OTEL_TRACES_SAMPLER_ARG],
|
||||
];
|
||||
|
||||
private const USER_VALUES = [
|
||||
VariableTypes::STRING => ['foo', 'foo'],
|
||||
VariableTypes::BOOL => ['true', true],
|
||||
VariableTypes::INTEGER => ['42', 42],
|
||||
VariableTypes::ENUM => ['val1', 'val1'],
|
||||
VariableTypes::LIST => ['val1,val2', ['val1','val2']],
|
||||
VariableTypes::MAP => ['var1=val1,var2=val2', ['var1'=>'val1','var2'=>'val2']],
|
||||
VariableTypes::MIXED => ['foo', 'foo'],
|
||||
];
|
||||
|
||||
private const LIBRARY_DEFAULTS = [
|
||||
VariableTypes::STRING => [Variables::OTEL_EXPORTER_OTLP_ENDPOINT, 'http://localhost:4318'],
|
||||
VariableTypes::BOOL => [Variables::OTEL_EXPORTER_OTLP_INSECURE, false],
|
||||
VariableTypes::INTEGER => [Variables::OTEL_EXPORTER_JAEGER_AGENT_PORT, 6831],
|
||||
VariableTypes::ENUM => [Variables::OTEL_LOG_LEVEL, 'info'],
|
||||
VariableTypes::LIST => [Variables::OTEL_PROPAGATORS, ['tracecontext', 'baggage']],
|
||||
];
|
||||
|
||||
private const DEFAULT_VALUES = [
|
||||
'log level' => [Variables::OTEL_LOG_LEVEL, Defaults::OTEL_LOG_LEVEL],
|
||||
'attribute count limit' => [Variables::OTEL_ATTRIBUTE_COUNT_LIMIT, Defaults::OTEL_ATTRIBUTE_COUNT_LIMIT],
|
||||
'trace exporter' => [Variables::OTEL_PHP_TRACES_PROCESSOR, Defaults::OTEL_PHP_TRACES_PROCESSOR],
|
||||
];
|
||||
|
||||
private const NO_DEFAULTS = [
|
||||
VariableTypes::STRING => [Variables::OTEL_SERVICE_NAME],
|
||||
VariableTypes::ENUM => [Variables::OTEL_EXPORTER_OTLP_COMPRESSION],
|
||||
VariableTypes::MAP => [Variables::OTEL_EXPORTER_OTLP_HEADERS],
|
||||
VariableTypes::MIXED => [Variables::OTEL_TRACES_SAMPLER_ARG],
|
||||
];
|
||||
|
||||
private const KNOWN_VALUES = [
|
||||
'log level' => [Variables::OTEL_LOG_LEVEL, KnownValues::OTEL_LOG_LEVEL],
|
||||
'trace sampler' => [Variables::OTEL_TRACES_SAMPLER, KnownValues::OTEL_TRACES_SAMPLER],
|
||||
'trace processor' => [Variables::OTEL_PHP_TRACES_PROCESSOR, KnownValues::OTEL_PHP_TRACES_PROCESSOR],
|
||||
];
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->restoreEnvironmentVariables();
|
||||
}
|
||||
|
||||
public function test_has_variable_from_environment(): void
|
||||
{
|
||||
$this->assertFalse(Configuration::has('FOO_VAR'));
|
||||
$this->setEnvironmentVariable('FOO_VAR', 'FOO');
|
||||
$this->assertTrue(Configuration::has('FOO_VAR'));
|
||||
}
|
||||
|
||||
public function test_integer_get(): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', '100');
|
||||
$value = Configuration::getInt('OTEL_FOO', 999);
|
||||
$this->assertSame(100, $value);
|
||||
}
|
||||
|
||||
public function test_integer_failure(): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', 'foo');
|
||||
$this->expectException(Exception::class);
|
||||
Configuration::getInt('OTEL_FOO', 99);
|
||||
}
|
||||
|
||||
public function environment_variables_integer_uses_default_if_env_var_not_defined()
|
||||
{
|
||||
$this->assertSame(20, Configuration::getInt('OTEL_FOO', 20));
|
||||
}
|
||||
|
||||
public function test_string_get(): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', 'foo');
|
||||
$value = Configuration::getString('OTEL_FOO', 'bar');
|
||||
$this->assertSame('foo', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The SDK MUST interpret an empty value of an environment variable the same way as when the variable is unset
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_string_uses_default_when_empty_value(?string $input): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', $input);
|
||||
$value = Configuration::getString('OTEL_FOO', 'bar');
|
||||
$this->assertSame('bar', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_int_uses_default_when_empty_value(?string $input): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', $input);
|
||||
$value = Configuration::getInt('OTEL_FOO', 99);
|
||||
$this->assertSame(99, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_bool_uses_default_when_empty_value(?string $input): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', $input);
|
||||
$value = Configuration::getBoolean('OTEL_FOO', true);
|
||||
$this->assertTrue($value);
|
||||
}
|
||||
|
||||
public function emptyProvider()
|
||||
{
|
||||
return [
|
||||
'no value' => [null],
|
||||
'empty string' => [''],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider booleanProvider
|
||||
*/
|
||||
public function test_bool_get(string $input, bool $default, bool $expected)
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_BOOL', $input);
|
||||
$this->assertSame($expected, Configuration::getBoolean('OTEL_BOOL', $default));
|
||||
}
|
||||
|
||||
public function booleanProvider()
|
||||
{
|
||||
return [
|
||||
'false' => ['false', true, false],
|
||||
'true' => ['true', false, true],
|
||||
'truthy' => ['1', false, true],
|
||||
'falsey' => ['0', true, false],
|
||||
'TRUE' => ['TRUE', false, true],
|
||||
'FALSE' => ['FALSE', true, false],
|
||||
];
|
||||
}
|
||||
|
||||
public function test_list_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_LIST', 'a,b,c');
|
||||
$this->assertSame(['a', 'b', 'c'], Configuration::getList('OTEL_LIST'));
|
||||
}
|
||||
|
||||
public function test_map_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_MAP', 'a=b,c=d');
|
||||
$this->assertSame(['a'=>'b', 'c'=>'d'], Configuration::getMap('OTEL_MAP'));
|
||||
}
|
||||
|
||||
public function test_enum_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_ENUM', 'foo');
|
||||
$this->assertSame('foo', Configuration::getEnum('OTEL_ENUM'));
|
||||
}
|
||||
|
||||
public function test_ratio_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_RATIO', '0.5');
|
||||
$this->assertSame(0.5, Configuration::getRatio('OTEL_RATIO'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider userValueProvider
|
||||
*/
|
||||
public function test_return_user_env_vars(string $methodName, string $variable, string $value, $result)
|
||||
{
|
||||
$this->setEnvironmentVariable($variable, $value);
|
||||
|
||||
$this->assertSame(
|
||||
$result,
|
||||
call_user_func([Configuration::class, $methodName], $variable)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider userValueProvider
|
||||
*/
|
||||
public function test_return_user_default_value(string $methodName, string $variable, string $defaultValue, $result)
|
||||
{
|
||||
$this->assertSame(
|
||||
$result,
|
||||
call_user_func([Configuration::class, $methodName], $variable, $defaultValue)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider libraryDefaultValueProvider
|
||||
*/
|
||||
public function test_return_library_default_value(string $methodName, string $variable, $result)
|
||||
{
|
||||
$this->assertSame(
|
||||
$result,
|
||||
call_user_func([Configuration::class, $methodName], $variable)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonEmptyMethodNameProvider
|
||||
*/
|
||||
public function test_no_value_throws_exception(string $methodName)
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
call_user_func([Configuration::class, $methodName], 'FOO_BAR_' . $methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidTypeProvider
|
||||
*/
|
||||
public function test_invalid_type_throws_exception(string $methodName, string $variable)
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
call_user_func([Configuration::class, $methodName], $variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider noDefaultProvider
|
||||
*/
|
||||
public function test_null_result_throws_exception(string $methodName, string $variable)
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
call_user_func([Configuration::class, $methodName], $variable);
|
||||
}
|
||||
|
||||
public function userValueProvider(): Generator
|
||||
{
|
||||
foreach (self::USER_VALUES as $varType => $values) {
|
||||
[$default, $result] = $values;
|
||||
|
||||
yield $varType => [
|
||||
self::METHOD_NAMES[$varType][0],
|
||||
self::TYPES[$varType][0],
|
||||
$default,
|
||||
$result,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function libraryDefaultValueProvider(): Generator
|
||||
{
|
||||
foreach (self::LIBRARY_DEFAULTS as $varType => $values) {
|
||||
[$variable, $result] = $values;
|
||||
|
||||
yield $varType => [
|
||||
self::METHOD_NAMES[$varType][0],
|
||||
$variable,
|
||||
$result,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function nonEmptyMethodNameProvider(): Generator
|
||||
{
|
||||
foreach (self::METHOD_NAMES as $varType => $names) {
|
||||
if (in_array($varType, self::ALLOW_EMPTY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $varType => $names;
|
||||
}
|
||||
}
|
||||
|
||||
public function invalidTypeProvider(): Generator
|
||||
{
|
||||
foreach (self::METHOD_NAMES as $varType => $names) {
|
||||
if ($varType === VariableTypes::MIXED) {
|
||||
continue;
|
||||
}
|
||||
$methodName = $names[0];
|
||||
foreach (self::TYPES as $methodType => $types) {
|
||||
if ($varType === $methodType || $methodType === VariableTypes::MIXED) {
|
||||
continue;
|
||||
}
|
||||
$variableName = $types[0];
|
||||
|
||||
yield sprintf('%s - %s', $varType, $methodType) => [$methodName, $variableName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function noDefaultProvider(): Generator
|
||||
{
|
||||
foreach (self::NO_DEFAULTS as $varType => $values) {
|
||||
if (in_array($varType, self::ALLOW_EMPTY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $varType => [self::METHOD_NAMES[$varType][0], $values[0]];
|
||||
}
|
||||
}
|
||||
|
||||
public function test_default_ratio_for_non_existent_variable(): void
|
||||
{
|
||||
$value = Configuration::getRatio('not-set', 0);
|
||||
$this->assertSame(0.0, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider knownValuesProvider
|
||||
*/
|
||||
public function test_get_known_values(string $varName, array $varValue): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Configuration::getKnownValues($varName)
|
||||
);
|
||||
}
|
||||
|
||||
public function knownValuesProvider(): array
|
||||
{
|
||||
return self::KNOWN_VALUES;
|
||||
}
|
||||
|
||||
public function test_retrieve_value_library_default(): void
|
||||
{
|
||||
$value = 'simple';
|
||||
$variable = Variables::OTEL_PHP_TRACES_PROCESSOR;
|
||||
|
||||
$this->assertFalse(
|
||||
Configuration::has($variable)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$value,
|
||||
Configuration::getEnum($variable, $value)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typeProvider
|
||||
*/
|
||||
public function test_get_type(string $varName, string $type): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$type,
|
||||
Configuration::getType($varName)
|
||||
);
|
||||
}
|
||||
|
||||
public function typeProvider(): array
|
||||
{
|
||||
return [
|
||||
'bool' => ['OTEL_EXPORTER_OTLP_INSECURE', VariableTypes::BOOL],
|
||||
'string' => ['OTEL_SERVICE_NAME', VariableTypes::STRING],
|
||||
'integer' => ['OTEL_EXPORTER_JAEGER_AGENT_PORT', VariableTypes::INTEGER],
|
||||
'enum' => ['OTEL_LOG_LEVEL', VariableTypes::ENUM],
|
||||
'list' => ['OTEL_PROPAGATORS', VariableTypes::LIST],
|
||||
'map' => ['OTEL_RESOURCE_ATTRIBUTES', VariableTypes::MAP],
|
||||
'mixed' => ['OTEL_TRACES_SAMPLER_ARG', VariableTypes::MIXED],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider defaultValueProvider
|
||||
*/
|
||||
public function test_get_default_value_with_empty_var(string $varName, $varValue): void
|
||||
{
|
||||
$this->setEnvironmentVariable($varName, '');
|
||||
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Configuration::getDefault($varName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider defaultValueProvider
|
||||
*/
|
||||
public function test_get_default_value(string $varName, $varValue): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Configuration::getDefault($varName)
|
||||
);
|
||||
}
|
||||
|
||||
public function defaultValueProvider(): array
|
||||
{
|
||||
return self::DEFAULT_VALUES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonStringProvider
|
||||
*/
|
||||
public function test_get_non_string_value(string $method, $value): void
|
||||
{
|
||||
$_SERVER['OTEL_FOO'] = $value;
|
||||
$this->assertTrue(Configuration::has('OTEL_FOO'));
|
||||
$this->assertSame($value, call_user_func([Configuration::class, $method], 'OTEL_FOO'));
|
||||
}
|
||||
|
||||
public function nonStringProvider(): array
|
||||
{
|
||||
return [
|
||||
['getFloat', 3.14159],
|
||||
['getInt', 22],
|
||||
['getBoolean', true],
|
||||
['getRatio', 0.44],
|
||||
['getMixed', [25, 'green']],
|
||||
['getList', ['foo', 'bar']],
|
||||
['getMap', ['key1' => 'val1', 'key2' => 'val2']],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\BooleanParser;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Parser\BooleanParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\Parser\BooleanParser
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Parser\BooleanParser
|
||||
*/
|
||||
class BooleanParserTest extends TestCase
|
||||
{
|
||||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration\Parser;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\ListParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\Parser\ListParser
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Parser\ListParser
|
||||
*/
|
||||
class ListParserTest extends TestCase
|
||||
{
|
||||
|
|
@ -41,7 +40,7 @@ class ListParserTest extends TestCase
|
|||
public function test_comma_separated_list_returns_array(string $value, array $expected): void
|
||||
{
|
||||
$this->assertSame(
|
||||
ListParser::parse($value),
|
||||
\OpenTelemetry\SDK\Common\Configuration\Parser\ListParser::parse($value),
|
||||
$expected
|
||||
);
|
||||
}
|
||||
|
|
@ -2,14 +2,13 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\MapParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\Parser\MapParser
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Parser\MapParser
|
||||
*/
|
||||
class MapParserTest extends TestCase
|
||||
{
|
||||
|
|
@ -43,7 +42,7 @@ class MapParserTest extends TestCase
|
|||
public function test_map_values_return_array(string $value, array $expected): void
|
||||
{
|
||||
$this->assertSame(
|
||||
MapParser::parse($value),
|
||||
\OpenTelemetry\SDK\Common\Configuration\Parser\MapParser::parse($value),
|
||||
$expected
|
||||
);
|
||||
}
|
||||
|
|
@ -55,7 +54,7 @@ class MapParserTest extends TestCase
|
|||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
MapParser::parse($value);
|
||||
\OpenTelemetry\SDK\Common\Configuration\Parser\MapParser::parse($value);
|
||||
}
|
||||
|
||||
public function mapValueProvider(): array
|
||||
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment\Parser;
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\SDK\Common\Environment\Parser\RatioParser;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Parser\RatioParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RangeException;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\Parser\RatioParser
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Parser\RatioParser
|
||||
*/
|
||||
class RatioParserTest extends TestCase
|
||||
{
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration\Resolver;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Defaults;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Resolver\CompositeResolver;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Resolver\ResolverInterface;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Resolver\CompositeResolver
|
||||
* @psalm-suppress UndefinedInterfaceMethod
|
||||
*/
|
||||
class CompositeResolverTest extends TestCase
|
||||
{
|
||||
private ResolverInterface $one;
|
||||
private ResolverInterface $two;
|
||||
private CompositeResolver $resolver;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->one = $this->createMock(ResolverInterface::class);
|
||||
$this->two = $this->createMock(ResolverInterface::class);
|
||||
$this->resolver = new CompositeResolver([$this->one, $this->two]);
|
||||
}
|
||||
|
||||
public function test_get_instance(): void
|
||||
{
|
||||
$instance = CompositeResolver::instance();
|
||||
$this->assertGreaterThanOrEqual(1, count($instance->getResolvers()));
|
||||
}
|
||||
|
||||
public function test_has_variable(): void
|
||||
{
|
||||
$this->one->expects($this->once())->method('hasVariable')->willReturn(false);
|
||||
$this->two->expects($this->once())->method('hasVariable')->willReturn(true);
|
||||
|
||||
$this->assertTrue($this->resolver->hasVariable('OTEL_FOO'));
|
||||
}
|
||||
|
||||
public function test_not_has_variable(): void
|
||||
{
|
||||
$this->one->expects($this->once())->method('hasVariable')->willReturn(false);
|
||||
$this->two->expects($this->once())->method('hasVariable')->willReturn(false);
|
||||
|
||||
$this->assertFalse($this->resolver->hasVariable('OTEL_FOO'));
|
||||
}
|
||||
|
||||
public function test_resolve_when_has_variable(): void
|
||||
{
|
||||
$var = 'OTEL_FOO';
|
||||
$this->one->method('hasVariable')->willReturn(false);
|
||||
$this->two->method('hasVariable')->willReturn(true);
|
||||
$this->two
|
||||
->expects($this->once())
|
||||
->method('retrieveValue')
|
||||
->with($var)
|
||||
->willReturn('foo');
|
||||
|
||||
$this->assertSame('foo', $this->resolver->resolve($var));
|
||||
}
|
||||
|
||||
public function test_resolve_uses_default_when_not_empty(): void
|
||||
{
|
||||
$this->one->method('hasVariable')->willReturn(false);
|
||||
$this->two->method('hasVariable')->willReturn(false);
|
||||
|
||||
$this->assertSame('foo', $this->resolver->resolve(Variables::OTEL_EXPORTER_OTLP_PROTOCOL, 'foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_resolve_uses_library_default_when_empty(?string $value): void
|
||||
{
|
||||
$this->one->method('hasVariable')->willReturn(false);
|
||||
$this->two->method('hasVariable')->willReturn(false);
|
||||
|
||||
$this->assertSame(Defaults::OTEL_EXPORTER_OTLP_PROTOCOL, $this->resolver->resolve(Variables::OTEL_EXPORTER_OTLP_PROTOCOL, $value));
|
||||
}
|
||||
|
||||
public function emptyProvider(): array
|
||||
{
|
||||
return [
|
||||
[''],
|
||||
[null],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Configuration\Resolver;
|
||||
|
||||
use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Resolver\EnvironmentResolver;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Resolver\EnvironmentResolver
|
||||
*/
|
||||
class EnvironmentResolverTest extends TestCase
|
||||
{
|
||||
use EnvironmentVariables;
|
||||
|
||||
private const RAW_VALUES = [
|
||||
'string' => ['STRING_VAR', 'foo'],
|
||||
'int' => ['INT_VAR', '42'],
|
||||
'float' => ['FLOAT_VAR', '4.2'],
|
||||
'list' => ['LIST_VAR', 'foo,bar,baz'],
|
||||
'map' => ['MAP_VAR', 'foo=bar,bar=baz'],
|
||||
];
|
||||
|
||||
private EnvironmentResolver $resolver;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->resolver = new EnvironmentResolver();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->restoreEnvironmentVariables();
|
||||
}
|
||||
|
||||
public function test_has_variable(): void
|
||||
{
|
||||
$this->assertFalse(
|
||||
$this->resolver->hasVariable('FOO_VAR')
|
||||
);
|
||||
|
||||
$this->setEnvironmentVariable('FOO_VAR', 'FOO');
|
||||
|
||||
$this->assertTrue(
|
||||
$this->resolver->hasVariable('FOO_VAR')
|
||||
);
|
||||
}
|
||||
|
||||
public function test_has_variable_with_injected_value(): void
|
||||
{
|
||||
$this->assertFalse(
|
||||
$this->resolver->hasVariable('FOO_VAR')
|
||||
);
|
||||
|
||||
$this->injectEnvironmentVariable('FOO_VAR', 'FOO');
|
||||
|
||||
$this->assertTrue(
|
||||
$this->resolver->hasVariable('FOO_VAR')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider rawValueProvider
|
||||
*/
|
||||
public function test_retrieve_value(string $varName, string $varValue): void
|
||||
{
|
||||
$this->setEnvironmentVariable($varName, $varValue);
|
||||
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
$this->resolver->retrieveValue($varName)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_retrieve_value_no_var(): void
|
||||
{
|
||||
$this->assertFalse(
|
||||
$this->resolver->hasVariable('FOO_VAR')
|
||||
);
|
||||
|
||||
$this->assertNull(
|
||||
$this->resolver->retrieveValue('FOO_VAR')
|
||||
);
|
||||
}
|
||||
|
||||
public function test_retrieve_value_with_injected_value(): void
|
||||
{
|
||||
$value = 'simple';
|
||||
$variable = 'OTEL_PHP_TRACES_PROCESSOR';
|
||||
|
||||
$this->assertFalse(
|
||||
$this->resolver->hasVariable($variable)
|
||||
);
|
||||
|
||||
$this->injectEnvironmentVariable($variable, $value);
|
||||
|
||||
$this->assertSame(
|
||||
$value,
|
||||
$this->resolver->retrieveValue($variable)
|
||||
);
|
||||
}
|
||||
|
||||
public function rawValueProvider(): array
|
||||
{
|
||||
return self::RAW_VALUES;
|
||||
}
|
||||
|
||||
private function injectEnvironmentVariable(string $name, $value): void
|
||||
{
|
||||
$_SERVER[$name] = $value;
|
||||
}
|
||||
|
||||
public function test_get_array_from_env(): void
|
||||
{
|
||||
$this->injectEnvironmentVariable('OTEL_FOO', ['foo', 'bar']);
|
||||
$value = $this->resolver->retrieveValue('OTEL_FOO');
|
||||
$this->assertEqualsCanonicalizing(['foo', 'bar'], $value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Example\Unit\SDK\Common\Configuration\Resolver;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Resolver\PhpIniAccessor;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Resolver\PhpIniResolver;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Configuration\Resolver\PhpIniResolver
|
||||
* @psalm-suppress UndefinedMethod
|
||||
*/
|
||||
class PhpIniResolverTest extends TestCase
|
||||
{
|
||||
private PhpIniAccessor $accessor;
|
||||
private PhpIniResolver $resolver;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->accessor = $this->createMock(PhpIniAccessor::class);
|
||||
$this->resolver = new PhpIniResolver($this->accessor);
|
||||
}
|
||||
|
||||
public function test_retrieve_array(): void
|
||||
{
|
||||
$this->accessor->expects($this->once())->method('get')->willReturn(['foo', 'bar', 'baz']);
|
||||
$this->assertSame('foo,bar,baz', $this->resolver->retrieveValue('OTEL_FOO'));
|
||||
}
|
||||
|
||||
public function test_retrieve_string(): void
|
||||
{
|
||||
$this->accessor->expects($this->once())->method('get')->willReturn('foo');
|
||||
$this->assertSame('foo', $this->resolver->retrieveValue('OTEL_FOO'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hasVariableProvider
|
||||
*/
|
||||
public function test_has_variable($value, bool $expected): void
|
||||
{
|
||||
$this->accessor->method('get')->willReturn($value);
|
||||
$this->assertSame($expected, $this->resolver->hasVariable('OTEL_FOO'));
|
||||
}
|
||||
|
||||
public function hasVariableProvider(): array
|
||||
{
|
||||
return [
|
||||
'string' => ['foo', true],
|
||||
'array' => [['foo'], true],
|
||||
'empty string' => ['', false],
|
||||
'null' => [null, false],
|
||||
'empty array' => [[], false],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment;
|
||||
|
||||
use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
|
||||
use Generator;
|
||||
use OpenTelemetry\SDK\Common\Environment\Accessor;
|
||||
use OpenTelemetry\SDK\Common\Environment\Variables as Env;
|
||||
use OpenTelemetry\SDK\Common\Environment\VariableTypes;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\Accessor
|
||||
*/
|
||||
class AccessorTest extends TestCase
|
||||
{
|
||||
use EnvironmentVariables;
|
||||
|
||||
private const ALLOW_EMPTY = [
|
||||
VariableTypes::LIST,
|
||||
VariableTypes::MAP,
|
||||
VariableTypes::MIXED,
|
||||
];
|
||||
|
||||
private const METHOD_NAMES = [
|
||||
VariableTypes::STRING => ['getString'],
|
||||
VariableTypes::BOOL => ['getBool'],
|
||||
VariableTypes::INTEGER => ['getInt'],
|
||||
VariableTypes::FLOAT => ['getFloat'],
|
||||
VariableTypes::RATIO => ['getRatio'],
|
||||
VariableTypes::ENUM => ['getEnum'],
|
||||
VariableTypes::LIST => ['getList'],
|
||||
VariableTypes::MAP => ['getMap'],
|
||||
VariableTypes::MIXED => ['getMixed'],
|
||||
];
|
||||
|
||||
private const TYPES = [
|
||||
VariableTypes::STRING => [Env::OTEL_SERVICE_NAME],
|
||||
VariableTypes::BOOL => [Env::OTEL_EXPORTER_OTLP_INSECURE],
|
||||
VariableTypes::INTEGER => [Env::OTEL_EXPORTER_JAEGER_AGENT_PORT],
|
||||
VariableTypes::ENUM => [Env::OTEL_LOG_LEVEL],
|
||||
VariableTypes::LIST => [Env::OTEL_PROPAGATORS],
|
||||
VariableTypes::MAP => [Env::OTEL_RESOURCE_ATTRIBUTES],
|
||||
VariableTypes::MIXED => [Env::OTEL_TRACES_SAMPLER_ARG],
|
||||
];
|
||||
|
||||
private const USER_VALUES = [
|
||||
VariableTypes::STRING => ['foo', 'foo'],
|
||||
VariableTypes::BOOL => ['true', true],
|
||||
VariableTypes::INTEGER => ['42', 42],
|
||||
VariableTypes::ENUM => ['val1', 'val1'],
|
||||
VariableTypes::LIST => ['val1,val2', ['val1','val2']],
|
||||
VariableTypes::MAP => ['var1=val1,var2=val2', ['var1'=>'val1','var2'=>'val2']],
|
||||
VariableTypes::MIXED => ['foo', 'foo'],
|
||||
];
|
||||
|
||||
private const LIBRARY_DEFAULTS = [
|
||||
VariableTypes::STRING => [Env::OTEL_EXPORTER_OTLP_ENDPOINT, 'http://localhost:4318'],
|
||||
VariableTypes::BOOL => [Env::OTEL_EXPORTER_OTLP_INSECURE, false],
|
||||
VariableTypes::INTEGER => [Env::OTEL_EXPORTER_JAEGER_AGENT_PORT, 6831],
|
||||
VariableTypes::ENUM => [Env::OTEL_LOG_LEVEL, 'info'],
|
||||
VariableTypes::LIST => [Env::OTEL_PROPAGATORS, ['tracecontext', 'baggage']],
|
||||
];
|
||||
|
||||
private const NO_DEFAULTS = [
|
||||
VariableTypes::STRING => [Env::OTEL_SERVICE_NAME],
|
||||
VariableTypes::ENUM => [Env::OTEL_EXPORTER_OTLP_COMPRESSION],
|
||||
VariableTypes::MAP => [Env::OTEL_EXPORTER_OTLP_HEADERS],
|
||||
VariableTypes::MIXED => [Env::OTEL_TRACES_SAMPLER_ARG],
|
||||
];
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->restoreEnvironmentVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider userValueProvider
|
||||
*/
|
||||
public function test_return_user_env_vars(string $methodName, string $variable, string $value, $result)
|
||||
{
|
||||
$this->setEnvironmentVariable($variable, $value);
|
||||
|
||||
$this->assertSame(
|
||||
$result,
|
||||
call_user_func([Accessor::class, $methodName], $variable)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider userValueProvider
|
||||
*/
|
||||
public function test_return_user_default_value(string $methodName, string $variable, string $defaultValue, $result)
|
||||
{
|
||||
$this->assertSame(
|
||||
$result,
|
||||
call_user_func([Accessor::class, $methodName], $variable, $defaultValue)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider libraryDefaultValueProvider
|
||||
*/
|
||||
public function test_return_library_default_value(string $methodName, string $variable, $result)
|
||||
{
|
||||
$this->assertSame(
|
||||
$result,
|
||||
call_user_func([Accessor::class, $methodName], $variable)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonEmptyMethodNameProvider
|
||||
*/
|
||||
public function test_no_value_throws_exception(string $methodName)
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
call_user_func([Accessor::class, $methodName], 'FOO_BAR_' . $methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidTypeProvider
|
||||
*/
|
||||
public function test_invalid_type_throws_exception(string $methodName, string $variable)
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
call_user_func([Accessor::class, $methodName], $variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider noDefaultProvider
|
||||
*/
|
||||
public function test_null_result_throws_exception(string $methodName, string $variable)
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
call_user_func([Accessor::class, $methodName], $variable);
|
||||
}
|
||||
|
||||
public function userValueProvider(): Generator
|
||||
{
|
||||
foreach (self::USER_VALUES as $varType => $values) {
|
||||
[$default, $result] = $values;
|
||||
|
||||
yield $varType => [
|
||||
self::METHOD_NAMES[$varType][0],
|
||||
self::TYPES[$varType][0],
|
||||
$default,
|
||||
$result,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function libraryDefaultValueProvider(): Generator
|
||||
{
|
||||
foreach (self::LIBRARY_DEFAULTS as $varType => $values) {
|
||||
[$variable, $result] = $values;
|
||||
|
||||
yield $varType => [
|
||||
self::METHOD_NAMES[$varType][0],
|
||||
$variable,
|
||||
$result,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function nonEmptyMethodNameProvider(): Generator
|
||||
{
|
||||
foreach (self::METHOD_NAMES as $varType => $names) {
|
||||
if (in_array($varType, self::ALLOW_EMPTY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $varType => $names;
|
||||
}
|
||||
}
|
||||
|
||||
public function invalidTypeProvider(): Generator
|
||||
{
|
||||
foreach (self::METHOD_NAMES as $varType => $names) {
|
||||
if ($varType === VariableTypes::MIXED) {
|
||||
continue;
|
||||
}
|
||||
$methodName = $names[0];
|
||||
foreach (self::TYPES as $methodType => $types) {
|
||||
if ($varType === $methodType || $methodType === VariableTypes::MIXED) {
|
||||
continue;
|
||||
}
|
||||
$variableName = $types[0];
|
||||
|
||||
yield sprintf('%s - %s', $varType, $methodType) => [$methodName, $variableName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function noDefaultProvider(): Generator
|
||||
{
|
||||
foreach (self::NO_DEFAULTS as $varType => $values) {
|
||||
if (in_array($varType, self::ALLOW_EMPTY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $varType => [self::METHOD_NAMES[$varType][0], $values[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment;
|
||||
|
||||
use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
|
||||
use Exception;
|
||||
use OpenTelemetry\SDK\Common\Environment\EnvironmentVariables as Env;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\EnvironmentVariables
|
||||
*/
|
||||
class EnvironmentVariablesTest extends TestCase
|
||||
{
|
||||
use EnvironmentVariables;
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->restoreEnvironmentVariables();
|
||||
}
|
||||
|
||||
public function test_has_environment_variable(): void
|
||||
{
|
||||
$this->assertFalse(Env::has('FOO_VAR'));
|
||||
$this->setEnvironmentVariable('FOO_VAR', 'FOO');
|
||||
$this->assertTrue(Env::has('FOO_VAR'));
|
||||
}
|
||||
|
||||
public function test_integer_get(): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', '100');
|
||||
$value = Env::getInt('OTEL_FOO', 999);
|
||||
$this->assertSame(100, $value);
|
||||
}
|
||||
|
||||
public function test_integer_failure(): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', 'foo');
|
||||
$this->expectException(Exception::class);
|
||||
Env::getInt('OTEL_FOO', 99);
|
||||
}
|
||||
|
||||
public function environment_variables_integer_uses_default_if_env_var_not_defined()
|
||||
{
|
||||
$this->assertSame(20, Env::getInt('OTEL_FOO', 20));
|
||||
}
|
||||
|
||||
public function test_string_get(): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', 'foo');
|
||||
$value = Env::getString('OTEL_FOO', 'bar');
|
||||
$this->assertSame('foo', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The SDK MUST interpret an empty value of an environment variable the same way as when the variable is unset
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_string_uses_default_when_empty_value(?string $input): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', $input);
|
||||
$value = Env::getString('OTEL_FOO', 'bar');
|
||||
$this->assertSame('bar', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_int_uses_default_when_empty_value(?string $input): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', $input);
|
||||
$value = Env::getInt('OTEL_FOO', 99);
|
||||
$this->assertSame(99, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider emptyProvider
|
||||
*/
|
||||
public function test_bool_uses_default_when_empty_value(?string $input): void
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_FOO', $input);
|
||||
$value = Env::getBoolean('OTEL_FOO', true);
|
||||
$this->assertTrue($value);
|
||||
}
|
||||
|
||||
public function emptyProvider()
|
||||
{
|
||||
return [
|
||||
'no value' => [null],
|
||||
'empty string' => [''],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider booleanProvider
|
||||
*/
|
||||
public function test_bool_get(string $input, bool $default, bool $expected)
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_BOOL', $input);
|
||||
$this->assertSame($expected, Env::getBoolean('OTEL_BOOL', $default));
|
||||
}
|
||||
|
||||
public function booleanProvider()
|
||||
{
|
||||
return [
|
||||
'false' => ['false', true, false],
|
||||
'true' => ['true', false, true],
|
||||
'truthy' => ['1', false, true],
|
||||
'falsey' => ['0', true, false],
|
||||
'TRUE' => ['TRUE', false, true],
|
||||
'FALSE' => ['FALSE', true, false],
|
||||
];
|
||||
}
|
||||
|
||||
public function test_list_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_LIST', 'a,b,c');
|
||||
$this->assertSame(['a', 'b', 'c'], Env::getList('OTEL_LIST'));
|
||||
}
|
||||
|
||||
public function test_map_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_MAP', 'a=b,c=d');
|
||||
$this->assertSame(['a'=>'b', 'c'=>'d'], Env::getMap('OTEL_MAP'));
|
||||
}
|
||||
|
||||
public function test_enum_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_ENUM', 'foo');
|
||||
$this->assertSame('foo', Env::getEnum('OTEL_ENUM'));
|
||||
}
|
||||
|
||||
public function test_ratio_get()
|
||||
{
|
||||
$this->setEnvironmentVariable('OTEL_RATIO', '0.5');
|
||||
$this->assertSame(0.5, Env::getRatio('OTEL_RATIO'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,271 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\Environment;
|
||||
|
||||
use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
|
||||
use OpenTelemetry\SDK\Common\Environment\Defaults;
|
||||
use OpenTelemetry\SDK\Common\Environment\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Environment\Resolver;
|
||||
use OpenTelemetry\SDK\Common\Environment\VariableTypes;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\SDK\Common\Environment\Resolver
|
||||
*/
|
||||
class ResolverTest extends TestCase
|
||||
{
|
||||
use EnvironmentVariables;
|
||||
|
||||
private const RAW_VALUES = [
|
||||
'string' => ['STRING_VAR', 'foo'],
|
||||
'int' => ['INT_VAR', '42'],
|
||||
'float' => ['FLOAT_VAR', '4.2'],
|
||||
'list' => ['LIST_VAR', 'foo,bar,baz'],
|
||||
'map' => ['MAP_VAR', 'foo=bar,bar=baz'],
|
||||
];
|
||||
|
||||
private const DEFAULT_VALUES = [
|
||||
'log level' => ['OTEL_LOG_LEVEL', Defaults::OTEL_LOG_LEVEL],
|
||||
'attribute count limit' => ['OTEL_ATTRIBUTE_COUNT_LIMIT', Defaults::OTEL_ATTRIBUTE_COUNT_LIMIT],
|
||||
'trace exporter' => ['OTEL_PHP_TRACES_PROCESSOR', Defaults::OTEL_PHP_TRACES_PROCESSOR],
|
||||
];
|
||||
|
||||
private const TYPES = [
|
||||
'bool' => ['OTEL_EXPORTER_OTLP_INSECURE', VariableTypes::BOOL],
|
||||
'string' => ['OTEL_SERVICE_NAME', VariableTypes::STRING],
|
||||
'integer' => ['OTEL_EXPORTER_JAEGER_AGENT_PORT', VariableTypes::INTEGER],
|
||||
'enum' => ['OTEL_LOG_LEVEL', VariableTypes::ENUM],
|
||||
'list' => ['OTEL_PROPAGATORS', VariableTypes::LIST],
|
||||
'map' => ['OTEL_RESOURCE_ATTRIBUTES', VariableTypes::MAP],
|
||||
'mixed' => ['OTEL_TRACES_SAMPLER_ARG', VariableTypes::MIXED],
|
||||
];
|
||||
|
||||
private const KNOWN_VALUES = [
|
||||
'log level' => ['OTEL_LOG_LEVEL', KnownValues::OTEL_LOG_LEVEL],
|
||||
'trace sampler' => ['OTEL_TRACES_SAMPLER', KnownValues::OTEL_TRACES_SAMPLER],
|
||||
'trace processor' => ['OTEL_PHP_TRACES_PROCESSOR', KnownValues::OTEL_PHP_TRACES_PROCESSOR],
|
||||
];
|
||||
|
||||
/**
|
||||
* All injected environment variables.
|
||||
*/
|
||||
private array $injectedEnvironmentVariables = [];
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->resetEnvironmentVariables();
|
||||
}
|
||||
|
||||
public function test_has_variable(): void
|
||||
{
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable('FOO_VAR')
|
||||
);
|
||||
|
||||
$this->setEnvironmentVariable('FOO_VAR', 'FOO');
|
||||
|
||||
$this->assertTrue(
|
||||
Resolver::hasVariable('FOO_VAR')
|
||||
);
|
||||
}
|
||||
|
||||
public function test_has_variable_with_injected_value(): void
|
||||
{
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable('FOO_VAR')
|
||||
);
|
||||
|
||||
$this->injectEnvironmentVariable('FOO_VAR', 'FOO');
|
||||
|
||||
$this->assertTrue(
|
||||
Resolver::hasVariable('FOO_VAR')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider rawValueProvider
|
||||
*/
|
||||
public function test_get_raw_value(string $varName, string $varValue): void
|
||||
{
|
||||
$this->setEnvironmentVariable($varName, $varValue);
|
||||
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Resolver::getRawValue($varName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider rawValueProvider
|
||||
*/
|
||||
public function test_get_raw_value_with_injected_value(string $varName, string $varValue): void
|
||||
{
|
||||
$this->injectEnvironmentVariable($varName, $varValue);
|
||||
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Resolver::getRawValue($varName)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_get_raw_value_no_var(): void
|
||||
{
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable('FOO_VAR')
|
||||
);
|
||||
|
||||
$this->assertNull(
|
||||
Resolver::getRawValue('FOO_VAR')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider defaultValueProvider
|
||||
*/
|
||||
public function test_get_default_value(string $varName, $varValue): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Resolver::getDefault($varName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider defaultValueProvider
|
||||
*/
|
||||
public function test_get_default_value_with_empty_var(string $varName, $varValue): void
|
||||
{
|
||||
$this->setEnvironmentVariable($varName, '');
|
||||
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Resolver::getDefault($varName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typeProvider
|
||||
*/
|
||||
public function test_get_type(string $varName, string $type): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$type,
|
||||
Resolver::getType($varName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider knownValuesProvider
|
||||
*/
|
||||
public function test_get_known_values(string $varName, array $varValue): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$varValue,
|
||||
Resolver::getKnownValues($varName)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_resolve_value(): void
|
||||
{
|
||||
$value = 'simple';
|
||||
$variable = 'OTEL_PHP_TRACES_PROCESSOR';
|
||||
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable($variable)
|
||||
);
|
||||
|
||||
$this->setEnvironmentVariable($variable, $value);
|
||||
|
||||
$this->assertSame(
|
||||
$value,
|
||||
Resolver::resolveValue($variable)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_resolve_value_with_injected_value(): void
|
||||
{
|
||||
$value = 'simple';
|
||||
$variable = 'OTEL_PHP_TRACES_PROCESSOR';
|
||||
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable($variable)
|
||||
);
|
||||
|
||||
$this->injectEnvironmentVariable($variable, $value);
|
||||
|
||||
$this->assertSame(
|
||||
$value,
|
||||
Resolver::resolveValue($variable)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_resolve_value_library_default(): void
|
||||
{
|
||||
$value = 'simple';
|
||||
$variable = 'OTEL_PHP_TRACES_PROCESSOR';
|
||||
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable($variable)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$value,
|
||||
Resolver::resolveValue($variable, $value)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_resolve_value_user_default(): void
|
||||
{
|
||||
$value = Defaults::OTEL_PHP_TRACES_PROCESSOR;
|
||||
$variable = 'OTEL_PHP_TRACES_PROCESSOR';
|
||||
|
||||
$this->assertFalse(
|
||||
Resolver::hasVariable($variable)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$value,
|
||||
Resolver::resolveValue($variable)
|
||||
);
|
||||
}
|
||||
|
||||
public function rawValueProvider(): array
|
||||
{
|
||||
return self::RAW_VALUES;
|
||||
}
|
||||
|
||||
public function defaultValueProvider(): array
|
||||
{
|
||||
return self::DEFAULT_VALUES;
|
||||
}
|
||||
|
||||
public function typeProvider(): array
|
||||
{
|
||||
return self::TYPES;
|
||||
}
|
||||
|
||||
public function knownValuesProvider(): array
|
||||
{
|
||||
return self::KNOWN_VALUES;
|
||||
}
|
||||
|
||||
private function injectEnvironmentVariable(string $name, string $value): void
|
||||
{
|
||||
if (!in_array($name, $this->injectedEnvironmentVariables, true)) {
|
||||
$this->injectedEnvironmentVariables[] = $name;
|
||||
}
|
||||
|
||||
$_ENV[$name] = $value;
|
||||
}
|
||||
|
||||
private function resetEnvironmentVariables(): void
|
||||
{
|
||||
$this->restoreEnvironmentVariables();
|
||||
|
||||
foreach ($this->injectedEnvironmentVariables as $variable) {
|
||||
unset($_ENV[$variable]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue