implement scope configuration (#1353)
This commit is contained in:
parent
382331e062
commit
41dd113030
|
|
@ -284,6 +284,7 @@ return [
|
|||
'PhanAccessClassInternal',
|
||||
'PhanAccessMethodInternal',
|
||||
'PhanAccessPropertyInternal',
|
||||
'PhanTypeMismatchPropertyReal',
|
||||
'PhanTemplateTypeNotUsedInFunctionReturn',
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -38,3 +38,15 @@ parameters:
|
|||
message: "#Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeParentInterface::.*#"
|
||||
paths:
|
||||
- src/Config/SDK
|
||||
-
|
||||
message: "#Cannot call method .* on null#"
|
||||
paths:
|
||||
- tests/Integration/SDK/Trace
|
||||
-
|
||||
message: "#Property .*Logger.*config .* does not accept .*Config?#"
|
||||
paths:
|
||||
- src/SDK/Logs
|
||||
-
|
||||
message: "#.*return with type T is not subtype.*#"
|
||||
paths:
|
||||
- src/SDK/Common/InstrumentationScope
|
||||
|
|
@ -21,7 +21,7 @@ class LateBindingLogger implements LoggerInterface
|
|||
($this->logger ??= ($this->factory)())->emit($logRecord);
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ interface LoggerInterface
|
|||
* are about to generate a LogRecord, to avoid performing computationally expensive work.
|
||||
* @experimental
|
||||
*/
|
||||
public function enabled(): bool;
|
||||
public function isEnabled(): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class NoopLogger implements LoggerInterface
|
|||
{
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use OpenTelemetry\Context\ContextInterface;
|
|||
*
|
||||
* @experimental
|
||||
*/
|
||||
interface GaugeInterface
|
||||
interface GaugeInterface extends SynchronousInstrument
|
||||
{
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@ interface Instrument
|
|||
{
|
||||
/**
|
||||
* Determine if the instrument is enabled. Instrumentation authors SHOULD call this API each time they record a measurement.
|
||||
*
|
||||
* MUST return false if:
|
||||
* - The MeterConfig of the Meter used to create the instrument has parameter disabled=true
|
||||
* - All resolved views for the instrument are configured with the Drop Aggregation
|
||||
* @experimental
|
||||
* @see https://opentelemetry.io/docs/specs/otel/metrics/sdk/#instrument-enabled
|
||||
*/
|
||||
public function enabled(): bool;
|
||||
public function isEnabled(): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,4 +58,9 @@ class LateBindingMeter implements MeterInterface
|
|||
{
|
||||
return ($this->meter ??= ($this->factory)())->createObservableUpDownCounter($name, $unit, $description, $advisory, $callbacks);
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,4 +178,6 @@ interface MeterInterface
|
|||
array|callable $advisory = [],
|
||||
callable ...$callbacks,
|
||||
): ObservableUpDownCounterInterface;
|
||||
|
||||
public function isEnabled(): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ final class NoopCounter implements CounterInterface
|
|||
// no-op
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,4 +15,9 @@ final class NoopGauge implements GaugeInterface
|
|||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ final class NoopHistogram implements HistogramInterface
|
|||
// no-op
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,4 +56,9 @@ final class NoopMeter implements MeterInterface
|
|||
{
|
||||
return new NoopObservableUpDownCounter();
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ final class NoopObservableCounter implements ObservableCounterInterface
|
|||
return new NoopObservableCallback();
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ final class NoopObservableGauge implements ObservableGaugeInterface
|
|||
return new NoopObservableCallback();
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ final class NoopObservableUpDownCounter implements ObservableUpDownCounterInterf
|
|||
return new NoopObservableCallback();
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ final class NoopUpDownCounter implements UpDownCounterInterface
|
|||
// no-op
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class LateBindingTracer implements TracerInterface
|
|||
return ($this->tracer ??= ($this->factory)())->spanBuilder($spanName);
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ final class NoopTracer implements TracerInterface
|
|||
return new NoopSpanBuilder(Context::storage());
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ interface TracerInterface
|
|||
* creating a new span.
|
||||
* @experimental
|
||||
*/
|
||||
public function enabled(): bool;
|
||||
public function isEnabled(): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\InstrumentationScope;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface Config
|
||||
{
|
||||
public function setDisabled(bool $disabled): void;
|
||||
public function isEnabled(): bool;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\InstrumentationScope;
|
||||
|
||||
trait ConfigTrait
|
||||
{
|
||||
private bool $disabled = false;
|
||||
|
||||
public function setDisabled(bool $disabled): void
|
||||
{
|
||||
$this->disabled = $disabled;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->disabled === false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\InstrumentationScope;
|
||||
|
||||
interface Configurable
|
||||
{
|
||||
public function updateConfigurator(Configurator $configurator): void;
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\InstrumentationScope;
|
||||
|
||||
use Closure;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
|
||||
use OpenTelemetry\SDK\Logs\LoggerConfig;
|
||||
use OpenTelemetry\SDK\Metrics\MeterConfig;
|
||||
use OpenTelemetry\SDK\Trace\TracerConfig;
|
||||
use WeakMap;
|
||||
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
final class Configurator
|
||||
{
|
||||
/** @var Closure(InstrumentationScopeInterface): T */
|
||||
private readonly Closure $factory;
|
||||
/** @var WeakMap<InstrumentationScopeInterface, T> */
|
||||
private WeakMap $configs;
|
||||
/** @var list<ConfiguratorClosure> */
|
||||
private array $configurators = [];
|
||||
|
||||
/**
|
||||
* @param Closure(InstrumentationScopeInterface): T $factory
|
||||
* @psalm-suppress PropertyTypeCoercion
|
||||
*/
|
||||
public function __construct(Closure $factory)
|
||||
{
|
||||
$this->configs = new WeakMap();
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Closure(T, InstrumentationScopeInterface): void $closure
|
||||
*/
|
||||
public function with(Closure $closure, ?string $name, ?string $version = null, ?string $schemaUrl = null): self
|
||||
{
|
||||
$this->configurators[] = $configurator = new ConfiguratorClosure($closure, self::namePattern($name), $version, $schemaUrl);
|
||||
|
||||
foreach ($this->configs as $instrumentationScope => $config) {
|
||||
if ($configurator->matches($instrumentationScope)) {
|
||||
($configurator->closure)($config, $instrumentationScope);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T
|
||||
*/
|
||||
public function resolve(InstrumentationScopeInterface $instrumentationScope): Config
|
||||
{
|
||||
if ($config = $this->configs[$instrumentationScope] ?? null) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
$config = ($this->factory)($instrumentationScope);
|
||||
foreach ($this->configurators as $configurator) {
|
||||
if ($configurator->matches($instrumentationScope)) {
|
||||
($configurator->closure)($config, $instrumentationScope);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->configs[$instrumentationScope] ??= $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default Configurator for a LoggerConfig
|
||||
* @return Configurator<LoggerConfig>
|
||||
*/
|
||||
public static function logger(): self
|
||||
{
|
||||
return (new Configurator(static fn () => new LoggerConfig()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default Configurator for a MeterConfig
|
||||
* @return Configurator<MeterConfig>
|
||||
*/
|
||||
public static function meter(): self
|
||||
{
|
||||
return (new Configurator(static fn () => new MeterConfig()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default Configurator for a TracerConfig
|
||||
* @return Configurator<TracerConfig>
|
||||
*/
|
||||
public static function tracer(): self
|
||||
{
|
||||
return (new Configurator(static fn () => new TracerConfig()));
|
||||
}
|
||||
|
||||
private static function namePattern(?string $name): ?string
|
||||
{
|
||||
return $name !== null
|
||||
? sprintf('/^%s$/', strtr(preg_quote($name, '/'), ['\\?' => '.', '\\*' => '.*']))
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Common\InstrumentationScope;
|
||||
|
||||
use Closure;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class ConfiguratorClosure
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
public readonly Closure $closure,
|
||||
private readonly ?string $name,
|
||||
private readonly ?string $version,
|
||||
private readonly ?string $schemaUrl,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress ArgumentTypeCoercion
|
||||
*/
|
||||
public function matches(InstrumentationScopeInterface $instrumentationScope): bool
|
||||
{
|
||||
return ($this->name === null || preg_match($this->name, $instrumentationScope->getName()))
|
||||
&& ($this->version === null || $this->version === $instrumentationScope->getVersion())
|
||||
&& ($this->schemaUrl === null || $this->schemaUrl === $instrumentationScope->getSchemaUrl());
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ use OpenTelemetry\API\Behavior\LogsMessagesTrait;
|
|||
use OpenTelemetry\API\Logs\LoggerInterface;
|
||||
use OpenTelemetry\API\Logs\LogRecord;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
|
||||
/**
|
||||
* Note that this logger class is deliberately NOT psr-3 compatible, per spec: "Note: this document defines a log
|
||||
|
|
@ -18,18 +19,26 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
|
|||
class Logger implements LoggerInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
private LoggerConfig $config;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param Configurator<LoggerConfig>|null $configurator
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly LoggerSharedState $loggerSharedState,
|
||||
private readonly InstrumentationScopeInterface $scope,
|
||||
?Configurator $configurator = null,
|
||||
) {
|
||||
$this->config = $configurator ? $configurator->resolve($scope) : LoggerConfig::default();
|
||||
}
|
||||
|
||||
public function emit(LogRecord $logRecord): void
|
||||
{
|
||||
//If a Logger is disabled, it MUST behave equivalently to No-op Logger.
|
||||
if ($this->isEnabled() === false) {
|
||||
return;
|
||||
}
|
||||
$readWriteLogRecord = new ReadWriteLogRecord($this->scope, $this->loggerSharedState, $logRecord);
|
||||
// @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/sdk.md#onemit
|
||||
$this->loggerSharedState->getProcessor()->onEmit(
|
||||
|
|
@ -43,8 +52,16 @@ class Logger implements LoggerInterface
|
|||
}
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
return $this->config->isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Configurator<LoggerConfig> $configurator
|
||||
*/
|
||||
public function updateConfig(Configurator $configurator): void
|
||||
{
|
||||
$this->config = $configurator->resolve($this->scope);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Logs;
|
||||
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\ConfigTrait;
|
||||
|
||||
class LoggerConfig implements Config
|
||||
{
|
||||
use ConfigTrait;
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,23 +8,31 @@ use OpenTelemetry\API\Logs\LoggerInterface;
|
|||
use OpenTelemetry\API\Logs\NoopLogger;
|
||||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
|
||||
use WeakMap;
|
||||
|
||||
class LoggerProvider implements LoggerProviderInterface
|
||||
{
|
||||
private readonly LoggerSharedState $loggerSharedState;
|
||||
private readonly WeakMap $loggers;
|
||||
|
||||
/**
|
||||
* @param Configurator<LoggerConfig>|null $configurator
|
||||
*/
|
||||
public function __construct(
|
||||
LogRecordProcessorInterface $processor,
|
||||
private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory,
|
||||
?ResourceInfo $resource = null,
|
||||
private ?Configurator $configurator = null,
|
||||
) {
|
||||
$this->loggerSharedState = new LoggerSharedState(
|
||||
$resource ?? ResourceInfoFactory::defaultResource(),
|
||||
(new LogRecordLimitsBuilder())->build(),
|
||||
$processor
|
||||
);
|
||||
$this->loggers = new WeakMap();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -36,8 +44,10 @@ class LoggerProvider implements LoggerProviderInterface
|
|||
return NoopLogger::getInstance();
|
||||
}
|
||||
$scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes);
|
||||
$logger = new Logger($this->loggerSharedState, $scope, $this->configurator);
|
||||
$this->loggers->offsetSet($logger, null);
|
||||
|
||||
return new Logger($this->loggerSharedState, $scope);
|
||||
return $logger;
|
||||
}
|
||||
|
||||
public function shutdown(CancellationInterface $cancellation = null): bool
|
||||
|
|
@ -54,4 +64,17 @@ class LoggerProvider implements LoggerProviderInterface
|
|||
{
|
||||
return new LoggerProviderBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the {@link Configurator} for a {@link LoggerProvider}, which will
|
||||
* reconfigure all loggers created from the provider.
|
||||
* @experimental
|
||||
*/
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
foreach ($this->loggers as $logger => $unused) {
|
||||
$logger->updateConfig($configurator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace OpenTelemetry\SDK\Logs;
|
|||
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Logs\Processor\MultiLogRecordProcessor;
|
||||
use OpenTelemetry\SDK\Logs\Processor\NoopLogRecordProcessor;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
|
|
@ -15,6 +16,7 @@ class LoggerProviderBuilder
|
|||
/** @var array<LogRecordProcessorInterface> */
|
||||
private array $processors = [];
|
||||
private ?ResourceInfo $resource = null;
|
||||
private ?Configurator $configurator = null;
|
||||
|
||||
public function addLogRecordProcessor(LogRecordProcessorInterface $processor): self
|
||||
{
|
||||
|
|
@ -35,10 +37,18 @@ class LoggerProviderBuilder
|
|||
return new LoggerProvider(
|
||||
$this->buildProcessor(),
|
||||
new InstrumentationScopeFactory(Attributes::factory()),
|
||||
$this->resource
|
||||
$this->resource,
|
||||
configurator: $this->configurator ?? Configurator::logger(),
|
||||
);
|
||||
}
|
||||
|
||||
public function setConfigurator(Configurator $configurator): self
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function buildProcessor(): LogRecordProcessorInterface
|
||||
{
|
||||
return match (count($this->processors)) {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Logs;
|
||||
|
||||
use OpenTelemetry\API\Logs as API;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable;
|
||||
|
||||
interface LoggerProviderInterface extends API\LoggerProviderInterface
|
||||
interface LoggerProviderInterface extends API\LoggerProviderInterface, Configurable
|
||||
{
|
||||
public function shutdown(): bool;
|
||||
public function forceFlush(): bool;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace OpenTelemetry\SDK\Logs;
|
|||
|
||||
use OpenTelemetry\API\Logs\LoggerInterface;
|
||||
use OpenTelemetry\API\Logs\NoopLogger;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
|
||||
class NoopLoggerProvider implements LoggerProviderInterface
|
||||
{
|
||||
|
|
@ -30,4 +31,9 @@ class NoopLoggerProvider implements LoggerProviderInterface
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\SDK\Metrics;
|
||||
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
|
||||
final class Instrument
|
||||
{
|
||||
public function __construct(
|
||||
|
|
@ -12,6 +14,12 @@ final class Instrument
|
|||
public readonly ?string $unit,
|
||||
public readonly ?string $description,
|
||||
public readonly array $advisory = [],
|
||||
public readonly ?MeterInterface $meter = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->meter?->isEnabled() ?? true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ use OpenTelemetry\API\Metrics\ObservableGaugeInterface;
|
|||
use OpenTelemetry\API\Metrics\ObservableUpDownCounterInterface;
|
||||
use OpenTelemetry\API\Metrics\UpDownCounterInterface;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use function OpenTelemetry\SDK\Common\Util\closure;
|
||||
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MetricRegistration\MultiRegistryRegistration;
|
||||
|
|
@ -34,11 +37,12 @@ use function serialize;
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Meter implements MeterInterface
|
||||
final class Meter implements MeterInterface, Configurable
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private ?string $instrumentationScopeId = null;
|
||||
private Config $config;
|
||||
|
||||
/**
|
||||
* @param iterable<MetricSourceRegistryInterface&DefaultAggregationProviderInterface> $metricRegistries
|
||||
|
|
@ -57,7 +61,9 @@ final class Meter implements MeterInterface
|
|||
private readonly MetricRegistryInterface $registry,
|
||||
private readonly MetricWriterInterface $writer,
|
||||
private readonly ArrayAccess $destructors,
|
||||
private ?Configurator $configurator = null,
|
||||
) {
|
||||
$this->config = $this->configurator?->resolve($this->instrumentationScope) ?? MeterConfig::default();
|
||||
}
|
||||
|
||||
private static function dummyInstrument(): Instrument
|
||||
|
|
@ -67,6 +73,15 @@ final class Meter implements MeterInterface
|
|||
return $dummy ??= (new \ReflectionClass(Instrument::class))->newInstanceWithoutConstructor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
$this->config = $configurator->resolve($this->instrumentationScope);
|
||||
}
|
||||
|
||||
public function batchObserve(callable $callback, AsynchronousInstrument $instrument, AsynchronousInstrument ...$instruments): ObservableCallbackInterface
|
||||
{
|
||||
$referenceCounters = [];
|
||||
|
|
@ -116,7 +131,7 @@ final class Meter implements MeterInterface
|
|||
$advisory,
|
||||
);
|
||||
|
||||
return new Counter($this->writer, $instrument, $referenceCounter);
|
||||
return new Counter($this->writer, $instrument, $referenceCounter, $this);
|
||||
}
|
||||
|
||||
public function createObservableCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableCounterInterface
|
||||
|
|
@ -138,7 +153,7 @@ final class Meter implements MeterInterface
|
|||
$referenceCounter->acquire(true);
|
||||
}
|
||||
|
||||
return new ObservableCounter($this->writer, $instrument, $referenceCounter, $this->destructors);
|
||||
return new ObservableCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this);
|
||||
}
|
||||
|
||||
public function createHistogram(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): HistogramInterface
|
||||
|
|
@ -151,7 +166,7 @@ final class Meter implements MeterInterface
|
|||
$advisory,
|
||||
);
|
||||
|
||||
return new Histogram($this->writer, $instrument, $referenceCounter);
|
||||
return new Histogram($this->writer, $instrument, $referenceCounter, $this);
|
||||
}
|
||||
|
||||
public function createGauge(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): GaugeInterface
|
||||
|
|
@ -164,7 +179,7 @@ final class Meter implements MeterInterface
|
|||
$advisory,
|
||||
);
|
||||
|
||||
return new Gauge($this->writer, $instrument, $referenceCounter);
|
||||
return new Gauge($this->writer, $instrument, $referenceCounter, $this);
|
||||
}
|
||||
|
||||
public function createObservableGauge(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableGaugeInterface
|
||||
|
|
@ -186,7 +201,7 @@ final class Meter implements MeterInterface
|
|||
$referenceCounter->acquire(true);
|
||||
}
|
||||
|
||||
return new ObservableGauge($this->writer, $instrument, $referenceCounter, $this->destructors);
|
||||
return new ObservableGauge($this->writer, $instrument, $referenceCounter, $this->destructors, $this);
|
||||
}
|
||||
|
||||
public function createUpDownCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): UpDownCounterInterface
|
||||
|
|
@ -199,7 +214,7 @@ final class Meter implements MeterInterface
|
|||
$advisory,
|
||||
);
|
||||
|
||||
return new UpDownCounter($this->writer, $instrument, $referenceCounter);
|
||||
return new UpDownCounter($this->writer, $instrument, $referenceCounter, $this);
|
||||
}
|
||||
|
||||
public function createObservableUpDownCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableUpDownCounterInterface
|
||||
|
|
@ -221,7 +236,12 @@ final class Meter implements MeterInterface
|
|||
$referenceCounter->acquire(true);
|
||||
}
|
||||
|
||||
return new ObservableUpDownCounter($this->writer, $instrument, $referenceCounter, $this->destructors);
|
||||
return new ObservableUpDownCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this);
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->config->isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -245,7 +265,7 @@ final class Meter implements MeterInterface
|
|||
*/
|
||||
private function createSynchronousWriter(string|InstrumentType $instrumentType, string $name, ?string $unit, ?string $description, array $advisory = []): array
|
||||
{
|
||||
$instrument = new Instrument($instrumentType, $name, $unit, $description, $advisory);
|
||||
$instrument = new Instrument($instrumentType, $name, $unit, $description, $advisory, $this);
|
||||
|
||||
$instrumentationScopeId = $this->instrumentationScopeId($this->instrumentationScope);
|
||||
$instrumentId = $this->instrumentId($instrument);
|
||||
|
|
@ -291,7 +311,7 @@ final class Meter implements MeterInterface
|
|||
*/
|
||||
private function createAsynchronousObserver(string|InstrumentType $instrumentType, string $name, ?string $unit, ?string $description, array $advisory): array
|
||||
{
|
||||
$instrument = new Instrument($instrumentType, $name, $unit, $description, $advisory);
|
||||
$instrument = new Instrument($instrumentType, $name, $unit, $description, $advisory, $this);
|
||||
|
||||
$instrumentationScopeId = $this->instrumentationScopeId($this->instrumentationScope);
|
||||
$instrumentId = $this->instrumentId($instrument);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Metrics;
|
||||
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\ConfigTrait;
|
||||
|
||||
class MeterConfig implements Config
|
||||
{
|
||||
use ConfigTrait;
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ use OpenTelemetry\API\Metrics\Noop\NoopMeter;
|
|||
use OpenTelemetry\Context\ContextStorageInterface;
|
||||
use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MetricFactory\StreamFactory;
|
||||
use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricRegistry;
|
||||
|
|
@ -29,6 +30,7 @@ final class MeterProvider implements MeterProviderInterface
|
|||
private readonly ArrayAccess $destructors;
|
||||
|
||||
private bool $closed = false;
|
||||
private readonly WeakMap $meters;
|
||||
|
||||
/**
|
||||
* @param iterable<MetricReaderInterface&MetricSourceRegistryInterface&DefaultAggregationProviderInterface> $metricReaders
|
||||
|
|
@ -44,6 +46,7 @@ final class MeterProvider implements MeterProviderInterface
|
|||
private readonly ?ExemplarFilterInterface $exemplarFilter,
|
||||
private readonly StalenessHandlerFactoryInterface $stalenessHandlerFactory,
|
||||
MetricFactoryInterface $metricFactory = null,
|
||||
private ?Configurator $configurator = null,
|
||||
) {
|
||||
$this->metricFactory = $metricFactory ?? new StreamFactory();
|
||||
$this->instruments = new MeterInstruments();
|
||||
|
|
@ -52,6 +55,7 @@ final class MeterProvider implements MeterProviderInterface
|
|||
$this->registry = $registry;
|
||||
$this->writer = $registry;
|
||||
$this->destructors = new WeakMap();
|
||||
$this->meters = new WeakMap();
|
||||
}
|
||||
|
||||
public function getMeter(
|
||||
|
|
@ -64,7 +68,7 @@ final class MeterProvider implements MeterProviderInterface
|
|||
return new NoopMeter();
|
||||
}
|
||||
|
||||
return new Meter(
|
||||
$meter = new Meter(
|
||||
$this->metricFactory,
|
||||
$this->resource,
|
||||
$this->clock,
|
||||
|
|
@ -77,7 +81,11 @@ final class MeterProvider implements MeterProviderInterface
|
|||
$this->registry,
|
||||
$this->writer,
|
||||
$this->destructors,
|
||||
$this->configurator,
|
||||
);
|
||||
$this->meters->offsetSet($meter, null);
|
||||
|
||||
return $meter;
|
||||
}
|
||||
|
||||
public function shutdown(): bool
|
||||
|
|
@ -118,4 +126,19 @@ final class MeterProvider implements MeterProviderInterface
|
|||
{
|
||||
return new MeterProviderBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the {@link Configurator} for a {@link MeterProvider}, which will reconfigure
|
||||
* all meters created from the provider.
|
||||
* @todo enabling a previous-disabled meter does not drop/recreate the underlying metric streams, so previously collected synchronous metrics will still be exported.
|
||||
* @experimental
|
||||
*/
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
|
||||
foreach ($this->meters as $meter => $unused) {
|
||||
$meter->updateConfigurator($configurator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Metrics;
|
||||
|
||||
use OpenTelemetry\API\Common\Time\Clock;
|
||||
use OpenTelemetry\API\Common\Time\ClockInterface;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\WithSampledTraceExemplarFilter;
|
||||
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface;
|
||||
use OpenTelemetry\SDK\Metrics\StalenessHandler\NoopStalenessHandlerFactory;
|
||||
|
|
@ -20,6 +22,8 @@ class MeterProviderBuilder
|
|||
private array $metricReaders = [];
|
||||
private ?ResourceInfo $resource = null;
|
||||
private ?ExemplarFilterInterface $exemplarFilter = null;
|
||||
private ?Configurator $configurator = null;
|
||||
private ?ClockInterface $clock = null;
|
||||
|
||||
public function setResource(ResourceInfo $resource): self
|
||||
{
|
||||
|
|
@ -42,6 +46,20 @@ class MeterProviderBuilder
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setConfigurator(Configurator $configurator): self
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClock(ClockInterface $clock): self
|
||||
{
|
||||
$this->clock = $clock;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
*/
|
||||
|
|
@ -50,13 +68,14 @@ class MeterProviderBuilder
|
|||
return new MeterProvider(
|
||||
null,
|
||||
$this->resource ?? ResourceInfoFactory::emptyResource(),
|
||||
Clock::getDefault(),
|
||||
$this->clock ?? Clock::getDefault(),
|
||||
Attributes::factory(),
|
||||
new InstrumentationScopeFactory(Attributes::factory()),
|
||||
$this->metricReaders,
|
||||
new CriteriaViewRegistry(),
|
||||
$this->exemplarFilter ?? new WithSampledTraceExemplarFilter(),
|
||||
new NoopStalenessHandlerFactory(),
|
||||
configurator: $this->configurator ?? Configurator::meter(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\SDK\Metrics;
|
||||
|
||||
interface MeterProviderInterface extends \OpenTelemetry\API\Metrics\MeterProviderInterface
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable;
|
||||
|
||||
interface MeterProviderInterface extends \OpenTelemetry\API\Metrics\MeterProviderInterface, Configurable
|
||||
{
|
||||
public function shutdown(): bool;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,4 +39,9 @@ final class StreamMetricSource implements MetricSourceInterface
|
|||
{
|
||||
$this->provider->stream->unregister($this->reader);
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->provider->instrument->isEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,9 @@ final class ExportingReader implements MetricReaderInterface, MetricSourceRegist
|
|||
|
||||
$metrics = [];
|
||||
foreach ($this->sources as $source) {
|
||||
$metrics[] = $source->collect();
|
||||
if ($source->isEnabled()) {
|
||||
$metrics[] = $source->collect();
|
||||
}
|
||||
}
|
||||
|
||||
if ($metrics === []) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ final class MetricRegistry implements MetricRegistryInterface, MetricWriterInter
|
|||
private array $asynchronousCallbacks = [];
|
||||
/** @var array<int, list<int>> */
|
||||
private array $asynchronousCallbackArguments = [];
|
||||
/** @var array<int, Instrument> */
|
||||
private array $instruments = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly ?ContextStorageInterface $contextStorage,
|
||||
|
|
@ -55,6 +57,7 @@ final class MetricRegistry implements MetricRegistryInterface, MetricWriterInter
|
|||
$this->synchronousAggregators[$streamId] = $aggregator;
|
||||
$this->instrumentToStreams[$instrumentId][$streamId] = $streamId;
|
||||
$this->streamToInstrument[$streamId] = $instrumentId;
|
||||
$this->instruments[$instrumentId] = $instrument;
|
||||
|
||||
return $streamId;
|
||||
}
|
||||
|
|
@ -68,6 +71,7 @@ final class MetricRegistry implements MetricRegistryInterface, MetricWriterInter
|
|||
$this->asynchronousAggregatorFactories[$streamId] = $aggregatorFactory;
|
||||
$this->instrumentToStreams[$instrumentId][$streamId] = $streamId;
|
||||
$this->streamToInstrument[$streamId] = $instrumentId;
|
||||
$this->instruments[$instrumentId] = $instrument;
|
||||
|
||||
return $streamId;
|
||||
}
|
||||
|
|
@ -81,6 +85,7 @@ final class MetricRegistry implements MetricRegistryInterface, MetricWriterInter
|
|||
$this->asynchronousAggregatorFactories[$streamId],
|
||||
$this->instrumentToStreams[$instrumentId][$streamId],
|
||||
$this->streamToInstrument[$streamId],
|
||||
$this->instruments[$instrumentId],
|
||||
);
|
||||
if (!$this->instrumentToStreams[$instrumentId]) {
|
||||
unset($this->instrumentToStreams[$instrumentId]);
|
||||
|
|
@ -139,10 +144,16 @@ final class MetricRegistry implements MetricRegistryInterface, MetricWriterInter
|
|||
$observers = [];
|
||||
$callbackIds = [];
|
||||
foreach ($streamIds as $streamId) {
|
||||
$instrumentId = $this->streamToInstrument[$streamId];
|
||||
if (
|
||||
array_key_exists($instrumentId, $this->instruments)
|
||||
&& $this->instruments[$instrumentId]->meter?->isEnabled() === false
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (!$aggregator = $this->synchronousAggregators[$streamId] ?? null) {
|
||||
$aggregator = $this->asynchronousAggregatorFactories[$streamId]->create();
|
||||
|
||||
$instrumentId = $this->streamToInstrument[$streamId];
|
||||
$observers[$instrumentId] ??= new MultiObserver($this->attributesFactory, $timestamp);
|
||||
$observers[$instrumentId]->writers[] = $aggregator;
|
||||
foreach ($this->instrumentToCallbacks[$instrumentId] ?? [] as $callbackId) {
|
||||
|
|
|
|||
|
|
@ -21,4 +21,5 @@ interface MetricSourceInterface
|
|||
* @return Metric collected metric
|
||||
*/
|
||||
public function collect(): Metric;
|
||||
public function isEnabled(): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace OpenTelemetry\SDK\Metrics;
|
|||
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
use OpenTelemetry\API\Metrics\Noop\NoopMeter;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
|
||||
class NoopMeterProvider implements MeterProviderInterface
|
||||
{
|
||||
|
|
@ -23,4 +24,9 @@ class NoopMeterProvider implements MeterProviderInterface
|
|||
{
|
||||
return new NoopMeter();
|
||||
}
|
||||
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace OpenTelemetry\SDK\Metrics;
|
|||
|
||||
use ArrayAccess;
|
||||
use function assert;
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
use OpenTelemetry\API\Metrics\ObservableCallbackInterface;
|
||||
use OpenTelemetry\API\Metrics\ObserverInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface;
|
||||
|
|
@ -15,24 +16,15 @@ use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface;
|
|||
*/
|
||||
trait ObservableInstrumentTrait
|
||||
{
|
||||
private MetricWriterInterface $writer;
|
||||
private Instrument $instrument;
|
||||
private ReferenceCounterInterface $referenceCounter;
|
||||
private ArrayAccess $destructors;
|
||||
|
||||
public function __construct(
|
||||
MetricWriterInterface $writer,
|
||||
Instrument $instrument,
|
||||
ReferenceCounterInterface $referenceCounter,
|
||||
ArrayAccess $destructors,
|
||||
private readonly MetricWriterInterface $writer,
|
||||
private readonly Instrument $instrument,
|
||||
private readonly ReferenceCounterInterface $referenceCounter,
|
||||
private readonly ArrayAccess $destructors,
|
||||
private readonly MeterInterface $meter,
|
||||
) {
|
||||
assert($this instanceof InstrumentHandle);
|
||||
|
||||
$this->writer = $writer;
|
||||
$this->instrument = $instrument;
|
||||
$this->referenceCounter = $referenceCounter;
|
||||
$this->destructors = $destructors;
|
||||
|
||||
$this->referenceCounter->acquire();
|
||||
}
|
||||
|
||||
|
|
@ -60,8 +52,12 @@ trait ObservableInstrumentTrait
|
|||
);
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
if (!$this->meter->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->writer->enabled($this->instrument);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\SDK\Metrics;
|
||||
|
||||
use function assert;
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -15,14 +16,16 @@ trait SynchronousInstrumentTrait
|
|||
private MetricWriterInterface $writer;
|
||||
private Instrument $instrument;
|
||||
private ReferenceCounterInterface $referenceCounter;
|
||||
private MeterInterface $meter;
|
||||
|
||||
public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter)
|
||||
public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, MeterInterface $meter)
|
||||
{
|
||||
assert($this instanceof InstrumentHandle);
|
||||
|
||||
$this->writer = $writer;
|
||||
$this->instrument = $instrument;
|
||||
$this->referenceCounter = $referenceCounter;
|
||||
$this->meter = $meter;
|
||||
|
||||
$this->referenceCounter->acquire();
|
||||
}
|
||||
|
|
@ -39,11 +42,17 @@ trait SynchronousInstrumentTrait
|
|||
|
||||
public function write($amount, iterable $attributes = [], $context = null): void
|
||||
{
|
||||
$this->writer->record($this->instrument, $amount, $attributes, $context);
|
||||
if ($this->isEnabled()) {
|
||||
$this->writer->record($this->instrument, $amount, $attributes, $context);
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
if (!$this->meter->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->writer->enabled($this->instrument);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace OpenTelemetry\SDK\Trace;
|
|||
|
||||
use OpenTelemetry\API;
|
||||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
|
||||
class NoopTracerProvider extends API\Trace\NoopTracerProvider implements TracerProviderInterface
|
||||
{
|
||||
|
|
@ -18,4 +19,8 @@ class NoopTracerProvider extends API\Trace\NoopTracerProvider implements TracerP
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,20 @@ use function ctype_space;
|
|||
use OpenTelemetry\API\Trace as API;
|
||||
use OpenTelemetry\Context\Context;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
|
||||
class Tracer implements API\TracerInterface
|
||||
{
|
||||
public const FALLBACK_SPAN_NAME = 'empty';
|
||||
private Config $config;
|
||||
|
||||
public function __construct(
|
||||
private readonly TracerSharedState $tracerSharedState,
|
||||
private readonly InstrumentationScopeInterface $instrumentationScope,
|
||||
?Configurator $configurator = null,
|
||||
) {
|
||||
$this->config = $configurator ? $configurator->resolve($this->instrumentationScope) : TracerConfig::default();
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
@ -25,8 +30,8 @@ class Tracer implements API\TracerInterface
|
|||
if (ctype_space($spanName)) {
|
||||
$spanName = self::FALLBACK_SPAN_NAME;
|
||||
}
|
||||
|
||||
if ($this->tracerSharedState->hasShutdown()) {
|
||||
// If a Tracer is disabled, it MUST behave equivalently to No-op Tracer
|
||||
if (!$this->config->isEnabled() || $this->tracerSharedState->hasShutdown()) {
|
||||
return new API\NoopSpanBuilder(Context::storage());
|
||||
}
|
||||
|
||||
|
|
@ -42,8 +47,13 @@ class Tracer implements API\TracerInterface
|
|||
return $this->instrumentationScope;
|
||||
}
|
||||
|
||||
public function enabled(): bool
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
return $this->config->isEnabled();
|
||||
}
|
||||
|
||||
public function updateConfig(Configurator $configurator): void
|
||||
{
|
||||
$this->config = $configurator->resolve($this->instrumentationScope);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\SDK\Trace;
|
||||
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\ConfigTrait;
|
||||
|
||||
class TracerConfig implements Config
|
||||
{
|
||||
use ConfigTrait;
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
|
|
@ -11,15 +11,18 @@ use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
|||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
|
||||
use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
|
||||
use OpenTelemetry\SDK\Trace\Sampler\ParentBased;
|
||||
use WeakMap;
|
||||
|
||||
final class TracerProvider implements TracerProviderInterface
|
||||
{
|
||||
private readonly TracerSharedState $tracerSharedState;
|
||||
private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory;
|
||||
private readonly WeakMap $tracers;
|
||||
|
||||
/** @param list<SpanProcessorInterface>|SpanProcessorInterface|null $spanProcessors */
|
||||
public function __construct(
|
||||
|
|
@ -29,6 +32,7 @@ final class TracerProvider implements TracerProviderInterface
|
|||
SpanLimits $spanLimits = null,
|
||||
IdGeneratorInterface $idGenerator = null,
|
||||
?InstrumentationScopeFactoryInterface $instrumentationScopeFactory = null,
|
||||
private ?Configurator $configurator = null,
|
||||
) {
|
||||
$spanProcessors ??= [];
|
||||
$spanProcessors = is_array($spanProcessors) ? $spanProcessors : [$spanProcessors];
|
||||
|
|
@ -45,6 +49,7 @@ final class TracerProvider implements TracerProviderInterface
|
|||
$spanProcessors
|
||||
);
|
||||
$this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory());
|
||||
$this->tracers = new WeakMap();
|
||||
}
|
||||
|
||||
public function forceFlush(?CancellationInterface $cancellation = null): bool
|
||||
|
|
@ -65,10 +70,15 @@ final class TracerProvider implements TracerProviderInterface
|
|||
return NoopTracer::getInstance();
|
||||
}
|
||||
|
||||
return new Tracer(
|
||||
$scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes);
|
||||
$tracer = new Tracer(
|
||||
$this->tracerSharedState,
|
||||
$this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes),
|
||||
$scope,
|
||||
$this->configurator,
|
||||
);
|
||||
$this->tracers->offsetSet($tracer, null);
|
||||
|
||||
return $tracer;
|
||||
}
|
||||
|
||||
public function getSampler(): SamplerInterface
|
||||
|
|
@ -92,4 +102,18 @@ final class TracerProvider implements TracerProviderInterface
|
|||
{
|
||||
return new TracerProviderBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the {@link Configurator} for a {@link TracerProvider}, which will
|
||||
* reconfigure all tracers created from the provider.
|
||||
* @experimental
|
||||
*/
|
||||
public function updateConfigurator(Configurator $configurator): void
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
|
||||
foreach ($this->tracers as $tracer => $unused) {
|
||||
$tracer->updateConfig($configurator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\SDK\Trace;
|
||||
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
|
||||
class TracerProviderBuilder
|
||||
|
|
@ -12,6 +13,7 @@ class TracerProviderBuilder
|
|||
private ?array $spanProcessors = [];
|
||||
private ?ResourceInfo $resource = null;
|
||||
private ?SamplerInterface $sampler = null;
|
||||
private ?Configurator $configurator = null;
|
||||
|
||||
public function addSpanProcessor(SpanProcessorInterface $spanProcessor): self
|
||||
{
|
||||
|
|
@ -34,12 +36,20 @@ class TracerProviderBuilder
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setConfigurator(Configurator $configurator): self
|
||||
{
|
||||
$this->configurator = $configurator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): TracerProviderInterface
|
||||
{
|
||||
return new TracerProvider(
|
||||
$this->spanProcessors,
|
||||
$this->sampler,
|
||||
$this->resource,
|
||||
configurator: $this->configurator ?? Configurator::tracer(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ namespace OpenTelemetry\SDK\Trace;
|
|||
|
||||
use OpenTelemetry\API\Trace as API;
|
||||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable;
|
||||
|
||||
interface TracerProviderInterface extends API\TracerProviderInterface
|
||||
interface TracerProviderInterface extends API\TracerProviderInterface, Configurable
|
||||
{
|
||||
public function forceFlush(?CancellationInterface $cancellation = null): bool;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Benchmark;
|
||||
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
use OpenTelemetry\API\Metrics\ObserverInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Metrics\MeterConfig;
|
||||
use OpenTelemetry\SDK\Metrics\MeterProvider;
|
||||
use OpenTelemetry\SDK\Metrics\MetricExporter\NoopMetricExporter;
|
||||
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
|
||||
use OpenTelemetry\SDK\Metrics\MetricReaderInterface;
|
||||
|
||||
class MetricBench
|
||||
{
|
||||
private readonly MeterInterface $enabled;
|
||||
private readonly MeterInterface $disabled;
|
||||
private readonly MetricReaderInterface $reader;
|
||||
public function __construct()
|
||||
{
|
||||
$exporter = new NoopMetricExporter();
|
||||
$this->reader = new ExportingReader($exporter);
|
||||
$meterProvider = MeterProvider::builder()
|
||||
->addReader($this->reader)
|
||||
->setConfigurator(
|
||||
Configurator::meter()
|
||||
->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'disabled')
|
||||
)
|
||||
->build();
|
||||
$this->enabled = $meterProvider->getMeter('enabled');
|
||||
$this->disabled = $meterProvider->getMeter('disabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Revs({100, 1000})
|
||||
* @Iterations(10)
|
||||
* @OutputTimeUnit("microseconds")
|
||||
* @ParamProviders("provideMeasurementCounts")
|
||||
*/
|
||||
public function bench_sync_measurements(array $params): void
|
||||
{
|
||||
$meter = $params['enabled'] === false ? $this->disabled : $this->enabled;
|
||||
$counter = $meter->createCounter('a');
|
||||
for ($i=0; $i < $params['count']; $i++) {
|
||||
$counter->add(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Revs({100, 1000})
|
||||
* @Iterations(10)
|
||||
* @OutputTimeUnit("microseconds")
|
||||
* @ParamProviders("provideMeasurementCounts")
|
||||
* @Groups("async")
|
||||
*/
|
||||
public function bench_async_measurements(array $params): void
|
||||
{
|
||||
$meter = $params['enabled'] === false ? $this->disabled : $this->enabled;
|
||||
$meter->createObservableCounter('b', callbacks: function (ObserverInterface $o) {
|
||||
$o->observe(1);
|
||||
});
|
||||
for ($i=0; $i < $params['count']; $i++) {
|
||||
$this->reader->collect();
|
||||
}
|
||||
}
|
||||
|
||||
public function provideMeasurementCounts(): \Generator
|
||||
{
|
||||
yield 'disabled+10' => ['enabled' => false, 'count' => 10];
|
||||
yield 'disabled+100' => ['enabled' => false, 'count' => 100];
|
||||
yield 'disabled+1000' => ['enabled' => false, 'count' => 1000];
|
||||
yield 'enabled+10' => ['enabled' => true, 'count' => 10];
|
||||
yield 'enabled+100' => ['enabled' => true, 'count' => 100];
|
||||
yield 'enabled+1000' => ['enabled' => true, 'count' => 1000];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Integration\SDK\Logs;
|
||||
|
||||
use ArrayObject;
|
||||
use OpenTelemetry\API\Logs\LogRecord;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Logs\Exporter\InMemoryExporter;
|
||||
use OpenTelemetry\SDK\Logs\LoggerConfig;
|
||||
use OpenTelemetry\SDK\Logs\LoggerProvider;
|
||||
use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor;
|
||||
use PHPUnit\Framework\Attributes\CoversNothing;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversNothing]
|
||||
class LoggerConfigTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* If a Logger is disabled, it MUST behave equivalently to No-op Logger
|
||||
*/
|
||||
#[Group('logs-compliance')]
|
||||
public function test_disable_scope_then_enable(): void
|
||||
{
|
||||
$storage = new ArrayObject([]);
|
||||
$exporter = new InMemoryExporter($storage);
|
||||
$loggerProvider = LoggerProvider::builder()
|
||||
->addLogRecordProcessor(new SimpleLogRecordProcessor($exporter))
|
||||
->setConfigurator(
|
||||
Configurator::logger()
|
||||
->with(static fn (LoggerConfig $config) => $config->setDisabled(true), name: 'two')
|
||||
)
|
||||
->build();
|
||||
$this->assertInstanceOf(LoggerProvider::class, $loggerProvider);
|
||||
|
||||
$logger_one = $loggerProvider->getLogger('one');
|
||||
$logger_two = $loggerProvider->getLogger('two');
|
||||
$logger_three = $loggerProvider->getLogger('three');
|
||||
|
||||
$this->assertTrue($logger_one->isEnabled());
|
||||
$this->assertFalse($logger_two->isEnabled());
|
||||
$this->assertTrue($logger_three->isEnabled());
|
||||
|
||||
$this->assertCount(0, $storage);
|
||||
$logger_one->emit(new LogRecord());
|
||||
$this->assertCount(1, $storage);
|
||||
$logger_two->emit(new LogRecord());
|
||||
$this->assertCount(1, $storage, 'no record emitted');
|
||||
|
||||
$loggerProvider->updateConfigurator(Configurator::logger()); //re-enable all
|
||||
$this->assertTrue($logger_one->isEnabled());
|
||||
$this->assertTrue($logger_two->isEnabled());
|
||||
$this->assertTrue($logger_three->isEnabled());
|
||||
|
||||
$logger_one->emit(new LogRecord());
|
||||
$this->assertCount(2, $storage);
|
||||
$logger_two->emit(new LogRecord());
|
||||
$this->assertCount(3, $storage, 'logger enabled, record emitted');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Integration\SDK\Metrics;
|
||||
|
||||
use OpenTelemetry\API\Common\Time\TestClock;
|
||||
use OpenTelemetry\API\Metrics\ObserverInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Metrics\Data\Temporality;
|
||||
use OpenTelemetry\SDK\Metrics\MeterConfig;
|
||||
use OpenTelemetry\SDK\Metrics\MeterProvider;
|
||||
use OpenTelemetry\SDK\Metrics\MetricExporter\InMemoryExporter;
|
||||
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
|
||||
use PHPUnit\Framework\Attributes\CoversNothing;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversNothing]
|
||||
class MeterConfigTest extends TestCase
|
||||
{
|
||||
const T0 = 0;
|
||||
const T1 = 1;
|
||||
const T2 = 2;
|
||||
|
||||
public function test_disable_scopes(): void
|
||||
{
|
||||
$meterProvider = MeterProvider::builder()
|
||||
->addReader(new ExportingReader(new InMemoryExporter()))
|
||||
->setConfigurator(
|
||||
Configurator::meter()
|
||||
->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'two')
|
||||
)
|
||||
->build();
|
||||
|
||||
$this->assertInstanceOf(MeterProvider::class, $meterProvider);
|
||||
|
||||
$meter_one = $meterProvider->getMeter('one');
|
||||
$meter_two = $meterProvider->getMeter('two');
|
||||
$meter_three = $meterProvider->getMeter('three');
|
||||
|
||||
$instruments = [];
|
||||
$instruments[] = $meter_two->createCounter('a');
|
||||
$instruments[] = $meter_two->createObservableCounter('b');
|
||||
$instruments[] = $meter_two->createUpDownCounter('c');
|
||||
$instruments[] = $meter_two->createObservableUpDownCounter('d');
|
||||
$instruments[] = $meter_two->createHistogram('e');
|
||||
$instruments[] = $meter_two->createGauge('f');
|
||||
$instruments[] = $meter_two->createObservableGauge('g');
|
||||
|
||||
foreach ($instruments as $id => $instrument) {
|
||||
$this->assertFalse($instrument->isEnabled(), sprintf('instrument %s is disabled', $id));
|
||||
}
|
||||
|
||||
$this->assertTrue($meter_one->isEnabled());
|
||||
$this->assertFalse($meter_two->isEnabled());
|
||||
$this->assertTrue($meter_three->isEnabled());
|
||||
|
||||
$meterProvider->updateConfigurator(Configurator::meter());
|
||||
|
||||
$this->assertTrue($meter_two->isEnabled());
|
||||
|
||||
foreach ($instruments as $instrument) {
|
||||
$this->assertTrue($instrument->isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a Meter is disabled, it MUST behave equivalently to No-op Meter
|
||||
*/
|
||||
#[Group('metrics-compliance')]
|
||||
public function test_metrics_not_exported_when_disabled(): void
|
||||
{
|
||||
$exporter = new InMemoryExporter();
|
||||
$reader = new ExportingReader($exporter);
|
||||
$meterProvider = MeterProvider::builder()
|
||||
->addReader($reader)
|
||||
->setConfigurator(
|
||||
Configurator::meter()
|
||||
->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: '*')
|
||||
)
|
||||
->build();
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$this->assertFalse($meter->isEnabled());
|
||||
$counter = $meter->createCounter('a');
|
||||
$async_counter = $meter->createObservableCounter('b', callbacks: function (ObserverInterface $o) {
|
||||
$this->fail('observer from disabled meter should not have been called');
|
||||
});
|
||||
$this->assertFalse($counter->isEnabled());
|
||||
$this->assertFalse($async_counter->isEnabled());
|
||||
$counter->add(1);
|
||||
$reader->collect();
|
||||
$metrics = $exporter->collect(true);
|
||||
$this->assertSame([], $metrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a meter is disabled, its streams should be dropped. Any previously collected
|
||||
* data will be lost. If a disabled meter is re-enabled, the streams should be
|
||||
* recreated.
|
||||
*/
|
||||
public function test_streams_recreated_on_enable(): void
|
||||
{
|
||||
$this->markTestSkipped('TODO implement drop/create streams'); // @phpstan-ignore-next-line
|
||||
$clock = new TestClock(self::T0);
|
||||
$disabledConfigurator = Configurator::meter()
|
||||
->with(static fn (MeterConfig $config) => $config->setDisabled(false), name: '*');
|
||||
$exporter = new InMemoryExporter(Temporality::CUMULATIVE);
|
||||
$reader = new ExportingReader($exporter);
|
||||
$meterProvider = MeterProvider::builder()
|
||||
->addReader($reader)
|
||||
->setClock($clock)
|
||||
->build();
|
||||
|
||||
$c = $meterProvider->getMeter('test')->createCounter('c');
|
||||
|
||||
//t0, meter is enabled
|
||||
$c->add(1);
|
||||
|
||||
//t1, disable meter
|
||||
$clock->setTime(self::T1);
|
||||
$meterProvider->updateConfigurator($disabledConfigurator);
|
||||
$c->add(10);
|
||||
|
||||
//t2, {sum=100, startTimestamp=t2}; must not export {sum=101, startTimestamp=t0}
|
||||
$clock->setTime(self::T2);
|
||||
$meterProvider->updateConfigurator(Configurator::meter());
|
||||
$c->add(100);
|
||||
|
||||
$reader->collect();
|
||||
$metrics = $exporter->collect();
|
||||
$this->assertCount(1, $metrics);
|
||||
$metric = $metrics[0];
|
||||
|
||||
$this->assertCount(1, $metric->data->dataPoints);
|
||||
$dataPoint = $metric->data->dataPoints[0];
|
||||
|
||||
$this->assertSame(self::T2, $dataPoint->startTimestamp);
|
||||
$this->assertSame(100, $dataPoint->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Integration\SDK\Trace;
|
||||
|
||||
use ArrayObject;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
|
||||
use OpenTelemetry\SDK\Trace\Tracer;
|
||||
use OpenTelemetry\SDK\Trace\TracerConfig;
|
||||
use OpenTelemetry\SDK\Trace\TracerProvider;
|
||||
use PHPUnit\Framework\Attributes\CoversNothing;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversNothing]
|
||||
class TracerConfigTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* If a Tracer is disabled, it MUST behave equivalently to No-op Tracer
|
||||
*/
|
||||
#[Group('trace-compliance')]
|
||||
public function test_disable_scopes(): void
|
||||
{
|
||||
$storage = new ArrayObject();
|
||||
$exporter = new InMemoryExporter($storage);
|
||||
$tracerProvider = TracerProvider::builder()
|
||||
->addSpanProcessor(new SimpleSpanProcessor($exporter))
|
||||
->setConfigurator(
|
||||
Configurator::tracer()
|
||||
->with(static fn (TracerConfig $config) => $config->setDisabled(false), name: '*')
|
||||
->with(static fn (TracerConfig $config) => $config->setDisabled(true), name: 'B')
|
||||
)
|
||||
->build();
|
||||
$tracerA = $tracerProvider->getTracer('A');
|
||||
$tracerB = $tracerProvider->getTracer('B');
|
||||
$tracerC = $tracerProvider->getTracer('C');
|
||||
|
||||
$parent = $tracerA->spanBuilder('parent')->startSpan();
|
||||
$this->assertTrue($parent->isRecording());
|
||||
$parent->setAttribute('a', 1);
|
||||
$parentScope = $parent->activate();
|
||||
|
||||
try {
|
||||
$child = $tracerB->spanBuilder('child')->startSpan();
|
||||
$child->setAttribute('b', 1);
|
||||
$childScope = $child->activate();
|
||||
|
||||
try {
|
||||
$this->assertFalse($child->isRecording());
|
||||
$grandChild = $tracerC->spanBuilder('grandchild')->startSpan();
|
||||
$this->assertTrue($grandChild->isRecording());
|
||||
$grandChild->setAttribute('c', 1);
|
||||
$grandChild->end();
|
||||
} finally {
|
||||
$childScope->detach();
|
||||
$child->end();
|
||||
}
|
||||
} finally {
|
||||
$parentScope->detach();
|
||||
$parent->end();
|
||||
}
|
||||
// Only tracerA:parent and tracerC:child should be recorded
|
||||
// tracerC:grandchild should list tracerA:parent as its parent
|
||||
$this->assertCount(2, $storage, 'only 2 of the 3 spans were recorded');
|
||||
|
||||
// @var ImmutableSpan $gc
|
||||
$gc = $storage->offsetGet(0);
|
||||
$this->assertSame('grandchild', $gc->getName());
|
||||
|
||||
// @var ImmutableSpan $p
|
||||
$p = $storage->offsetGet(1);
|
||||
$this->assertSame('parent', $p->getName());
|
||||
|
||||
$this->assertSame($p->getTraceId(), $gc->getTraceId(), 'parent and grandchild are in the same trace');
|
||||
$this->assertSame($gc->getParentContext()->getSpanId(), $p->getContext()->getSpanId(), 'parent is the parent of grandchild');
|
||||
}
|
||||
|
||||
public function test_disable_scope_then_enable(): void
|
||||
{
|
||||
$storage = new ArrayObject();
|
||||
$exporter = new InMemoryExporter($storage);
|
||||
$tracerProvider = TracerProvider::builder()
|
||||
->addSpanProcessor(new SimpleSpanProcessor($exporter))
|
||||
->setConfigurator(
|
||||
Configurator::tracer()
|
||||
->with(static fn (TracerConfig $config) => $config->setDisabled(true), name: 'B')
|
||||
)
|
||||
->build();
|
||||
$tracerA = $tracerProvider->getTracer('A');
|
||||
$tracerB = $tracerProvider->getTracer('B');
|
||||
$tracerC = $tracerProvider->getTracer('C');
|
||||
|
||||
$parent = $tracerA->spanBuilder('parent')->startSpan();
|
||||
$this->assertTrue($parent->isRecording());
|
||||
$parent->setAttribute('a', 1);
|
||||
$parentScope = $parent->activate();
|
||||
|
||||
try {
|
||||
$child = $tracerB->spanBuilder('child')->startSpan();
|
||||
$child->setAttribute('b', 1);
|
||||
$childScope = $child->activate();
|
||||
$tracerProvider->updateConfigurator(Configurator::tracer()); //re-enable tracer two
|
||||
$sibling = $tracerB->spanBuilder('sibling')->startSpan();
|
||||
$siblingScope = $sibling->activate();
|
||||
|
||||
try {
|
||||
$this->assertFalse($child->isRecording());
|
||||
$grandChild = $tracerC->spanBuilder('grandchild')->startSpan();
|
||||
$this->assertTrue($grandChild->isRecording());
|
||||
$grandChild->setAttribute('c', 1);
|
||||
$grandChild->end();
|
||||
} finally {
|
||||
$siblingScope->detach();
|
||||
$sibling->end();
|
||||
$childScope->detach();
|
||||
$child->end();
|
||||
}
|
||||
} finally {
|
||||
$parentScope->detach();
|
||||
$parent->end();
|
||||
}
|
||||
// tracerA:parent, tracerB:sibling and tracerC:grandchild should be recorded
|
||||
// tracerC:grandchild should list tracerB:sibling as its parent
|
||||
$this->assertCount(3, $storage, 'only 3 of the 4 spans were recorded');
|
||||
|
||||
// @var ImmutableSpan $gc
|
||||
$gc = $storage->offsetGet(0);
|
||||
$this->assertSame('grandchild', $gc->getName());
|
||||
|
||||
// @var ImmutableSpan $s
|
||||
$s = $storage->offsetGet(1);
|
||||
$this->assertSame('sibling', $s->getName());
|
||||
|
||||
// @var ImmutableSpan $p
|
||||
$p = $storage->offsetGet(2);
|
||||
$this->assertSame('parent', $p->getName());
|
||||
|
||||
$this->assertSame($p->getTraceId(), $gc->getTraceId(), 'parent and grandchild are in the same trace');
|
||||
$this->assertSame($p->getTraceId(), $s->getTraceId(), 'parent and sibling are in the same trace');
|
||||
$this->assertSame($gc->getParentContext()->getSpanId(), $s->getContext()->getSpanId(), 'sibling is the parent of grandchild');
|
||||
$this->assertSame($s->getParentContext()->getSpanId(), $p->getContext()->getSpanId(), 'parent is the parent of sibling');
|
||||
}
|
||||
|
||||
public function test_reenable_enables_tracer(): void
|
||||
{
|
||||
$tracerProvider = TracerProvider::builder()
|
||||
->setConfigurator(
|
||||
Configurator::tracer()
|
||||
->with(static fn (TracerConfig $config) => $config->setDisabled(true), name: 'two')
|
||||
)
|
||||
->build();
|
||||
$tracer = $tracerProvider->getTracer(name: 'two');
|
||||
$this->assertInstanceOf(Tracer::class, $tracer);
|
||||
$this->assertFalse($tracer->isEnabled());
|
||||
|
||||
$tracerProvider->updateConfigurator(Configurator::tracer()); //reset
|
||||
|
||||
$this->assertTrue($tracer->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,6 @@ class NoopLoggerTest extends TestCase
|
|||
|
||||
public function test_enabled(): void
|
||||
{
|
||||
$this->assertFalse(NoopLogger::getInstance()->enabled());
|
||||
$this->assertFalse(NoopLogger::getInstance()->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,6 @@ class NoopTracerTest extends TestCase
|
|||
|
||||
public function test_enabled(): void
|
||||
{
|
||||
$this->assertFalse(NoopTracer::getInstance()->enabled());
|
||||
$this->assertFalse(NoopTracer::getInstance()->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Common\InstrumentationScope;
|
||||
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\ConfigTrait;
|
||||
use OpenTelemetry\SDK\Trace\TracerConfig;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(ConfigTrait::class)]
|
||||
class ConfigTest extends TestCase
|
||||
{
|
||||
private Config $config;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->config = new class() implements Config {
|
||||
use ConfigTrait;
|
||||
};
|
||||
}
|
||||
|
||||
#[DataProvider('enabledProvider')]
|
||||
public function test_is_enabled(bool $disabled, bool $expected): void
|
||||
{
|
||||
$this->config->setDisabled($disabled);
|
||||
$this->assertSame($expected, $this->config->isEnabled());
|
||||
}
|
||||
|
||||
public static function enabledProvider(): array
|
||||
{
|
||||
return [
|
||||
[false, true],
|
||||
[true, false],
|
||||
];
|
||||
}
|
||||
|
||||
public function test_default_is_enabled(): void
|
||||
{
|
||||
$config = TracerConfig::default();
|
||||
$this->assertTrue($config->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\SDK\Common\InstrumentationScope;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Attribute\AttributesInterface;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(Configurator::class)]
|
||||
class ConfiguratorTest extends TestCase
|
||||
{
|
||||
private Configurator $configurator;
|
||||
private InstrumentationScope $scope;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$config = new class() implements Config {
|
||||
private bool $disabled = false;
|
||||
public function setDisabled(bool $disabled): void
|
||||
{
|
||||
$this->disabled = $disabled;
|
||||
}
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->disabled === false;
|
||||
}
|
||||
};
|
||||
$this->scope = new InstrumentationScope('test', '1.0', 'https://example.org/schema', $this->createMock(AttributesInterface::class));
|
||||
$this->configurator = (new Configurator(static fn () => $config));
|
||||
}
|
||||
|
||||
public function test_match_name(): void
|
||||
{
|
||||
$configurator = $this->configurator->with(static fn (Config $config) => $config->setDisabled(true), name: 'test');
|
||||
$this->assertFalse($configurator->resolve($this->scope)->isEnabled());
|
||||
}
|
||||
|
||||
public function test_returns_default_on_no_match(): void
|
||||
{
|
||||
$config = $this->configurator->resolve($this->scope);
|
||||
|
||||
$this->assertTrue($config->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,14 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\Tests\Unit\SDK\Logs;
|
||||
|
||||
use OpenTelemetry\API\Logs\NoopLogger;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Config;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Logs\Logger;
|
||||
use OpenTelemetry\SDK\Logs\LoggerConfig;
|
||||
use OpenTelemetry\SDK\Logs\LoggerProvider;
|
||||
use OpenTelemetry\SDK\Logs\LoggerProviderBuilder;
|
||||
use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
|
|
@ -23,19 +28,25 @@ class LoggerProviderTest extends TestCase
|
|||
{
|
||||
/** @var LogRecordProcessorInterface&MockObject $processor */
|
||||
private LogRecordProcessorInterface $processor;
|
||||
private InstrumentationScopeFactoryInterface $instrumentationScopeFactory;
|
||||
private LoggerProvider $provider;
|
||||
/** @var Config&MockObject */
|
||||
private Config $config;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->processor = $this->createMock(LogRecordProcessorInterface::class);
|
||||
$this->instrumentationScopeFactory = $this->createMock(InstrumentationScopeFactoryInterface::class);
|
||||
$instrumentationScopeFactory = $this->createMock(InstrumentationScopeFactoryInterface::class);
|
||||
$instrumentationScopeFactory->method('create')->willReturn($this->createMock(InstrumentationScope::class));
|
||||
$resource = $this->createMock(ResourceInfo::class);
|
||||
$this->provider = new LoggerProvider($this->processor, $this->instrumentationScopeFactory, $resource);
|
||||
$this->config = $this->createMock(LoggerConfig::class);
|
||||
$configurator = $this->createMock(Configurator::class);
|
||||
$configurator->method('resolve')->willReturn($this->config);
|
||||
$this->provider = new LoggerProvider($this->processor, $instrumentationScopeFactory, $resource, $configurator);
|
||||
}
|
||||
|
||||
public function test_get_logger(): void
|
||||
{
|
||||
$this->config->method('isEnabled')->willReturn(true);
|
||||
$logger = $this->provider->getLogger('name');
|
||||
$this->assertInstanceOf(Logger::class, $logger);
|
||||
}
|
||||
|
|
@ -47,6 +58,13 @@ class LoggerProviderTest extends TestCase
|
|||
$this->assertInstanceOf(NoopLogger::class, $logger);
|
||||
}
|
||||
|
||||
public function test_get_logger_if_disabled(): void
|
||||
{
|
||||
$this->config->method('isEnabled')->willReturn(false);
|
||||
$logger = $this->provider->getLogger('name');
|
||||
$this->assertFalse($logger->isEnabled());
|
||||
}
|
||||
|
||||
public function test_shutdown_calls_processor_shutdown(): void
|
||||
{
|
||||
$this->processor->expects($this->once())->method('shutdown');
|
||||
|
|
@ -58,4 +76,24 @@ class LoggerProviderTest extends TestCase
|
|||
$this->processor->expects($this->once())->method('forceFlush');
|
||||
$this->provider->forceFlush();
|
||||
}
|
||||
|
||||
public function test_builder(): void
|
||||
{
|
||||
$this->assertInstanceOf(LoggerProviderBuilder::class, $this->provider->builder());
|
||||
}
|
||||
|
||||
public function test_update_configurator_updates_loggers(): void
|
||||
{
|
||||
$lp = LoggerProvider::builder()->build();
|
||||
$this->assertInstanceOf(LoggerProvider::class, $lp);
|
||||
$one = $lp->getLogger('one');
|
||||
$two = $lp->getLogger('two');
|
||||
|
||||
$this->assertTrue($one->isEnabled());
|
||||
$this->assertTrue($two->isEnabled());
|
||||
|
||||
$lp->updateConfigurator(Configurator::logger()->with(static fn (LoggerConfig $config) => $config->setDisabled(true), name: '*'));
|
||||
$this->assertFalse($one->isEnabled());
|
||||
$this->assertFalse($two->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ use OpenTelemetry\API\Logs\LogRecord;
|
|||
use OpenTelemetry\Context\ContextInterface;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Logs\Logger;
|
||||
use OpenTelemetry\SDK\Logs\LoggerConfig;
|
||||
use OpenTelemetry\SDK\Logs\LoggerSharedState;
|
||||
use OpenTelemetry\SDK\Logs\LogRecordLimitsBuilder;
|
||||
use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface;
|
||||
|
|
@ -113,6 +115,21 @@ class LoggerTest extends TestCase
|
|||
public function test_enabled(): void
|
||||
{
|
||||
$logger = new Logger($this->sharedState, $this->scope);
|
||||
$this->assertTrue($logger->enabled());
|
||||
$this->assertTrue($logger->isEnabled());
|
||||
|
||||
$this->processor->expects($this->once())->method('onEmit');
|
||||
|
||||
$logger->emit(new LogRecord());
|
||||
}
|
||||
|
||||
public function test_does_not_log_if_disabled(): void
|
||||
{
|
||||
$configurator = Configurator::logger()->with(static fn (LoggerConfig $config) => $config->setDisabled(true), name: 'foo');
|
||||
$logger = new Logger($this->sharedState, $this->scope, $configurator);
|
||||
$this->assertFalse($logger->isEnabled());
|
||||
|
||||
$this->processor->expects($this->never())->method('onEmit');
|
||||
|
||||
$logger->emit(new LogRecord());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\Tests\Unit\SDK\Metrics;
|
||||
|
||||
use OpenTelemetry\API\Common\Time\TestClock;
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
use OpenTelemetry\API\Metrics\ObserverInterface;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Metrics\Aggregation\ExplicitBucketHistogramAggregation;
|
||||
|
|
@ -40,17 +41,24 @@ use WeakMap;
|
|||
#[CoversClass(ObservableInstrumentTrait::class)]
|
||||
final class InstrumentTest extends TestCase
|
||||
{
|
||||
private MeterInterface $meter;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->meter = $this->createMock(MeterInterface::class);
|
||||
$this->meter->method('isEnabled')->willReturn(true);
|
||||
}
|
||||
|
||||
public function test_counter(): void
|
||||
{
|
||||
$a = new MetricAggregator(null, new SumAggregation(true));
|
||||
$s = new SynchronousMetricStream(new SumAggregation(true), 0);
|
||||
$w = new MetricRegistry(null, Attributes::factory(), new TestClock(1));
|
||||
$i = new Instrument(InstrumentType::COUNTER, 'test', null, null);
|
||||
$i = new Instrument(InstrumentType::COUNTER, 'test', null, null, meter: $this->meter);
|
||||
$n = $w->registerSynchronousStream($i, $s, $a);
|
||||
$r = $s->register(Temporality::DELTA);
|
||||
|
||||
$c = new Counter($w, $i, new NoopStalenessHandler());
|
||||
$c = new Counter($w, $i, new NoopStalenessHandler(), $this->meter);
|
||||
$c->add(5);
|
||||
$c->add(7);
|
||||
$c->add(3);
|
||||
|
|
@ -75,11 +83,11 @@ final class InstrumentTest extends TestCase
|
|||
$a = new MetricAggregatorFactory(null, new SumAggregation(true));
|
||||
$s = new SynchronousMetricStream(new SumAggregation(true), 0);
|
||||
$w = new MetricRegistry(null, Attributes::factory(), new TestClock(1));
|
||||
$i = new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'test', null, null);
|
||||
$i = new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'test', null, null, meter: $this->meter);
|
||||
$n = $w->registerAsynchronousStream($i, $s, $a);
|
||||
$r = $s->register(Temporality::CUMULATIVE);
|
||||
|
||||
$c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap());
|
||||
$c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->meter);
|
||||
$c->observe(static function (ObserverInterface $observer): void {
|
||||
$observer->observe(5);
|
||||
});
|
||||
|
|
@ -104,7 +112,7 @@ final class InstrumentTest extends TestCase
|
|||
$a = new MetricAggregatorFactory(null, new SumAggregation(true));
|
||||
$s = new SynchronousMetricStream(new SumAggregation(true), 0);
|
||||
$w = new MetricRegistry(null, Attributes::factory(), new TestClock(1));
|
||||
$i = new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'test', null, null);
|
||||
$i = new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'test', null, null, meter: $this->meter);
|
||||
$n = $w->registerAsynchronousStream($i, $s, $a);
|
||||
$r = $s->register(Temporality::CUMULATIVE);
|
||||
|
||||
|
|
@ -115,7 +123,7 @@ final class InstrumentTest extends TestCase
|
|||
}
|
||||
};
|
||||
|
||||
$c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap());
|
||||
$c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->meter);
|
||||
$c->observe($instance);
|
||||
$instance = null;
|
||||
|
||||
|
|
@ -132,11 +140,11 @@ final class InstrumentTest extends TestCase
|
|||
$a = new MetricAggregator(null, new SumAggregation(false));
|
||||
$s = new SynchronousMetricStream(new SumAggregation(false), 0);
|
||||
$w = new MetricRegistry(null, Attributes::factory(), new TestClock(1));
|
||||
$i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null);
|
||||
$i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null, meter: $this->meter);
|
||||
$n = $w->registerSynchronousStream($i, $s, $a);
|
||||
$r = $s->register(Temporality::DELTA);
|
||||
|
||||
$c = new UpDownCounter($w, $i, new NoopStalenessHandler());
|
||||
$c = new UpDownCounter($w, $i, new NoopStalenessHandler(), $this->meter);
|
||||
$c->add(5);
|
||||
$c->add(7);
|
||||
$c->add(-8);
|
||||
|
|
@ -161,11 +169,11 @@ final class InstrumentTest extends TestCase
|
|||
$a = new MetricAggregator(null, new ExplicitBucketHistogramAggregation([3, 6, 9]));
|
||||
$s = new SynchronousMetricStream(new ExplicitBucketHistogramAggregation([3, 6, 9]), 0);
|
||||
$w = new MetricRegistry(null, Attributes::factory(), new TestClock(1));
|
||||
$i = new Instrument(InstrumentType::HISTOGRAM, 'test', null, null);
|
||||
$i = new Instrument(InstrumentType::HISTOGRAM, 'test', null, null, meter: $this->meter);
|
||||
$n = $w->registerSynchronousStream($i, $s, $a);
|
||||
$r = $s->register(Temporality::DELTA);
|
||||
|
||||
$h = new Histogram($w, $i, new NoopStalenessHandler());
|
||||
$h = new Histogram($w, $i, new NoopStalenessHandler(), $this->meter);
|
||||
$h->record(1);
|
||||
$h->record(7);
|
||||
$h->record(9);
|
||||
|
|
@ -242,24 +250,27 @@ final class InstrumentTest extends TestCase
|
|||
new ObservableCallback($writer, $referenceCounter, 1, $callbackDestructor, new stdClass());
|
||||
}
|
||||
|
||||
public function test_synchronous_enabled(): void
|
||||
public function test_synchronous_disabled_if_meter_disabled(): void
|
||||
{
|
||||
$w = $this->createMock(MetricWriterInterface::class);
|
||||
$c = $this->createMock(ReferenceCounterInterface::class);
|
||||
$i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null);
|
||||
$counter = new Counter($w, $i, $c);
|
||||
$i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null, meter: $this->meter);
|
||||
$meter = $this->createMock(MeterInterface::class);
|
||||
$meter->expects($this->once())->method('isEnabled')->willReturn(false);
|
||||
$counter = new Counter($w, $i, $c, $meter);
|
||||
|
||||
$this->assertTrue($counter->enabled());
|
||||
$this->assertFalse($counter->isEnabled());
|
||||
}
|
||||
|
||||
public function test_asynchronous_enabled(): void
|
||||
public function test_asynchronous_disabled_if_meter_disabled(): void
|
||||
{
|
||||
$w = $this->createMock(MetricWriterInterface::class);
|
||||
$w->method('enabled')->willReturn(true);
|
||||
$c = $this->createMock(ReferenceCounterInterface::class);
|
||||
$i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null);
|
||||
$counter = new ObservableCounter($w, $i, $c, new WeakMap());
|
||||
$i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null, meter: $this->meter);
|
||||
$meter = $this->createMock(MeterInterface::class);
|
||||
$meter->expects($this->once())->method('isEnabled')->willReturn(false);
|
||||
$counter = new ObservableCounter($w, $i, $c, new WeakMap(), $meter);
|
||||
|
||||
$this->assertTrue($counter->enabled());
|
||||
$this->assertFalse($counter->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,12 @@ use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
|||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MeterConfig;
|
||||
use OpenTelemetry\SDK\Metrics\MeterProvider;
|
||||
use OpenTelemetry\SDK\Metrics\MetricExporter\InMemoryExporter;
|
||||
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
|
||||
use OpenTelemetry\SDK\Metrics\MetricReaderInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MetricSourceRegistryInterface;
|
||||
use OpenTelemetry\SDK\Metrics\StalenessHandler\ImmediateStalenessHandlerFactory;
|
||||
|
|
@ -104,6 +108,19 @@ final class MeterProviderTest extends TestCase
|
|||
);
|
||||
$this->assertTrue($meterProvider->forceFlush());
|
||||
}
|
||||
|
||||
public function test_disable(): void
|
||||
{
|
||||
$meterProvider = MeterProvider::builder()->addReader(new ExportingReader(new InMemoryExporter()))->build();
|
||||
$this->assertInstanceOf(MeterProvider::class, $meterProvider);
|
||||
$meter = $meterProvider->getMeter('one');
|
||||
$this->assertTrue($meter->isEnabled());
|
||||
$counter = $meter->createCounter('A');
|
||||
$this->assertTrue($counter->isEnabled());
|
||||
$meterProvider->updateConfigurator(Configurator::meter()->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'one'));
|
||||
$this->assertFalse($meter->isEnabled());
|
||||
$this->assertFalse($counter->isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
interface MetricReaderSourceRegistryInterface extends MetricReaderInterface, MetricSourceRegistryInterface, DefaultAggregationProviderInterface
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ use OpenTelemetry\API\Common\Time\Clock;
|
|||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Metrics\AggregationInterface;
|
||||
use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface;
|
||||
use OpenTelemetry\SDK\Metrics\Instrument;
|
||||
use OpenTelemetry\SDK\Metrics\InstrumentType;
|
||||
use OpenTelemetry\SDK\Metrics\Meter;
|
||||
use OpenTelemetry\SDK\Metrics\MeterConfig;
|
||||
use OpenTelemetry\SDK\Metrics\MeterProvider;
|
||||
use OpenTelemetry\SDK\Metrics\MetricFactoryInterface;
|
||||
use OpenTelemetry\SDK\Metrics\MetricReaderInterface;
|
||||
|
|
@ -32,46 +34,48 @@ final class MeterTest extends TestCase
|
|||
public function test_create_counter(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
public function test_create_histogram(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::HISTOGRAM, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::HISTOGRAM, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createHistogram('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
public function test_create_histogram_advisory(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
|
|
@ -83,6 +87,7 @@ final class MeterTest extends TestCase
|
|||
's',
|
||||
'Measures the duration of inbound HTTP requests.',
|
||||
['ExplicitBucketBoundaries' => [0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10]],
|
||||
$meter,
|
||||
),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
|
|
@ -90,8 +95,6 @@ final class MeterTest extends TestCase
|
|||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createHistogram(
|
||||
'http.server.duration',
|
||||
's',
|
||||
|
|
@ -103,97 +106,97 @@ final class MeterTest extends TestCase
|
|||
public function test_create_gauge(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::GAUGE, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::GAUGE, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createGauge('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
public function test_create_up_down_counter(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::UP_DOWN_COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::UP_DOWN_COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createUpDownCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
public function test_create_observable_counter(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createAsynchronousObserver')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createObservableCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
public function test_create_observable_gauge(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createAsynchronousObserver')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_GAUGE, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_GAUGE, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createObservableGauge('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
public function test_create_observable_up_down_counter(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createAsynchronousObserver')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_UP_DOWN_COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_UP_DOWN_COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createObservableUpDownCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
||||
|
|
@ -201,20 +204,20 @@ final class MeterTest extends TestCase
|
|||
public function test_reuses_writer_when_not_stale(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$counter = $meter->createCounter('name', 'unit', 'description');
|
||||
$counter = $meter->createCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
|
@ -222,20 +225,20 @@ final class MeterTest extends TestCase
|
|||
public function test_releases_writer_on_stale(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->exactly(2))->method('createSynchronousWriter')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createCounter('name', 'unit', 'description');
|
||||
$meter->createCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
|
@ -244,19 +247,19 @@ final class MeterTest extends TestCase
|
|||
public function test_reuses_observer_when_not_stale(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->once())->method('createAsynchronousObserver')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$observer = $meter->createObservableCounter('name', 'unit', 'description');
|
||||
$observer = $meter->createObservableCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
|
@ -264,19 +267,19 @@ final class MeterTest extends TestCase
|
|||
public function test_releases_observer_on_stale(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$metricFactory->expects($this->exactly(2))->method('createAsynchronousObserver')
|
||||
->with(
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
new InstrumentationScope('test', null, null, Attributes::create([])),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'name', 'unit', 'description'),
|
||||
new Instrument(InstrumentType::ASYNCHRONOUS_COUNTER, 'name', 'unit', 'description', meter: $meter),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$meter->createObservableCounter('name', 'unit', 'description');
|
||||
$meter->createObservableCounter('name', 'unit', 'description');
|
||||
}
|
||||
|
|
@ -373,6 +376,18 @@ final class MeterTest extends TestCase
|
|||
$meter->createCounter('name');
|
||||
}
|
||||
|
||||
public function test_update_configurator(): void
|
||||
{
|
||||
$metricFactory = $this->createMock(MetricFactoryInterface::class);
|
||||
$metricFactory->method('createSynchronousWriter')->willReturn([]);
|
||||
|
||||
$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
|
||||
$meter = $meterProvider->getMeter('test');
|
||||
$this->assertTrue($meter->isEnabled());
|
||||
$meterProvider->updateConfigurator(Configurator::meter()->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'test'));
|
||||
$this->assertFalse($meter->isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iterable<MetricReaderInterface&MetricSourceRegistryInterface&DefaultAggregationProviderInterface> $metricReaders
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ final class ExportingReaderTest extends TestCase
|
|||
|
||||
$source = $this->createMock(MetricSourceInterface::class);
|
||||
$source->expects($this->once())->method('collect')->willReturn($metric);
|
||||
$source->method('isEnabled')->willReturn(true);
|
||||
$provider = $this->createMock(MetricSourceProviderInterface::class);
|
||||
$provider->expects($this->once())->method('create')->willReturn($source);
|
||||
$metricMetadata = $this->createMock(MetricMetadataInterface::class);
|
||||
|
|
@ -183,6 +184,7 @@ final class ExportingReaderTest extends TestCase
|
|||
$provider = $this->createMock(MetricSourceProviderInterface::class);
|
||||
$source = $this->createMock(MetricSourceInterface::class);
|
||||
$source->method('collect')->willReturn($this->createMock(Metric::class));
|
||||
$source->method('isEnabled')->willReturn(true);
|
||||
$provider->method('create')->willReturn($source);
|
||||
$exporter->method('temporality')->willReturn('foo');
|
||||
$exporter->expects($this->once())->method('export')->willReturn(true);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\Tests\Unit\SDK\Metrics\View;
|
||||
|
||||
use OpenTelemetry\API\Metrics\MeterInterface;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope;
|
||||
use OpenTelemetry\SDK\Metrics\Instrument;
|
||||
|
|
@ -30,14 +31,22 @@ final class SelectionCriteriaTest extends TestCase
|
|||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private MeterInterface $meter;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->meter = $this->createMock(MeterInterface::class);
|
||||
$this->meter->method('isEnabled')->willReturn(true);
|
||||
}
|
||||
|
||||
public function test_instrument_scope_name_criteria(): void
|
||||
{
|
||||
$this->assertTrue((new InstrumentationScopeNameCriteria('scopeName'))->accepts(
|
||||
new Instrument(InstrumentType::COUNTER, 'name', null, null),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', null, null, meter: $this->meter),
|
||||
new InstrumentationScope('scopeName', null, null, Attributes::create([])),
|
||||
));
|
||||
$this->assertFalse((new InstrumentationScopeNameCriteria('scopeName'))->accepts(
|
||||
new Instrument(InstrumentType::COUNTER, 'name', null, null),
|
||||
new Instrument(InstrumentType::COUNTER, 'name', null, null, meter: $this->meter),
|
||||
new InstrumentationScope('scope-name', null, null, Attributes::create([])),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ declare(strict_types=1);
|
|||
namespace OpenTelemetry\Tests\Unit\SDK\Trace;
|
||||
|
||||
use OpenTelemetry\API\Trace\NoopTracer;
|
||||
use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator;
|
||||
use OpenTelemetry\SDK\Trace\SamplerInterface;
|
||||
use OpenTelemetry\SDK\Trace\TracerConfig;
|
||||
use OpenTelemetry\SDK\Trace\TracerProvider;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
|
@ -93,4 +95,19 @@ class TracerProviderTest extends TestCase
|
|||
$provider->getTracer('foo')
|
||||
);
|
||||
}
|
||||
|
||||
public function test_update_configurator_updates_tracers(): void
|
||||
{
|
||||
$tp = TracerProvider::builder()->build();
|
||||
$this->assertInstanceOf(TracerProvider::class, $tp);
|
||||
$one = $tp->getTracer('one');
|
||||
$two = $tp->getTracer('two');
|
||||
|
||||
$this->assertTrue($one->isEnabled());
|
||||
$this->assertTrue($two->isEnabled());
|
||||
|
||||
$tp->updateConfigurator(Configurator::tracer()->with(static fn (TracerConfig $config) => $config->setDisabled(true), name: '*'));
|
||||
$this->assertFalse($one->isEnabled());
|
||||
$this->assertFalse($two->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,6 @@ class TracerTest extends TestCase
|
|||
|
||||
public function test_enabled(): void
|
||||
{
|
||||
$this->assertTrue($this->tracer->enabled());
|
||||
$this->assertTrue($this->tracer->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue