From c12f89df4ba00075df433c76cda35da645679070 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 18 Jul 2024 16:23:02 +1000 Subject: [PATCH 01/36] add enabled function spec 1.34 requires logger, tracer, and instrument to have an enabled function --- src/API/Logs/LoggerInterface.php | 7 +++++ src/API/Logs/NoopLogger.php | 5 ++++ src/API/Metrics/AsynchronousInstrument.php | 2 +- src/API/Metrics/Instrument.php | 14 +++++++++ src/API/Metrics/Noop/NoopCounter.php | 5 ++++ src/API/Metrics/Noop/NoopHistogram.php | 5 ++++ .../Metrics/Noop/NoopObservableCounter.php | 5 ++++ src/API/Metrics/Noop/NoopObservableGauge.php | 5 ++++ .../Noop/NoopObservableUpDownCounter.php | 5 ++++ src/API/Metrics/Noop/NoopUpDownCounter.php | 5 ++++ src/API/Metrics/SynchronousInstrument.php | 2 +- src/API/Trace/NoopTracer.php | 5 ++++ src/API/Trace/TracerInterface.php | 7 +++++ src/SDK/Logs/Logger.php | 5 ++++ .../DefaultAggregationProviderTrait.php | 1 - src/SDK/Metrics/ObservableInstrumentTrait.php | 5 ++++ .../Metrics/SynchronousInstrumentTrait.php | 5 ++++ src/SDK/Trace/Tracer.php | 5 ++++ tests/Unit/API/Logs/NoopLoggerTest.php | 7 ++++- tests/Unit/API/Trace/NoopTracerTest.php | 29 +++++++++++++++++++ tests/Unit/SDK/Logs/LoggerTest.php | 6 ++++ tests/Unit/SDK/Metrics/InstrumentTest.php | 22 ++++++++++++++ tests/Unit/SDK/Trace/TracerTest.php | 5 ++++ 23 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/API/Metrics/Instrument.php create mode 100644 tests/Unit/API/Trace/NoopTracerTest.php diff --git a/src/API/Logs/LoggerInterface.php b/src/API/Logs/LoggerInterface.php index 4e1bc3931..9ab08e440 100644 --- a/src/API/Logs/LoggerInterface.php +++ b/src/API/Logs/LoggerInterface.php @@ -11,4 +11,11 @@ interface LoggerInterface * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.32.0/specification/logs/bridge-api.md#artifact-naming */ public function emit(LogRecord $logRecord): void; + + /** + * Determine if the logger is enabled. Logs bridge API authors SHOULD call this method each time they + * are about to generate a LogRecord, to avoid performing computationally expensive work. + * @experimental + */ + public function enabled(): bool; } diff --git a/src/API/Logs/NoopLogger.php b/src/API/Logs/NoopLogger.php index faacd5e10..9267ca545 100644 --- a/src/API/Logs/NoopLogger.php +++ b/src/API/Logs/NoopLogger.php @@ -30,4 +30,9 @@ public function emit(LogRecord $logRecord): void public function log($level, $message, array $context = []): void { } + + public function enabled(): bool + { + return false; + } } diff --git a/src/API/Metrics/AsynchronousInstrument.php b/src/API/Metrics/AsynchronousInstrument.php index fc552c83f..e25f3d766 100644 --- a/src/API/Metrics/AsynchronousInstrument.php +++ b/src/API/Metrics/AsynchronousInstrument.php @@ -7,6 +7,6 @@ /** * Marker interface for asynchronous instruments. */ -interface AsynchronousInstrument +interface AsynchronousInstrument extends Instrument { } diff --git a/src/API/Metrics/Instrument.php b/src/API/Metrics/Instrument.php new file mode 100644 index 000000000..bd22b920e --- /dev/null +++ b/src/API/Metrics/Instrument.php @@ -0,0 +1,14 @@ + new Aggregation\LastValueAggregation(), default => null, }; - // @codeCoverageIgnoreEnd } } diff --git a/src/SDK/Metrics/ObservableInstrumentTrait.php b/src/SDK/Metrics/ObservableInstrumentTrait.php index 6b9ea9be8..67a2aea0b 100644 --- a/src/SDK/Metrics/ObservableInstrumentTrait.php +++ b/src/SDK/Metrics/ObservableInstrumentTrait.php @@ -59,4 +59,9 @@ public function observe(callable $callback): ObservableCallbackInterface $this->referenceCounter, ); } + + public function enabled(): bool + { + return true; + } } diff --git a/src/SDK/Metrics/SynchronousInstrumentTrait.php b/src/SDK/Metrics/SynchronousInstrumentTrait.php index d5ffa7e33..7da31cd3c 100644 --- a/src/SDK/Metrics/SynchronousInstrumentTrait.php +++ b/src/SDK/Metrics/SynchronousInstrumentTrait.php @@ -41,4 +41,9 @@ public function write($amount, iterable $attributes = [], $context = null): void { $this->writer->record($this->instrument, $amount, $attributes, $context); } + + public function enabled(): bool + { + return true; + } } diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index 5f9c56920..4115b7ca2 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -41,4 +41,9 @@ public function getInstrumentationScope(): InstrumentationScopeInterface { return $this->instrumentationScope; } + + public function enabled(): bool + { + return true; + } } diff --git a/tests/Unit/API/Logs/NoopLoggerTest.php b/tests/Unit/API/Logs/NoopLoggerTest.php index ce0e35e6c..4bc1f5263 100644 --- a/tests/Unit/API/Logs/NoopLoggerTest.php +++ b/tests/Unit/API/Logs/NoopLoggerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Example\Unit\API\Logs; +namespace OpenTelemetry\Tests\Unit\API\Logs; use OpenTelemetry\API\Logs\NoopLogger; use PHPUnit\Framework\Attributes\CoversClass; @@ -15,4 +15,9 @@ public function test_get_instance(): void { $this->assertInstanceOf(NoopLogger::class, NoopLogger::getInstance()); } + + public function test_enabled(): void + { + $this->assertFalse(NoopLogger::getInstance()->enabled()); + } } diff --git a/tests/Unit/API/Trace/NoopTracerTest.php b/tests/Unit/API/Trace/NoopTracerTest.php new file mode 100644 index 000000000..1ee49eb9c --- /dev/null +++ b/tests/Unit/API/Trace/NoopTracerTest.php @@ -0,0 +1,29 @@ +assertSame(NoopTracer::getInstance(), NoopTracer::getInstance()); + } + + public function test_span_builder(): void + { + $this->assertInstanceOf(NoopSpanBuilder::class, NoopTracer::getInstance()->spanBuilder('test')); + } + + public function test_enabled(): void + { + $this->assertFalse(NoopTracer::getInstance()->enabled()); + } +} diff --git a/tests/Unit/SDK/Logs/LoggerTest.php b/tests/Unit/SDK/Logs/LoggerTest.php index 8400f87db..11670055b 100644 --- a/tests/Unit/SDK/Logs/LoggerTest.php +++ b/tests/Unit/SDK/Logs/LoggerTest.php @@ -109,4 +109,10 @@ public function test_logs_dropped_attributes(): void $logger->emit($record); } + + public function test_enabled(): void + { + $logger = new Logger($this->sharedState, $this->scope); + $this->assertTrue($logger->enabled()); + } } diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index 362653539..e88b2f67e 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -20,6 +20,7 @@ use OpenTelemetry\SDK\Metrics\ObservableCallback; use OpenTelemetry\SDK\Metrics\ObservableCallbackDestructor; use OpenTelemetry\SDK\Metrics\ObservableCounter; +use OpenTelemetry\SDK\Metrics\ObservableInstrumentTrait; use OpenTelemetry\SDK\Metrics\ReferenceCounterInterface; use OpenTelemetry\SDK\Metrics\StalenessHandler\NoopStalenessHandler; use OpenTelemetry\SDK\Metrics\Stream\MetricAggregator; @@ -36,6 +37,7 @@ #[CoversClass(UpDownCounter::class)] #[CoversClass(Histogram::class)] #[CoversClass(ObservableCallback::class)] +#[CoversClass(ObservableInstrumentTrait::class)] final class InstrumentTest extends TestCase { @@ -239,4 +241,24 @@ public function test_observable_callback_does_not_acquire_persistent_on_destruct /** @noinspection PhpExpressionResultUnusedInspection */ new ObservableCallback($writer, $referenceCounter, 1, $callbackDestructor, new stdClass()); } + + public function test_synchronous_enabled(): 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); + + $this->assertTrue($counter->enabled()); + } + + public function test_asynchronous_enabled(): void + { + $w = $this->createMock(MetricWriterInterface::class); + $c = $this->createMock(ReferenceCounterInterface::class); + $i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null); + $counter = new ObservableCounter($w, $i, $c, new WeakMap()); + + $this->assertTrue($counter->enabled()); + } } diff --git a/tests/Unit/SDK/Trace/TracerTest.php b/tests/Unit/SDK/Trace/TracerTest.php index 94341733e..7719bc4bd 100644 --- a/tests/Unit/SDK/Trace/TracerTest.php +++ b/tests/Unit/SDK/Trace/TracerTest.php @@ -63,4 +63,9 @@ public function test_returns_noop_span_builder_if_shared_state_is_shutdown(): vo $this->tracerSharedState->method('hasShutdown')->willReturn(true); //@phpstan-ignore-line $this->assertInstanceOf(NoopSpanBuilder::class, $this->tracer->spanBuilder('foo')); } + + public function test_enabled(): void + { + $this->assertTrue($this->tracer->enabled()); + } } From 7f8324bac34d14d63d2bd5b998f0ddd77d2bffbd Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 18 Jul 2024 21:37:17 +1000 Subject: [PATCH 02/36] tracer configurator --- phpstan.neon.dist | 4 + .../Common/InstrumentationScope/Condition.php | 26 +++++ .../Common/InstrumentationScope/Predicate.php | 12 ++ .../Predicate/Attribute.php | 27 +++++ .../Predicate/AttributeExists.php | 21 ++++ .../InstrumentationScope/Predicate/Name.php | 25 ++++ src/SDK/Common/InstrumentationScope/State.php | 11 ++ src/SDK/Logs/LoggerConfig.php | 10 ++ src/SDK/Logs/LoggerConfigurator.php | 18 +++ src/SDK/Trace/Tracer.php | 8 +- src/SDK/Trace/TracerConfig.php | 27 +++++ src/SDK/Trace/TracerConfigurator.php | 32 +++++ src/SDK/Trace/TracerProvider.php | 8 +- src/SDK/Trace/TracerProviderBuilder.php | 13 +++ .../InstrumentationScope/ConditionTest.php | 24 ++++ .../Predicate/AttributeExistsTest.php | 31 +++++ .../Predicate/AttributeTest.php | 31 +++++ tests/Unit/SDK/Trace/TracerConfigTest.php | 110 ++++++++++++++++++ 18 files changed, 434 insertions(+), 4 deletions(-) create mode 100644 src/SDK/Common/InstrumentationScope/Condition.php create mode 100644 src/SDK/Common/InstrumentationScope/Predicate.php create mode 100644 src/SDK/Common/InstrumentationScope/Predicate/Attribute.php create mode 100644 src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php create mode 100644 src/SDK/Common/InstrumentationScope/Predicate/Name.php create mode 100644 src/SDK/Common/InstrumentationScope/State.php create mode 100644 src/SDK/Logs/LoggerConfig.php create mode 100644 src/SDK/Logs/LoggerConfigurator.php create mode 100644 src/SDK/Trace/TracerConfig.php create mode 100644 src/SDK/Trace/TracerConfigurator.php create mode 100644 tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php create mode 100644 tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php create mode 100644 tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php create mode 100644 tests/Unit/SDK/Trace/TracerConfigTest.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 74b2971a2..1e0e5527e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -38,3 +38,7 @@ 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/Unit/SDK/Trace diff --git a/src/SDK/Common/InstrumentationScope/Condition.php b/src/SDK/Common/InstrumentationScope/Condition.php new file mode 100644 index 000000000..cb9d761ee --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/Condition.php @@ -0,0 +1,26 @@ +predicate->match($scope); + } + + public function state(): State + { + return $this->state; + } +} diff --git a/src/SDK/Common/InstrumentationScope/Predicate.php b/src/SDK/Common/InstrumentationScope/Predicate.php new file mode 100644 index 000000000..66b952179 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/Predicate.php @@ -0,0 +1,12 @@ +getAttributes()->has($this->key)) { + return false; + } + $attribute = $scope->getAttributes()->get($this->key); + + return $attribute === $this->value; + } +} diff --git a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php new file mode 100644 index 000000000..63937fbce --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php @@ -0,0 +1,21 @@ +getAttributes()->has($this->key); + } +} diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php new file mode 100644 index 000000000..f1cec7156 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/Predicate/Name.php @@ -0,0 +1,25 @@ +regex, $scope->getName()); + + return $result > 0; + } +} diff --git a/src/SDK/Common/InstrumentationScope/State.php b/src/SDK/Common/InstrumentationScope/State.php new file mode 100644 index 000000000..3c11ca595 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/State.php @@ -0,0 +1,11 @@ +config = $config ?? TracerConfig::default(); } /** @inheritDoc */ @@ -25,8 +28,7 @@ public function spanBuilder(string $spanName): API\SpanBuilderInterface if (ctype_space($spanName)) { $spanName = self::FALLBACK_SPAN_NAME; } - - if ($this->tracerSharedState->hasShutdown()) { + if (!$this->config->isEnabled() || $this->tracerSharedState->hasShutdown()) { return new API\NoopSpanBuilder(Context::storage()); } @@ -44,6 +46,6 @@ public function getInstrumentationScope(): InstrumentationScopeInterface public function enabled(): bool { - return true; + return $this->config->isEnabled(); } } diff --git a/src/SDK/Trace/TracerConfig.php b/src/SDK/Trace/TracerConfig.php new file mode 100644 index 000000000..039acfe22 --- /dev/null +++ b/src/SDK/Trace/TracerConfig.php @@ -0,0 +1,27 @@ +state === State::ENABLED; + } + + public static function default(): self + { + return new self(); + } +} diff --git a/src/SDK/Trace/TracerConfigurator.php b/src/SDK/Trace/TracerConfigurator.php new file mode 100644 index 000000000..f20d64f2e --- /dev/null +++ b/src/SDK/Trace/TracerConfigurator.php @@ -0,0 +1,32 @@ + $conditions + */ + public function __construct(private readonly array $conditions = []) + { + } + + public function getConfig(InstrumentationScopeInterface $scope): TracerConfig + { + foreach ($this->conditions as $condition) { + if ($condition->match($scope)) { + return new TracerConfig($condition->state()); + } + } + + return TracerConfig::default(); + } +} diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index f0eda6843..d4f575459 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -20,6 +20,7 @@ final class TracerProvider implements TracerProviderInterface { private readonly TracerSharedState $tracerSharedState; private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory; + private readonly TracerConfigurator $configurator; /** @param list|SpanProcessorInterface|null $spanProcessors */ public function __construct( @@ -29,6 +30,7 @@ public function __construct( SpanLimits $spanLimits = null, IdGeneratorInterface $idGenerator = null, ?InstrumentationScopeFactoryInterface $instrumentationScopeFactory = null, + ?TracerConfigurator $configurator = null, ) { $spanProcessors ??= []; $spanProcessors = is_array($spanProcessors) ? $spanProcessors : [$spanProcessors]; @@ -45,6 +47,7 @@ public function __construct( $spanProcessors ); $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); + $this->configurator = $configurator ?? new TracerConfigurator(); } public function forceFlush(?CancellationInterface $cancellation = null): bool @@ -65,9 +68,12 @@ public function getTracer( return NoopTracer::getInstance(); } + $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); + return new Tracer( $this->tracerSharedState, - $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes), + $scope, + $this->configurator->getConfig($scope), ); } diff --git a/src/SDK/Trace/TracerProviderBuilder.php b/src/SDK/Trace/TracerProviderBuilder.php index 5a1cb4ae5..a2e37d490 100644 --- a/src/SDK/Trace/TracerProviderBuilder.php +++ b/src/SDK/Trace/TracerProviderBuilder.php @@ -4,6 +4,9 @@ namespace OpenTelemetry\SDK\Trace; +use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; +use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Resource\ResourceInfo; class TracerProviderBuilder @@ -12,6 +15,8 @@ class TracerProviderBuilder private ?array $spanProcessors = []; private ?ResourceInfo $resource = null; private ?SamplerInterface $sampler = null; + /** @var list */ + private array $conditions = []; public function addSpanProcessor(SpanProcessorInterface $spanProcessor): self { @@ -34,12 +39,20 @@ public function setSampler(SamplerInterface $sampler): self return $this; } + public function addTracerConfiguratorCondition(Predicate $predicate, State $state): self + { + $this->conditions[] = new Condition($predicate, $state); + + return $this; + } + public function build(): TracerProviderInterface { return new TracerProvider( $this->spanProcessors, $this->sampler, $this->resource, + configurator: new TracerConfigurator($this->conditions), ); } } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php new file mode 100644 index 000000000..90866f105 --- /dev/null +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php @@ -0,0 +1,24 @@ +createMock(Predicate::class); + $predicate->expects($this->once())->method('match')->willReturn(true); + $condition = new Condition($predicate, State::DISABLED); + $this->assertTrue($condition->match($this->createMock(InstrumentationScopeInterface::class))); + } +} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php new file mode 100644 index 000000000..f0529ca35 --- /dev/null +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php @@ -0,0 +1,31 @@ +createMock(InstrumentationScopeInterface::class); + $attributes = $this->createMock(AttributesInterface::class); + $scope->method('getAttributes')->willReturn($attributes); + $attributes->method('has')->willReturnCallback(function (string $key) { + return $key === 'foo'; + }); + + $predicate = new AttributeExists('foo'); + $this->assertTrue($predicate->match($scope)); + + $predicate = new AttributeExists('bar'); + $this->assertFalse($predicate->match($scope)); + } +} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php new file mode 100644 index 000000000..1f168a6c4 --- /dev/null +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php @@ -0,0 +1,31 @@ + 'bar'], 0); + $scope = $this->createMock(InstrumentationScopeInterface::class); + $scope->method('getAttributes')->willReturn($attributes); + + $predicate = new Attribute('foo', 'bar'); + $this->assertTrue($predicate->match($scope), 'found and matches'); + + $predicate = new Attribute('foo', 'baz'); + $this->assertFalse($predicate->match($scope), 'found but does not match'); + + $predicate = new Attribute('bar', 'bat'); + $this->assertFalse($predicate->match($scope), 'no attribute found'); + } +} diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Unit/SDK/Trace/TracerConfigTest.php new file mode 100644 index 000000000..397ad2d18 --- /dev/null +++ b/tests/Unit/SDK/Trace/TracerConfigTest.php @@ -0,0 +1,110 @@ +addSpanProcessor(new SimpleSpanProcessor($exporter)) + ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two + ->build(); + $tracer_one = $tracerProvider->getTracer('one'); + $tracer_two = $tracerProvider->getTracer('two'); + $tracer_three = $tracerProvider->getTracer('three'); + + $parent = $tracer_one->spanBuilder('parent')->startSpan(); + $this->assertTrue($parent->isRecording()); + $parent->setAttribute('a', 1); + $parentScope = $parent->activate(); + + try { + $child = $tracer_two->spanBuilder('child')->startSpan(); + $child->setAttribute('b', 1); + $childScope = $child->activate(); + + try { + $this->assertFalse($child->isRecording()); + $grandChild = $tracer_three->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'); + } + + #[DataProvider('conditionsProvider')] + public function test_conditions(Predicate $predicate, State $state, bool $expectDisabled): void + { + $tracerProvider = TracerProvider::builder() + ->addTracerConfiguratorCondition($predicate, $state) + ->build(); + $tracer = $tracerProvider->getTracer(name: 'two', attributes: ['foo' => 'bar']); + $span = $tracer->spanBuilder('span')->startSpan(); + if ($expectDisabled) { + $this->assertInstanceOf(NonRecordingSpan::class, $span); + } else { + $this->assertNotInstanceOf(NonRecordingSpan::class, $span); + } + } + + public static function conditionsProvider(): array + { + return [ + 'match name + disable' => [new Predicate\Name('~two~'), State::DISABLED, true], + 'match name + enable' => [new Predicate\Name('~two~'), State::ENABLED, false], + 'no match name + disable' => [new Predicate\Name('~one~'), State::DISABLED, false], + 'no match name + enable' => [new Predicate\Name('~one~'), State::ENABLED, false], + 'attribute exists + disable' => [new Predicate\AttributeExists('foo'), State::DISABLED, true], + 'attribute exists + enable' => [new Predicate\AttributeExists('foo'), State::ENABLED, false], + 'attributes matches + disable' => [new Predicate\Attribute('foo', 'bar'), State::DISABLED, true], + 'attribute does not match' => [new Predicate\Attribute('foo', 'no-match'), State::DISABLED, false], + ]; + } +} From b61feede9a00e1f64ed4580b34a8331eb409c68e Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 18 Jul 2024 22:19:46 +1000 Subject: [PATCH 03/36] logger config --- src/SDK/Logs/Logger.php | 5 ++- src/SDK/Logs/LoggerConfig.php | 14 ++++++++ src/SDK/Logs/LoggerConfigurator.php | 18 ++++++++-- src/SDK/Logs/LoggerProvider.php | 8 ++++- src/SDK/Logs/LoggerProviderBuilder.php | 13 ++++++- tests/Unit/SDK/Logs/LoggerConfigTest.php | 41 ++++++++++++++++++++++ tests/Unit/SDK/Logs/LoggerProviderTest.php | 26 ++++++++++++-- 7 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 tests/Unit/SDK/Logs/LoggerConfigTest.php diff --git a/src/SDK/Logs/Logger.php b/src/SDK/Logs/Logger.php index 3004e755b..0327c5c0c 100644 --- a/src/SDK/Logs/Logger.php +++ b/src/SDK/Logs/Logger.php @@ -18,6 +18,7 @@ class Logger implements LoggerInterface { use LogsMessagesTrait; + private readonly LoggerConfig $config; /** * @internal @@ -25,7 +26,9 @@ class Logger implements LoggerInterface public function __construct( private readonly LoggerSharedState $loggerSharedState, private readonly InstrumentationScopeInterface $scope, + ?LoggerConfig $config = null, ) { + $this->config = $config ?? LoggerConfig::default(); } public function emit(LogRecord $logRecord): void @@ -45,6 +48,6 @@ public function emit(LogRecord $logRecord): void public function enabled(): bool { - return true; + return $this->config->isEnabled(); } } diff --git a/src/SDK/Logs/LoggerConfig.php b/src/SDK/Logs/LoggerConfig.php index 3a01b13bf..b21ee6548 100644 --- a/src/SDK/Logs/LoggerConfig.php +++ b/src/SDK/Logs/LoggerConfig.php @@ -4,7 +4,21 @@ namespace OpenTelemetry\SDK\Logs; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; + class LoggerConfig { + public function __construct(private readonly State $state = State::ENABLED) + { + } + + public function isEnabled(): bool + { + return $this->state === State::ENABLED; + } + public static function default(): self + { + return new self(); + } } diff --git a/src/SDK/Logs/LoggerConfigurator.php b/src/SDK/Logs/LoggerConfigurator.php index 299cc3c46..e38e2bb3a 100644 --- a/src/SDK/Logs/LoggerConfigurator.php +++ b/src/SDK/Logs/LoggerConfigurator.php @@ -5,14 +5,28 @@ namespace OpenTelemetry\SDK\Logs; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; /** * @experimental */ class LoggerConfigurator { - public function __invoke(InstrumentationScopeInterface $scope): LoggerConfig + /** + * @param list $conditions + */ + public function __construct(private readonly array $conditions = []) { - return new LoggerConfig(); + } + + public function getConfig(InstrumentationScopeInterface $scope): LoggerConfig + { + foreach ($this->conditions as $condition) { + if ($condition->match($scope)) { + return new LoggerConfig($condition->state()); + } + } + + return LoggerConfig::default(); } } diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index 707cb3319..67179d71a 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -14,17 +14,20 @@ class LoggerProvider implements LoggerProviderInterface { private readonly LoggerSharedState $loggerSharedState; + private readonly LoggerConfigurator $configurator; public function __construct( LogRecordProcessorInterface $processor, private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null, + ?LoggerConfigurator $configurator = null, ) { $this->loggerSharedState = new LoggerSharedState( $resource ?? ResourceInfoFactory::defaultResource(), (new LogRecordLimitsBuilder())->build(), $processor ); + $this->configurator = $configurator ?? new LoggerConfigurator(); } /** @@ -36,8 +39,11 @@ public function getLogger(string $name, ?string $version = null, ?string $schema return NoopLogger::getInstance(); } $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); + if ($this->configurator->getConfig($scope)->isEnabled() === false) { + return NoopLogger::getInstance(); + } - return new Logger($this->loggerSharedState, $scope); + return new Logger($this->loggerSharedState, $scope, $this->configurator->getConfig($scope)); } public function shutdown(CancellationInterface $cancellation = null): bool diff --git a/src/SDK/Logs/LoggerProviderBuilder.php b/src/SDK/Logs/LoggerProviderBuilder.php index a4ac29df5..2de193ce6 100644 --- a/src/SDK/Logs/LoggerProviderBuilder.php +++ b/src/SDK/Logs/LoggerProviderBuilder.php @@ -6,6 +6,7 @@ use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; +use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; use OpenTelemetry\SDK\Logs\Processor\MultiLogRecordProcessor; use OpenTelemetry\SDK\Logs\Processor\NoopLogRecordProcessor; use OpenTelemetry\SDK\Resource\ResourceInfo; @@ -15,6 +16,8 @@ class LoggerProviderBuilder /** @var array */ private array $processors = []; private ?ResourceInfo $resource = null; + /** @var list */ + private array $conditions = []; public function addLogRecordProcessor(LogRecordProcessorInterface $processor): self { @@ -35,10 +38,18 @@ public function build(): LoggerProviderInterface return new LoggerProvider( $this->buildProcessor(), new InstrumentationScopeFactory(Attributes::factory()), - $this->resource + $this->resource, + configurator: new LoggerConfigurator($this->conditions), ); } + public function addLoggerConfiguratorCondition(Condition $condition): self + { + $this->conditions[] = $condition; + + return $this; + } + private function buildProcessor(): LogRecordProcessorInterface { return match (count($this->processors)) { diff --git a/tests/Unit/SDK/Logs/LoggerConfigTest.php b/tests/Unit/SDK/Logs/LoggerConfigTest.php new file mode 100644 index 000000000..3484c2537 --- /dev/null +++ b/tests/Unit/SDK/Logs/LoggerConfigTest.php @@ -0,0 +1,41 @@ +addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) + ->addLoggerConfiguratorCondition(new Condition(new Name('~two~'), State::DISABLED)) //disable logger named 'two' + ->build(); + + $logger_one = $loggerProvider->getLogger('one'); + $logger_two = $loggerProvider->getLogger('two'); + $logger_three = $loggerProvider->getLogger('three'); + + $this->assertNotInstanceOf(NoopLogger::class, $logger_one); + $this->assertInstanceOf(NoopLogger::class, $logger_two); + $this->assertNotInstanceOf(NoopLogger::class, $logger_three); + } +} diff --git a/tests/Unit/SDK/Logs/LoggerProviderTest.php b/tests/Unit/SDK/Logs/LoggerProviderTest.php index 08a7fda92..389480e49 100644 --- a/tests/Unit/SDK/Logs/LoggerProviderTest.php +++ b/tests/Unit/SDK/Logs/LoggerProviderTest.php @@ -7,7 +7,10 @@ use OpenTelemetry\API\Logs\NoopLogger; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Logs\Logger; +use OpenTelemetry\SDK\Logs\LoggerConfig; +use OpenTelemetry\SDK\Logs\LoggerConfigurator; 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 +26,24 @@ class LoggerProviderTest extends TestCase { /** @var LogRecordProcessorInterface&MockObject $processor */ private LogRecordProcessorInterface $processor; - private InstrumentationScopeFactoryInterface $instrumentationScopeFactory; private LoggerProvider $provider; + /** @var LoggerConfig&MockObject */ + private LoggerConfig $config; public function setUp(): void { $this->processor = $this->createMock(LogRecordProcessorInterface::class); - $this->instrumentationScopeFactory = $this->createMock(InstrumentationScopeFactoryInterface::class); + $instrumentationScopeFactory = $this->createMock(InstrumentationScopeFactoryInterface::class); $resource = $this->createMock(ResourceInfo::class); - $this->provider = new LoggerProvider($this->processor, $this->instrumentationScopeFactory, $resource); + $this->config = $this->createMock(LoggerConfig::class); + $configurator = $this->createMock(LoggerConfigurator::class); + $configurator->method('getConfig')->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 +55,13 @@ public function test_get_logger_after_shutdown(): void $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->assertInstanceOf(NoopLogger::class, $logger); + } + public function test_shutdown_calls_processor_shutdown(): void { $this->processor->expects($this->once())->method('shutdown'); @@ -58,4 +73,9 @@ public function test_force_flush_calls_processor_force_flush(): void $this->processor->expects($this->once())->method('forceFlush'); $this->provider->forceFlush(); } + + public function test_builder(): void + { + $this->assertInstanceOf(LoggerProviderBuilder::class, $this->provider->builder()); + } } From 3111994b740e1671dc3908258bf31c924473d905 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 18 Jul 2024 23:51:24 +1000 Subject: [PATCH 04/36] meter config --- src/API/Metrics/MeterInterface.php | 2 + src/API/Metrics/Noop/NoopMeter.php | 5 ++ src/SDK/Metrics/Meter.php | 44 ++++++++++++++--- src/SDK/Metrics/MeterConfig.php | 24 +++++++++ src/SDK/Metrics/MeterConfigurator.php | 32 ++++++++++++ src/SDK/Metrics/MeterProvider.php | 8 ++- src/SDK/Metrics/MeterProviderBuilder.php | 11 +++++ src/SDK/Metrics/ObservableInstrumentTrait.php | 3 ++ .../Metrics/SynchronousInstrumentTrait.php | 6 ++- tests/Unit/SDK/Metrics/InstrumentTest.php | 21 +++++--- tests/Unit/SDK/Metrics/MeterConfigTest.php | 49 +++++++++++++++++++ 11 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 src/SDK/Metrics/MeterConfig.php create mode 100644 src/SDK/Metrics/MeterConfigurator.php create mode 100644 tests/Unit/SDK/Metrics/MeterConfigTest.php diff --git a/src/API/Metrics/MeterInterface.php b/src/API/Metrics/MeterInterface.php index fa12e5814..f8f0b9c69 100644 --- a/src/API/Metrics/MeterInterface.php +++ b/src/API/Metrics/MeterInterface.php @@ -178,4 +178,6 @@ public function createObservableUpDownCounter( array|callable $advisory = [], callable ...$callbacks, ): ObservableUpDownCounterInterface; + + public function isEnabled(): bool; } diff --git a/src/API/Metrics/Noop/NoopMeter.php b/src/API/Metrics/Noop/NoopMeter.php index 25ae9f864..63671c800 100644 --- a/src/API/Metrics/Noop/NoopMeter.php +++ b/src/API/Metrics/Noop/NoopMeter.php @@ -56,4 +56,9 @@ public function createObservableUpDownCounter(string $name, ?string $unit = null { return new NoopObservableUpDownCounter(); } + + public function isEnabled(): bool + { + return false; + } } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index f13544f51..671046153 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -15,6 +15,7 @@ use OpenTelemetry\API\Metrics\GaugeInterface; use OpenTelemetry\API\Metrics\HistogramInterface; use OpenTelemetry\API\Metrics\MeterInterface; +use OpenTelemetry\API\Metrics\Noop\NoopMeter; use OpenTelemetry\API\Metrics\ObservableCallbackInterface; use OpenTelemetry\API\Metrics\ObservableCounterInterface; use OpenTelemetry\API\Metrics\ObservableGaugeInterface; @@ -39,6 +40,7 @@ final class Meter implements MeterInterface use LogsMessagesTrait; private ?string $instrumentationScopeId = null; + private NoopMeter $noop; /** * @param iterable $metricRegistries @@ -57,7 +59,9 @@ public function __construct( private readonly MetricRegistryInterface $registry, private readonly MetricWriterInterface $writer, private readonly ArrayAccess $destructors, + private readonly MeterConfig $config, ) { + $this->noop = new NoopMeter(); } private static function dummyInstrument(): Instrument @@ -108,6 +112,9 @@ public function batchObserve(callable $callback, AsynchronousInstrument $instrum public function createCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): CounterInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createCounter($name); + } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::COUNTER, $name, @@ -116,11 +123,14 @@ public function createCounter(string $name, ?string $unit = null, ?string $descr $advisory, ); - return new Counter($this->writer, $instrument, $referenceCounter); + return new Counter($this->writer, $instrument, $referenceCounter, $this->config); } public function createObservableCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableCounterInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createObservableCounter($name); + } if (is_callable($advisory)) { array_unshift($callbacks, $advisory); $advisory = []; @@ -138,11 +148,14 @@ public function createObservableCounter(string $name, ?string $unit = null, ?str $referenceCounter->acquire(true); } - return new ObservableCounter($this->writer, $instrument, $referenceCounter, $this->destructors); + return new ObservableCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this->config); } public function createHistogram(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): HistogramInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createHistogram($name); + } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::HISTOGRAM, $name, @@ -151,11 +164,14 @@ public function createHistogram(string $name, ?string $unit = null, ?string $des $advisory, ); - return new Histogram($this->writer, $instrument, $referenceCounter); + return new Histogram($this->writer, $instrument, $referenceCounter, $this->config); } public function createGauge(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): GaugeInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createGauge($name); + } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::GAUGE, $name, @@ -164,11 +180,14 @@ public function createGauge(string $name, ?string $unit = null, ?string $descrip $advisory, ); - return new Gauge($this->writer, $instrument, $referenceCounter); + return new Gauge($this->writer, $instrument, $referenceCounter, $this->config); } public function createObservableGauge(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableGaugeInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createObservableGauge($name); + } if (is_callable($advisory)) { array_unshift($callbacks, $advisory); $advisory = []; @@ -186,11 +205,14 @@ public function createObservableGauge(string $name, ?string $unit = null, ?strin $referenceCounter->acquire(true); } - return new ObservableGauge($this->writer, $instrument, $referenceCounter, $this->destructors); + return new ObservableGauge($this->writer, $instrument, $referenceCounter, $this->destructors, $this->config); } public function createUpDownCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): UpDownCounterInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createUpDownCounter($name); + } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::UP_DOWN_COUNTER, $name, @@ -199,11 +221,14 @@ public function createUpDownCounter(string $name, ?string $unit = null, ?string $advisory, ); - return new UpDownCounter($this->writer, $instrument, $referenceCounter); + return new UpDownCounter($this->writer, $instrument, $referenceCounter, $this->config); } public function createObservableUpDownCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableUpDownCounterInterface { + if ($this->config->isEnabled() === false) { + return $this->noop->createObservableUpDownCounter($name); + } if (is_callable($advisory)) { array_unshift($callbacks, $advisory); $advisory = []; @@ -221,7 +246,12 @@ public function createObservableUpDownCounter(string $name, ?string $unit = null $referenceCounter->acquire(true); } - return new ObservableUpDownCounter($this->writer, $instrument, $referenceCounter, $this->destructors); + return new ObservableUpDownCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this->config); + } + + public function isEnabled(): bool + { + return $this->config->isEnabled(); } /** diff --git a/src/SDK/Metrics/MeterConfig.php b/src/SDK/Metrics/MeterConfig.php new file mode 100644 index 000000000..7cb2058bb --- /dev/null +++ b/src/SDK/Metrics/MeterConfig.php @@ -0,0 +1,24 @@ +state === State::ENABLED; + } + + public static function default(): self + { + return new self(); + } +} diff --git a/src/SDK/Metrics/MeterConfigurator.php b/src/SDK/Metrics/MeterConfigurator.php new file mode 100644 index 000000000..5064f3259 --- /dev/null +++ b/src/SDK/Metrics/MeterConfigurator.php @@ -0,0 +1,32 @@ + $conditions + */ + public function __construct(private readonly array $conditions = []) + { + } + + public function getConfig(InstrumentationScopeInterface $scope): MeterConfig + { + foreach ($this->conditions as $condition) { + if ($condition->match($scope)) { + return new MeterConfig($condition->state()); + } + } + + return MeterConfig::default(); + } +} diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index 4fc307f41..d00984ec5 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -29,6 +29,7 @@ final class MeterProvider implements MeterProviderInterface private readonly ArrayAccess $destructors; private bool $closed = false; + private readonly MeterConfigurator $configurator; /** * @param iterable $metricReaders @@ -44,6 +45,7 @@ public function __construct( private readonly ?ExemplarFilterInterface $exemplarFilter, private readonly StalenessHandlerFactoryInterface $stalenessHandlerFactory, MetricFactoryInterface $metricFactory = null, + ?MeterConfigurator $configurator = null, ) { $this->metricFactory = $metricFactory ?? new StreamFactory(); $this->instruments = new MeterInstruments(); @@ -52,6 +54,7 @@ public function __construct( $this->registry = $registry; $this->writer = $registry; $this->destructors = new WeakMap(); + $this->configurator = $configurator ?? new MeterConfigurator(); } public function getMeter( @@ -64,6 +67,8 @@ public function getMeter( return new NoopMeter(); } + $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); + return new Meter( $this->metricFactory, $this->resource, @@ -73,10 +78,11 @@ public function getMeter( $this->viewRegistry, $this->exemplarFilter, $this->instruments, - $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes), + $scope, $this->registry, $this->writer, $this->destructors, + $this->configurator->getConfig($scope), ); } diff --git a/src/SDK/Metrics/MeterProviderBuilder.php b/src/SDK/Metrics/MeterProviderBuilder.php index 940621bcb..401ef336c 100644 --- a/src/SDK/Metrics/MeterProviderBuilder.php +++ b/src/SDK/Metrics/MeterProviderBuilder.php @@ -7,6 +7,7 @@ use OpenTelemetry\API\Common\Time\Clock; use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; +use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\WithSampledTraceExemplarFilter; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface; use OpenTelemetry\SDK\Metrics\StalenessHandler\NoopStalenessHandlerFactory; @@ -20,6 +21,8 @@ class MeterProviderBuilder private array $metricReaders = []; private ?ResourceInfo $resource = null; private ?ExemplarFilterInterface $exemplarFilter = null; + /** @var list */ + private array $conditions = []; public function setResource(ResourceInfo $resource): self { @@ -42,6 +45,13 @@ public function addReader(MetricReaderInterface $reader): self return $this; } + public function addMeterConfiguratorCondition(Condition $condition): self + { + $this->conditions[] = $condition; + + return $this; + } + /** * @psalm-suppress PossiblyInvalidArgument */ @@ -57,6 +67,7 @@ public function build(): MeterProviderInterface new CriteriaViewRegistry(), $this->exemplarFilter ?? new WithSampledTraceExemplarFilter(), new NoopStalenessHandlerFactory(), + configurator: new MeterConfigurator($this->conditions), ); } } diff --git a/src/SDK/Metrics/ObservableInstrumentTrait.php b/src/SDK/Metrics/ObservableInstrumentTrait.php index 67a2aea0b..03d7da76a 100644 --- a/src/SDK/Metrics/ObservableInstrumentTrait.php +++ b/src/SDK/Metrics/ObservableInstrumentTrait.php @@ -19,12 +19,14 @@ trait ObservableInstrumentTrait private Instrument $instrument; private ReferenceCounterInterface $referenceCounter; private ArrayAccess $destructors; + private MeterConfig $config; public function __construct( MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, ArrayAccess $destructors, + MeterConfig $config, ) { assert($this instanceof InstrumentHandle); @@ -32,6 +34,7 @@ public function __construct( $this->instrument = $instrument; $this->referenceCounter = $referenceCounter; $this->destructors = $destructors; + $this->config = $config; $this->referenceCounter->acquire(); } diff --git a/src/SDK/Metrics/SynchronousInstrumentTrait.php b/src/SDK/Metrics/SynchronousInstrumentTrait.php index 7da31cd3c..136723d11 100644 --- a/src/SDK/Metrics/SynchronousInstrumentTrait.php +++ b/src/SDK/Metrics/SynchronousInstrumentTrait.php @@ -15,14 +15,16 @@ trait SynchronousInstrumentTrait private MetricWriterInterface $writer; private Instrument $instrument; private ReferenceCounterInterface $referenceCounter; + private MeterConfig $config; - public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter) + public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, MeterConfig $config) { assert($this instanceof InstrumentHandle); $this->writer = $writer; $this->instrument = $instrument; $this->referenceCounter = $referenceCounter; + $this->config = $config; $this->referenceCounter->acquire(); } @@ -44,6 +46,6 @@ public function write($amount, iterable $attributes = [], $context = null): void public function enabled(): bool { - return true; + return $this->config->isEnabled(); } } diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index e88b2f67e..90de48226 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -15,6 +15,7 @@ use OpenTelemetry\SDK\Metrics\Histogram; use OpenTelemetry\SDK\Metrics\Instrument; use OpenTelemetry\SDK\Metrics\InstrumentType; +use OpenTelemetry\SDK\Metrics\MeterConfig; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricRegistry; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; use OpenTelemetry\SDK\Metrics\ObservableCallback; @@ -40,6 +41,12 @@ #[CoversClass(ObservableInstrumentTrait::class)] final class InstrumentTest extends TestCase { + private MeterConfig $config; + + public function setUp(): void + { + $this->config = MeterConfig::default(); + } public function test_counter(): void { @@ -50,7 +57,7 @@ public function test_counter(): void $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->config); $c->add(5); $c->add(7); $c->add(3); @@ -79,7 +86,7 @@ public function test_asynchronous_counter(): void $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->config); $c->observe(static function (ObserverInterface $observer): void { $observer->observe(5); }); @@ -115,7 +122,7 @@ public function __invoke(ObserverInterface $observer) } }; - $c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap()); + $c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->config); $c->observe($instance); $instance = null; @@ -136,7 +143,7 @@ public function test_up_down_counter(): void $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->config); $c->add(5); $c->add(7); $c->add(-8); @@ -165,7 +172,7 @@ public function test_histogram(): void $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->config); $h->record(1); $h->record(7); $h->record(9); @@ -247,7 +254,7 @@ public function test_synchronous_enabled(): 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); + $counter = new Counter($w, $i, $c, $this->config); $this->assertTrue($counter->enabled()); } @@ -257,7 +264,7 @@ public function test_asynchronous_enabled(): void $w = $this->createMock(MetricWriterInterface::class); $c = $this->createMock(ReferenceCounterInterface::class); $i = new Instrument(InstrumentType::UP_DOWN_COUNTER, 'test', null, null); - $counter = new ObservableCounter($w, $i, $c, new WeakMap()); + $counter = new ObservableCounter($w, $i, $c, new WeakMap(), $this->config); $this->assertTrue($counter->enabled()); } diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Unit/SDK/Metrics/MeterConfigTest.php new file mode 100644 index 000000000..3e2301229 --- /dev/null +++ b/tests/Unit/SDK/Metrics/MeterConfigTest.php @@ -0,0 +1,49 @@ +addMeterConfiguratorCondition(new Condition(new Name('~two~'), State::DISABLED)) //meter two disabled + ->build(); + + $meter_one = $meterProvider->getMeter('one'); + $meter_two = $meterProvider->getMeter('two'); + $meter_three = $meterProvider->getMeter('three'); + + $this->assertTrue($meter_one->isEnabled()); + $this->assertFalse($meter_two->isEnabled()); + $this->assertTrue($meter_three->isEnabled()); + + $this->assertInstanceOf(NoopCounter::class, $meter_two->createCounter('a')); + $this->assertInstanceOf(NoopObservableCounter::class, $meter_two->createObservableCounter('b')); + $this->assertInstanceOf(NoopUpDownCounter::class, $meter_two->createUpDownCounter('c')); + $this->assertInstanceOf(NoopObservableUpDownCounter::class, $meter_two->createObservableUpDownCounter('d')); + $this->assertInstanceOf(NoopHistogram::class, $meter_two->createHistogram('e')); + $this->assertInstanceOf(NoopGauge::class, $meter_two->createGauge('f')); + $this->assertInstanceOf(NoopObservableGauge::class, $meter_two->createObservableGauge('g')); + } +} From 62486094815a36211fd82ce7180ed6e410299865 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Fri, 19 Jul 2024 13:43:34 +1000 Subject: [PATCH 05/36] allow tracer reconfiguration after creation --- src/SDK/Trace/NoopTracerProvider.php | 4 ++++ src/SDK/Trace/Tracer.php | 7 ++++++- src/SDK/Trace/TracerProvider.php | 20 +++++++++++++++++--- src/SDK/Trace/TracerProviderInterface.php | 2 ++ tests/Unit/SDK/Trace/TracerConfigTest.php | 16 ++++++++++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/SDK/Trace/NoopTracerProvider.php b/src/SDK/Trace/NoopTracerProvider.php index 7cd4d4e7d..5ad6ab92b 100644 --- a/src/SDK/Trace/NoopTracerProvider.php +++ b/src/SDK/Trace/NoopTracerProvider.php @@ -18,4 +18,8 @@ public function shutdown(?CancellationInterface $cancellation = null): bool { return true; } + + public function updateConfigurator(TracerConfigurator $configurator): void + { + } } diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index bcd9c0913..7582208f8 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -12,7 +12,7 @@ class Tracer implements API\TracerInterface { public const FALLBACK_SPAN_NAME = 'empty'; - private readonly TracerConfig $config; + private TracerConfig $config; public function __construct( private readonly TracerSharedState $tracerSharedState, @@ -48,4 +48,9 @@ public function enabled(): bool { return $this->config->isEnabled(); } + + public function updateConfig(TracerConfigurator $configurator): void + { + $this->config = $configurator->getConfig($this->instrumentationScope); + } } diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index d4f575459..fa7f755bb 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -15,12 +15,14 @@ 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 TracerConfigurator $configurator; + private TracerConfigurator $configurator; + private WeakMap $tracers; /** @param list|SpanProcessorInterface|null $spanProcessors */ public function __construct( @@ -48,6 +50,7 @@ public function __construct( ); $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); $this->configurator = $configurator ?? new TracerConfigurator(); + $this->tracers = new WeakMap(); } public function forceFlush(?CancellationInterface $cancellation = null): bool @@ -69,12 +72,14 @@ public function getTracer( } $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); - - return new Tracer( + $tracer = new Tracer( $this->tracerSharedState, $scope, $this->configurator->getConfig($scope), ); + $this->tracers->offsetSet($tracer, $tracer); + + return $tracer; } public function getSampler(): SamplerInterface @@ -98,4 +103,13 @@ public static function builder(): TracerProviderBuilder { return new TracerProviderBuilder(); } + + public function updateConfigurator(TracerConfigurator $configurator): void + { + $this->configurator = $configurator; + + foreach ($this->tracers as $tracer) { + $tracer->updateConfig($configurator); + } + } } diff --git a/src/SDK/Trace/TracerProviderInterface.php b/src/SDK/Trace/TracerProviderInterface.php index d61c1ea8f..937191b2f 100644 --- a/src/SDK/Trace/TracerProviderInterface.php +++ b/src/SDK/Trace/TracerProviderInterface.php @@ -12,4 +12,6 @@ interface TracerProviderInterface extends API\TracerProviderInterface public function forceFlush(?CancellationInterface $cancellation = null): bool; public function shutdown(?CancellationInterface $cancellation = null): bool; + + public function updateConfigurator(TracerConfigurator $configurator): void; } diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Unit/SDK/Trace/TracerConfigTest.php index 397ad2d18..6b4b94fb4 100644 --- a/tests/Unit/SDK/Trace/TracerConfigTest.php +++ b/tests/Unit/SDK/Trace/TracerConfigTest.php @@ -12,6 +12,7 @@ use OpenTelemetry\SDK\Trace\ImmutableSpan; 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\TracerConfigurator; use OpenTelemetry\SDK\Trace\TracerProvider; @@ -107,4 +108,19 @@ public static function conditionsProvider(): array 'attribute does not match' => [new Predicate\Attribute('foo', 'no-match'), State::DISABLED, false], ]; } + + public function test_enable_after_disable(): void + { + $tracerProvider = TracerProvider::builder() + ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two + ->build(); + $tracer = $tracerProvider->getTracer(name: 'two'); + $this->assertInstanceOf(Tracer::class, $tracer); + $this->assertFalse($tracer->enabled()); + + $update = new TracerConfigurator(); + $tracerProvider->updateConfigurator($update); + + $this->assertTrue($tracer->enabled()); + } } From 1a4fca77b1fd94dde44cc9d1a0c65558a20c7e93 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Fri, 19 Jul 2024 14:48:30 +1000 Subject: [PATCH 06/36] test enabling a tracer mid-trace --- tests/Unit/SDK/Trace/TracerConfigTest.php | 75 +++++++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Unit/SDK/Trace/TracerConfigTest.php index 6b4b94fb4..bda68292b 100644 --- a/tests/Unit/SDK/Trace/TracerConfigTest.php +++ b/tests/Unit/SDK/Trace/TracerConfigTest.php @@ -36,23 +36,23 @@ public function test_disable_scopes(): void ->addSpanProcessor(new SimpleSpanProcessor($exporter)) ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two ->build(); - $tracer_one = $tracerProvider->getTracer('one'); - $tracer_two = $tracerProvider->getTracer('two'); - $tracer_three = $tracerProvider->getTracer('three'); + $tracerA = $tracerProvider->getTracer('one'); + $tracerB = $tracerProvider->getTracer('two'); + $tracerC = $tracerProvider->getTracer('three'); - $parent = $tracer_one->spanBuilder('parent')->startSpan(); + $parent = $tracerA->spanBuilder('parent')->startSpan(); $this->assertTrue($parent->isRecording()); $parent->setAttribute('a', 1); $parentScope = $parent->activate(); try { - $child = $tracer_two->spanBuilder('child')->startSpan(); + $child = $tracerB->spanBuilder('child')->startSpan(); $child->setAttribute('b', 1); $childScope = $child->activate(); try { $this->assertFalse($child->isRecording()); - $grandChild = $tracer_three->spanBuilder('grandchild')->startSpan(); + $grandChild = $tracerC->spanBuilder('grandchild')->startSpan(); $this->assertTrue($grandChild->isRecording()); $grandChild->setAttribute('c', 1); $grandChild->end(); @@ -80,6 +80,69 @@ public function test_disable_scopes(): void $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)) + ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two + ->build(); + $tracerA = $tracerProvider->getTracer('one'); + $tracerB = $tracerProvider->getTracer('two'); + $tracerC = $tracerProvider->getTracer('three'); + + $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(new TracerConfigurator()); //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'); + } + #[DataProvider('conditionsProvider')] public function test_conditions(Predicate $predicate, State $state, bool $expectDisabled): void { From 0d70f91befbd1cd2e88ca59ed201960d3917be1a Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Fri, 19 Jul 2024 16:06:17 +1000 Subject: [PATCH 07/36] tracer configurator builder --- src/SDK/Trace/TracerConfigurator.php | 5 ++++ src/SDK/Trace/TracerConfiguratorBuilder.php | 27 ++++++++++++++++++++ src/SDK/Trace/TracerProviderBuilder.php | 12 +++------ tests/Unit/SDK/Trace/TracerConfigTest.php | 28 +++++++++++++-------- 4 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 src/SDK/Trace/TracerConfiguratorBuilder.php diff --git a/src/SDK/Trace/TracerConfigurator.php b/src/SDK/Trace/TracerConfigurator.php index f20d64f2e..365053acf 100644 --- a/src/SDK/Trace/TracerConfigurator.php +++ b/src/SDK/Trace/TracerConfigurator.php @@ -29,4 +29,9 @@ public function getConfig(InstrumentationScopeInterface $scope): TracerConfig return TracerConfig::default(); } + + public static function builder(): TracerConfiguratorBuilder + { + return new TracerConfiguratorBuilder(); + } } diff --git a/src/SDK/Trace/TracerConfiguratorBuilder.php b/src/SDK/Trace/TracerConfiguratorBuilder.php new file mode 100644 index 000000000..897a73b92 --- /dev/null +++ b/src/SDK/Trace/TracerConfiguratorBuilder.php @@ -0,0 +1,27 @@ + */ + private array $conditions = []; + + public function addCondition(Predicate $predicate, State $state): TracerConfiguratorBuilder + { + $this->conditions[] = new Condition($predicate, $state); + + return $this; + } + + public function build(): TracerConfigurator + { + return new TracerConfigurator($this->conditions); + } +} diff --git a/src/SDK/Trace/TracerProviderBuilder.php b/src/SDK/Trace/TracerProviderBuilder.php index a2e37d490..409a26809 100644 --- a/src/SDK/Trace/TracerProviderBuilder.php +++ b/src/SDK/Trace/TracerProviderBuilder.php @@ -4,9 +4,6 @@ namespace OpenTelemetry\SDK\Trace; -use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Resource\ResourceInfo; class TracerProviderBuilder @@ -15,8 +12,7 @@ class TracerProviderBuilder private ?array $spanProcessors = []; private ?ResourceInfo $resource = null; private ?SamplerInterface $sampler = null; - /** @var list */ - private array $conditions = []; + private ?TracerConfigurator $configurator = null; public function addSpanProcessor(SpanProcessorInterface $spanProcessor): self { @@ -39,9 +35,9 @@ public function setSampler(SamplerInterface $sampler): self return $this; } - public function addTracerConfiguratorCondition(Predicate $predicate, State $state): self + public function setConfigurator(TracerConfigurator $configurator): self { - $this->conditions[] = new Condition($predicate, $state); + $this->configurator = $configurator; return $this; } @@ -52,7 +48,7 @@ public function build(): TracerProviderInterface $this->spanProcessors, $this->sampler, $this->resource, - configurator: new TracerConfigurator($this->conditions), + configurator: $this->configurator, ); } } diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Unit/SDK/Trace/TracerConfigTest.php index bda68292b..1a8bef8c5 100644 --- a/tests/Unit/SDK/Trace/TracerConfigTest.php +++ b/tests/Unit/SDK/Trace/TracerConfigTest.php @@ -34,11 +34,11 @@ public function test_disable_scopes(): void $exporter = new InMemoryExporter($storage); $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) - ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two + ->setConfigurator(TracerConfigurator::builder()->addCondition(new Predicate\Name('~B~'), State::DISABLED)->build()) //disable tracer B ->build(); - $tracerA = $tracerProvider->getTracer('one'); - $tracerB = $tracerProvider->getTracer('two'); - $tracerC = $tracerProvider->getTracer('three'); + $tracerA = $tracerProvider->getTracer('A'); + $tracerB = $tracerProvider->getTracer('B'); + $tracerC = $tracerProvider->getTracer('C'); $parent = $tracerA->spanBuilder('parent')->startSpan(); $this->assertTrue($parent->isRecording()); @@ -86,11 +86,15 @@ public function test_disable_scope_then_enable(): void $exporter = new InMemoryExporter($storage); $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) - ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two + ->setConfigurator( + TracerConfigurator::builder() + ->addCondition(new Predicate\Name('~B~'), State::DISABLED) //disable tracer B + ->build() + ) ->build(); - $tracerA = $tracerProvider->getTracer('one'); - $tracerB = $tracerProvider->getTracer('two'); - $tracerC = $tracerProvider->getTracer('three'); + $tracerA = $tracerProvider->getTracer('A'); + $tracerB = $tracerProvider->getTracer('B'); + $tracerC = $tracerProvider->getTracer('C'); $parent = $tracerA->spanBuilder('parent')->startSpan(); $this->assertTrue($parent->isRecording()); @@ -147,7 +151,7 @@ public function test_disable_scope_then_enable(): void public function test_conditions(Predicate $predicate, State $state, bool $expectDisabled): void { $tracerProvider = TracerProvider::builder() - ->addTracerConfiguratorCondition($predicate, $state) + ->setConfigurator(TracerConfigurator::builder()->addCondition($predicate, $state)->build()) ->build(); $tracer = $tracerProvider->getTracer(name: 'two', attributes: ['foo' => 'bar']); $span = $tracer->spanBuilder('span')->startSpan(); @@ -175,7 +179,11 @@ public static function conditionsProvider(): array public function test_enable_after_disable(): void { $tracerProvider = TracerProvider::builder() - ->addTracerConfiguratorCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer two + ->setConfigurator( + TracerConfigurator::builder() + ->addCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer A + ->build() + ) ->build(); $tracer = $tracerProvider->getTracer(name: 'two'); $this->assertInstanceOf(Tracer::class, $tracer); From 8c6fb99a32e19862c251cbecdf6a84b9343e8376 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Fri, 19 Jul 2024 16:55:51 +1000 Subject: [PATCH 08/36] consolidate configurators and config --- .../InstrumentationScope/Config.php} | 6 +-- .../InstrumentationScope/Configurator.php} | 18 ++++---- .../ConfiguratorBuilder.php | 23 +++++++++++ src/SDK/Logs/Logger.php | 7 ++-- src/SDK/Logs/LoggerConfig.php | 24 ----------- src/SDK/Logs/LoggerProvider.php | 7 ++-- src/SDK/Logs/LoggerProviderBuilder.php | 11 +++-- src/SDK/Metrics/Meter.php | 3 +- src/SDK/Metrics/MeterProvider.php | 7 ++-- src/SDK/Metrics/MeterProviderBuilder.php | 11 +++-- src/SDK/Metrics/ObservableInstrumentTrait.php | 5 ++- .../Metrics/SynchronousInstrumentTrait.php | 5 ++- src/SDK/Trace/NoopTracerProvider.php | 3 +- src/SDK/Trace/Tracer.php | 10 +++-- src/SDK/Trace/TracerConfigurator.php | 37 ----------------- src/SDK/Trace/TracerConfiguratorBuilder.php | 27 ------------ src/SDK/Trace/TracerProvider.php | 9 ++-- src/SDK/Trace/TracerProviderBuilder.php | 5 ++- src/SDK/Trace/TracerProviderInterface.php | 3 +- tests/Unit/SDK/Logs/LoggerConfigTest.php | 41 ------------------- tests/Unit/SDK/Logs/LoggerProviderTest.php | 39 +++++++++++++++--- tests/Unit/SDK/Metrics/InstrumentTest.php | 6 +-- tests/Unit/SDK/Metrics/MeterConfigTest.php | 8 +++- tests/Unit/SDK/Trace/TracerConfigTest.php | 21 +++++----- 24 files changed, 136 insertions(+), 200 deletions(-) rename src/SDK/{Trace/TracerConfig.php => Common/InstrumentationScope/Config.php} (74%) rename src/SDK/{Logs/LoggerConfigurator.php => Common/InstrumentationScope/Configurator.php} (60%) create mode 100644 src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php delete mode 100644 src/SDK/Logs/LoggerConfig.php delete mode 100644 src/SDK/Trace/TracerConfigurator.php delete mode 100644 src/SDK/Trace/TracerConfiguratorBuilder.php delete mode 100644 tests/Unit/SDK/Logs/LoggerConfigTest.php diff --git a/src/SDK/Trace/TracerConfig.php b/src/SDK/Common/InstrumentationScope/Config.php similarity index 74% rename from src/SDK/Trace/TracerConfig.php rename to src/SDK/Common/InstrumentationScope/Config.php index 039acfe22..8d7af0a21 100644 --- a/src/SDK/Trace/TracerConfig.php +++ b/src/SDK/Common/InstrumentationScope/Config.php @@ -2,14 +2,12 @@ declare(strict_types=1); -namespace OpenTelemetry\SDK\Trace; - -use OpenTelemetry\SDK\Common\InstrumentationScope\State; +namespace OpenTelemetry\SDK\Common\InstrumentationScope; /** * @internal */ -class TracerConfig +class Config { public function __construct(private readonly State $state = State::ENABLED) { diff --git a/src/SDK/Logs/LoggerConfigurator.php b/src/SDK/Common/InstrumentationScope/Configurator.php similarity index 60% rename from src/SDK/Logs/LoggerConfigurator.php rename to src/SDK/Common/InstrumentationScope/Configurator.php index e38e2bb3a..8d4d2ad66 100644 --- a/src/SDK/Logs/LoggerConfigurator.php +++ b/src/SDK/Common/InstrumentationScope/Configurator.php @@ -2,15 +2,14 @@ declare(strict_types=1); -namespace OpenTelemetry\SDK\Logs; +namespace OpenTelemetry\SDK\Common\InstrumentationScope; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; /** - * @experimental + * @internal */ -class LoggerConfigurator +class Configurator { /** * @param list $conditions @@ -19,14 +18,19 @@ public function __construct(private readonly array $conditions = []) { } - public function getConfig(InstrumentationScopeInterface $scope): LoggerConfig + public function getConfig(InstrumentationScopeInterface $scope): Config { foreach ($this->conditions as $condition) { if ($condition->match($scope)) { - return new LoggerConfig($condition->state()); + return new Config($condition->state()); } } - return LoggerConfig::default(); + return Config::default(); + } + + public static function builder(): ConfiguratorBuilder + { + return new ConfiguratorBuilder(); } } diff --git a/src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php b/src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php new file mode 100644 index 000000000..674fdd519 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php @@ -0,0 +1,23 @@ + */ + private array $conditions = []; + + public function addCondition(Predicate $predicate, State $state): ConfiguratorBuilder + { + $this->conditions[] = new Condition($predicate, $state); + + return $this; + } + + public function build(): Configurator + { + return new Configurator($this->conditions); + } +} diff --git a/src/SDK/Logs/Logger.php b/src/SDK/Logs/Logger.php index 0327c5c0c..71e4ff50e 100644 --- a/src/SDK/Logs/Logger.php +++ b/src/SDK/Logs/Logger.php @@ -8,6 +8,7 @@ use OpenTelemetry\API\Logs\LoggerInterface; use OpenTelemetry\API\Logs\LogRecord; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; /** * Note that this logger class is deliberately NOT psr-3 compatible, per spec: "Note: this document defines a log @@ -18,7 +19,7 @@ class Logger implements LoggerInterface { use LogsMessagesTrait; - private readonly LoggerConfig $config; + private readonly Config $config; /** * @internal @@ -26,9 +27,9 @@ class Logger implements LoggerInterface public function __construct( private readonly LoggerSharedState $loggerSharedState, private readonly InstrumentationScopeInterface $scope, - ?LoggerConfig $config = null, + ?Config $config = null, ) { - $this->config = $config ?? LoggerConfig::default(); + $this->config = $config ?? Config::default(); } public function emit(LogRecord $logRecord): void diff --git a/src/SDK/Logs/LoggerConfig.php b/src/SDK/Logs/LoggerConfig.php deleted file mode 100644 index b21ee6548..000000000 --- a/src/SDK/Logs/LoggerConfig.php +++ /dev/null @@ -1,24 +0,0 @@ -state === State::ENABLED; - } - - public static function default(): self - { - return new self(); - } -} diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index 67179d71a..3d43e3541 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -8,26 +8,27 @@ 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; class LoggerProvider implements LoggerProviderInterface { private readonly LoggerSharedState $loggerSharedState; - private readonly LoggerConfigurator $configurator; + private readonly Configurator $configurator; public function __construct( LogRecordProcessorInterface $processor, private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null, - ?LoggerConfigurator $configurator = null, + ?Configurator $configurator = null, ) { $this->loggerSharedState = new LoggerSharedState( $resource ?? ResourceInfoFactory::defaultResource(), (new LogRecordLimitsBuilder())->build(), $processor ); - $this->configurator = $configurator ?? new LoggerConfigurator(); + $this->configurator = $configurator ?? new Configurator(); } /** diff --git a/src/SDK/Logs/LoggerProviderBuilder.php b/src/SDK/Logs/LoggerProviderBuilder.php index 2de193ce6..ea6744665 100644 --- a/src/SDK/Logs/LoggerProviderBuilder.php +++ b/src/SDK/Logs/LoggerProviderBuilder.php @@ -6,7 +6,7 @@ use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; -use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Logs\Processor\MultiLogRecordProcessor; use OpenTelemetry\SDK\Logs\Processor\NoopLogRecordProcessor; use OpenTelemetry\SDK\Resource\ResourceInfo; @@ -16,8 +16,7 @@ class LoggerProviderBuilder /** @var array */ private array $processors = []; private ?ResourceInfo $resource = null; - /** @var list */ - private array $conditions = []; + private ?Configurator $configurator = null; public function addLogRecordProcessor(LogRecordProcessorInterface $processor): self { @@ -39,13 +38,13 @@ public function build(): LoggerProviderInterface $this->buildProcessor(), new InstrumentationScopeFactory(Attributes::factory()), $this->resource, - configurator: new LoggerConfigurator($this->conditions), + configurator: $this->configurator, ); } - public function addLoggerConfiguratorCondition(Condition $condition): self + public function setConfigurator(Configurator $configurator): self { - $this->conditions[] = $condition; + $this->configurator = $configurator; return $this; } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index 671046153..0d314cb53 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -22,6 +22,7 @@ use OpenTelemetry\API\Metrics\ObservableUpDownCounterInterface; use OpenTelemetry\API\Metrics\UpDownCounterInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use function OpenTelemetry\SDK\Common\Util\closure; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface; use OpenTelemetry\SDK\Metrics\MetricRegistration\MultiRegistryRegistration; @@ -59,7 +60,7 @@ public function __construct( private readonly MetricRegistryInterface $registry, private readonly MetricWriterInterface $writer, private readonly ArrayAccess $destructors, - private readonly MeterConfig $config, + private readonly Config $config, ) { $this->noop = new NoopMeter(); } diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index d00984ec5..f4ecb7e1c 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -11,6 +11,7 @@ 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,7 +30,7 @@ final class MeterProvider implements MeterProviderInterface private readonly ArrayAccess $destructors; private bool $closed = false; - private readonly MeterConfigurator $configurator; + private readonly Configurator $configurator; /** * @param iterable $metricReaders @@ -45,7 +46,7 @@ public function __construct( private readonly ?ExemplarFilterInterface $exemplarFilter, private readonly StalenessHandlerFactoryInterface $stalenessHandlerFactory, MetricFactoryInterface $metricFactory = null, - ?MeterConfigurator $configurator = null, + ?Configurator $configurator = null, ) { $this->metricFactory = $metricFactory ?? new StreamFactory(); $this->instruments = new MeterInstruments(); @@ -54,7 +55,7 @@ public function __construct( $this->registry = $registry; $this->writer = $registry; $this->destructors = new WeakMap(); - $this->configurator = $configurator ?? new MeterConfigurator(); + $this->configurator = $configurator ?? new Configurator(); } public function getMeter( diff --git a/src/SDK/Metrics/MeterProviderBuilder.php b/src/SDK/Metrics/MeterProviderBuilder.php index 401ef336c..ebaf91c2a 100644 --- a/src/SDK/Metrics/MeterProviderBuilder.php +++ b/src/SDK/Metrics/MeterProviderBuilder.php @@ -7,7 +7,7 @@ use OpenTelemetry\API\Common\Time\Clock; use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; -use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; +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; @@ -21,8 +21,7 @@ class MeterProviderBuilder private array $metricReaders = []; private ?ResourceInfo $resource = null; private ?ExemplarFilterInterface $exemplarFilter = null; - /** @var list */ - private array $conditions = []; + private ?Configurator $configurator = null; public function setResource(ResourceInfo $resource): self { @@ -45,9 +44,9 @@ public function addReader(MetricReaderInterface $reader): self return $this; } - public function addMeterConfiguratorCondition(Condition $condition): self + public function setConfigurator(Configurator $configurator): self { - $this->conditions[] = $condition; + $this->configurator = $configurator; return $this; } @@ -67,7 +66,7 @@ public function build(): MeterProviderInterface new CriteriaViewRegistry(), $this->exemplarFilter ?? new WithSampledTraceExemplarFilter(), new NoopStalenessHandlerFactory(), - configurator: new MeterConfigurator($this->conditions), + configurator: $this->configurator, ); } } diff --git a/src/SDK/Metrics/ObservableInstrumentTrait.php b/src/SDK/Metrics/ObservableInstrumentTrait.php index 03d7da76a..0a4aba6ec 100644 --- a/src/SDK/Metrics/ObservableInstrumentTrait.php +++ b/src/SDK/Metrics/ObservableInstrumentTrait.php @@ -8,6 +8,7 @@ use function assert; use OpenTelemetry\API\Metrics\ObservableCallbackInterface; use OpenTelemetry\API\Metrics\ObserverInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; /** @@ -19,14 +20,14 @@ trait ObservableInstrumentTrait private Instrument $instrument; private ReferenceCounterInterface $referenceCounter; private ArrayAccess $destructors; - private MeterConfig $config; + private Config $config; public function __construct( MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, ArrayAccess $destructors, - MeterConfig $config, + Config $config, ) { assert($this instanceof InstrumentHandle); diff --git a/src/SDK/Metrics/SynchronousInstrumentTrait.php b/src/SDK/Metrics/SynchronousInstrumentTrait.php index 136723d11..231fbfb97 100644 --- a/src/SDK/Metrics/SynchronousInstrumentTrait.php +++ b/src/SDK/Metrics/SynchronousInstrumentTrait.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\SDK\Metrics; use function assert; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; /** @@ -15,9 +16,9 @@ trait SynchronousInstrumentTrait private MetricWriterInterface $writer; private Instrument $instrument; private ReferenceCounterInterface $referenceCounter; - private MeterConfig $config; + private Config $config; - public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, MeterConfig $config) + public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, Config $config) { assert($this instanceof InstrumentHandle); diff --git a/src/SDK/Trace/NoopTracerProvider.php b/src/SDK/Trace/NoopTracerProvider.php index 5ad6ab92b..e29edbf8a 100644 --- a/src/SDK/Trace/NoopTracerProvider.php +++ b/src/SDK/Trace/NoopTracerProvider.php @@ -6,6 +6,7 @@ use OpenTelemetry\API; use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; class NoopTracerProvider extends API\Trace\NoopTracerProvider implements TracerProviderInterface { @@ -19,7 +20,7 @@ public function shutdown(?CancellationInterface $cancellation = null): bool return true; } - public function updateConfigurator(TracerConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { } } diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index 7582208f8..935cb1b9f 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -8,18 +8,20 @@ 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 TracerConfig $config; + private Config $config; public function __construct( private readonly TracerSharedState $tracerSharedState, private readonly InstrumentationScopeInterface $instrumentationScope, - ?TracerConfig $config = null, + ?Config $config = null, ) { - $this->config = $config ?? TracerConfig::default(); + $this->config = $config ?? Config::default(); } /** @inheritDoc */ @@ -49,7 +51,7 @@ public function enabled(): bool return $this->config->isEnabled(); } - public function updateConfig(TracerConfigurator $configurator): void + public function updateConfig(Configurator $configurator): void { $this->config = $configurator->getConfig($this->instrumentationScope); } diff --git a/src/SDK/Trace/TracerConfigurator.php b/src/SDK/Trace/TracerConfigurator.php deleted file mode 100644 index 365053acf..000000000 --- a/src/SDK/Trace/TracerConfigurator.php +++ /dev/null @@ -1,37 +0,0 @@ - $conditions - */ - public function __construct(private readonly array $conditions = []) - { - } - - public function getConfig(InstrumentationScopeInterface $scope): TracerConfig - { - foreach ($this->conditions as $condition) { - if ($condition->match($scope)) { - return new TracerConfig($condition->state()); - } - } - - return TracerConfig::default(); - } - - public static function builder(): TracerConfiguratorBuilder - { - return new TracerConfiguratorBuilder(); - } -} diff --git a/src/SDK/Trace/TracerConfiguratorBuilder.php b/src/SDK/Trace/TracerConfiguratorBuilder.php deleted file mode 100644 index 897a73b92..000000000 --- a/src/SDK/Trace/TracerConfiguratorBuilder.php +++ /dev/null @@ -1,27 +0,0 @@ - */ - private array $conditions = []; - - public function addCondition(Predicate $predicate, State $state): TracerConfiguratorBuilder - { - $this->conditions[] = new Condition($predicate, $state); - - return $this; - } - - public function build(): TracerConfigurator - { - return new TracerConfigurator($this->conditions); - } -} diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index fa7f755bb..3b595a16d 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -11,6 +11,7 @@ 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; @@ -21,7 +22,7 @@ final class TracerProvider implements TracerProviderInterface { private readonly TracerSharedState $tracerSharedState; private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory; - private TracerConfigurator $configurator; + private Configurator $configurator; private WeakMap $tracers; /** @param list|SpanProcessorInterface|null $spanProcessors */ @@ -32,7 +33,7 @@ public function __construct( SpanLimits $spanLimits = null, IdGeneratorInterface $idGenerator = null, ?InstrumentationScopeFactoryInterface $instrumentationScopeFactory = null, - ?TracerConfigurator $configurator = null, + ?Configurator $configurator = null, ) { $spanProcessors ??= []; $spanProcessors = is_array($spanProcessors) ? $spanProcessors : [$spanProcessors]; @@ -49,7 +50,7 @@ public function __construct( $spanProcessors ); $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); - $this->configurator = $configurator ?? new TracerConfigurator(); + $this->configurator = $configurator ?? new Configurator(); $this->tracers = new WeakMap(); } @@ -104,7 +105,7 @@ public static function builder(): TracerProviderBuilder return new TracerProviderBuilder(); } - public function updateConfigurator(TracerConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; diff --git a/src/SDK/Trace/TracerProviderBuilder.php b/src/SDK/Trace/TracerProviderBuilder.php index 409a26809..583fdf6ef 100644 --- a/src/SDK/Trace/TracerProviderBuilder.php +++ b/src/SDK/Trace/TracerProviderBuilder.php @@ -4,6 +4,7 @@ namespace OpenTelemetry\SDK\Trace; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Resource\ResourceInfo; class TracerProviderBuilder @@ -12,7 +13,7 @@ class TracerProviderBuilder private ?array $spanProcessors = []; private ?ResourceInfo $resource = null; private ?SamplerInterface $sampler = null; - private ?TracerConfigurator $configurator = null; + private ?Configurator $configurator = null; public function addSpanProcessor(SpanProcessorInterface $spanProcessor): self { @@ -35,7 +36,7 @@ public function setSampler(SamplerInterface $sampler): self return $this; } - public function setConfigurator(TracerConfigurator $configurator): self + public function setConfigurator(Configurator $configurator): self { $this->configurator = $configurator; diff --git a/src/SDK/Trace/TracerProviderInterface.php b/src/SDK/Trace/TracerProviderInterface.php index 937191b2f..aa6ae8d3a 100644 --- a/src/SDK/Trace/TracerProviderInterface.php +++ b/src/SDK/Trace/TracerProviderInterface.php @@ -6,6 +6,7 @@ use OpenTelemetry\API\Trace as API; use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; interface TracerProviderInterface extends API\TracerProviderInterface { @@ -13,5 +14,5 @@ public function forceFlush(?CancellationInterface $cancellation = null): bool; public function shutdown(?CancellationInterface $cancellation = null): bool; - public function updateConfigurator(TracerConfigurator $configurator): void; + public function updateConfigurator(Configurator $configurator): void; } diff --git a/tests/Unit/SDK/Logs/LoggerConfigTest.php b/tests/Unit/SDK/Logs/LoggerConfigTest.php deleted file mode 100644 index 3484c2537..000000000 --- a/tests/Unit/SDK/Logs/LoggerConfigTest.php +++ /dev/null @@ -1,41 +0,0 @@ -addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) - ->addLoggerConfiguratorCondition(new Condition(new Name('~two~'), State::DISABLED)) //disable logger named 'two' - ->build(); - - $logger_one = $loggerProvider->getLogger('one'); - $logger_two = $loggerProvider->getLogger('two'); - $logger_three = $loggerProvider->getLogger('three'); - - $this->assertNotInstanceOf(NoopLogger::class, $logger_one); - $this->assertInstanceOf(NoopLogger::class, $logger_two); - $this->assertNotInstanceOf(NoopLogger::class, $logger_three); - } -} diff --git a/tests/Unit/SDK/Logs/LoggerProviderTest.php b/tests/Unit/SDK/Logs/LoggerProviderTest.php index 389480e49..6c7f2ea7a 100644 --- a/tests/Unit/SDK/Logs/LoggerProviderTest.php +++ b/tests/Unit/SDK/Logs/LoggerProviderTest.php @@ -4,14 +4,19 @@ namespace OpenTelemetry\Tests\Unit\SDK\Logs; +use ArrayObject; use OpenTelemetry\API\Logs\NoopLogger; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; +use OpenTelemetry\SDK\Logs\Exporter\InMemoryExporter; use OpenTelemetry\SDK\Logs\Logger; -use OpenTelemetry\SDK\Logs\LoggerConfig; -use OpenTelemetry\SDK\Logs\LoggerConfigurator; use OpenTelemetry\SDK\Logs\LoggerProvider; use OpenTelemetry\SDK\Logs\LoggerProviderBuilder; use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; +use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor; use OpenTelemetry\SDK\Resource\ResourceInfo; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; @@ -27,16 +32,16 @@ class LoggerProviderTest extends TestCase /** @var LogRecordProcessorInterface&MockObject $processor */ private LogRecordProcessorInterface $processor; private LoggerProvider $provider; - /** @var LoggerConfig&MockObject */ - private LoggerConfig $config; + /** @var Config&MockObject */ + private Config $config; public function setUp(): void { $this->processor = $this->createMock(LogRecordProcessorInterface::class); $instrumentationScopeFactory = $this->createMock(InstrumentationScopeFactoryInterface::class); $resource = $this->createMock(ResourceInfo::class); - $this->config = $this->createMock(LoggerConfig::class); - $configurator = $this->createMock(LoggerConfigurator::class); + $this->config = $this->createMock(Config::class); + $configurator = $this->createMock(Configurator::class); $configurator->method('getConfig')->willReturn($this->config); $this->provider = new LoggerProvider($this->processor, $instrumentationScopeFactory, $resource, $configurator); } @@ -78,4 +83,26 @@ public function test_builder(): void { $this->assertInstanceOf(LoggerProviderBuilder::class, $this->provider->builder()); } + + public function test_disable_with_configurator(): void + { + $storage = new ArrayObject([]); + $exporter = new InMemoryExporter($storage); + $loggerProvider = LoggerProvider::builder() + ->addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) + ->setConfigurator( + Configurator::builder() + ->addCondition(new Name('~two~'), State::DISABLED) //disable logger named 'two' + ->build() + ) + ->build(); + + $logger_one = $loggerProvider->getLogger('one'); + $logger_two = $loggerProvider->getLogger('two'); + $logger_three = $loggerProvider->getLogger('three'); + + $this->assertNotInstanceOf(NoopLogger::class, $logger_one); + $this->assertInstanceOf(NoopLogger::class, $logger_two); + $this->assertNotInstanceOf(NoopLogger::class, $logger_three); + } } diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index 90de48226..ecc4f437b 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -7,6 +7,7 @@ use OpenTelemetry\API\Common\Time\TestClock; use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\Aggregation\ExplicitBucketHistogramAggregation; use OpenTelemetry\SDK\Metrics\Aggregation\SumAggregation; use OpenTelemetry\SDK\Metrics\Counter; @@ -15,7 +16,6 @@ use OpenTelemetry\SDK\Metrics\Histogram; use OpenTelemetry\SDK\Metrics\Instrument; use OpenTelemetry\SDK\Metrics\InstrumentType; -use OpenTelemetry\SDK\Metrics\MeterConfig; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricRegistry; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; use OpenTelemetry\SDK\Metrics\ObservableCallback; @@ -41,11 +41,11 @@ #[CoversClass(ObservableInstrumentTrait::class)] final class InstrumentTest extends TestCase { - private MeterConfig $config; + private Config $config; public function setUp(): void { - $this->config = MeterConfig::default(); + $this->config = Config::default(); } public function test_counter(): void diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Unit/SDK/Metrics/MeterConfigTest.php index 3e2301229..0a6bdac9c 100644 --- a/tests/Unit/SDK/Metrics/MeterConfigTest.php +++ b/tests/Unit/SDK/Metrics/MeterConfigTest.php @@ -11,7 +11,7 @@ use OpenTelemetry\API\Metrics\Noop\NoopObservableGauge; use OpenTelemetry\API\Metrics\Noop\NoopObservableUpDownCounter; use OpenTelemetry\API\Metrics\Noop\NoopUpDownCounter; -use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Metrics\MeterConfig; @@ -27,7 +27,11 @@ class MeterConfigTest extends TestCase public function test_disable_scopes(): void { $meterProvider = MeterProvider::builder() - ->addMeterConfiguratorCondition(new Condition(new Name('~two~'), State::DISABLED)) //meter two disabled + ->setConfigurator( + Configurator::builder() + ->addCondition(new Name('~two~'), State::DISABLED) + ->build() + ) ->build(); $meter_one = $meterProvider->getMeter('one'); diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Unit/SDK/Trace/TracerConfigTest.php index 1a8bef8c5..5ea083c76 100644 --- a/tests/Unit/SDK/Trace/TracerConfigTest.php +++ b/tests/Unit/SDK/Trace/TracerConfigTest.php @@ -7,21 +7,20 @@ use ArrayObject; use OpenTelemetry\API\Trace\NonRecordingSpan; use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; use OpenTelemetry\SDK\Common\InstrumentationScope\State; -use OpenTelemetry\SDK\Trace\ImmutableSpan; 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\TracerConfigurator; use OpenTelemetry\SDK\Trace\TracerProvider; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -#[CoversClass(TracerConfig::class)] -#[CoversClass(TracerConfigurator::class)] +#[CoversClass(Config::class)] +#[CoversClass(Configurator::class)] #[CoversClass(Predicate\Attribute::class)] #[CoversClass(Predicate\AttributeExists::class)] #[CoversClass(Predicate\Name::class)] @@ -34,7 +33,7 @@ public function test_disable_scopes(): void $exporter = new InMemoryExporter($storage); $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) - ->setConfigurator(TracerConfigurator::builder()->addCondition(new Predicate\Name('~B~'), State::DISABLED)->build()) //disable tracer B + ->setConfigurator(Configurator::builder()->addCondition(new Predicate\Name('~B~'), State::DISABLED)->build()) //disable tracer B ->build(); $tracerA = $tracerProvider->getTracer('A'); $tracerB = $tracerProvider->getTracer('B'); @@ -87,7 +86,7 @@ public function test_disable_scope_then_enable(): void $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) ->setConfigurator( - TracerConfigurator::builder() + Configurator::builder() ->addCondition(new Predicate\Name('~B~'), State::DISABLED) //disable tracer B ->build() ) @@ -105,7 +104,7 @@ public function test_disable_scope_then_enable(): void $child = $tracerB->spanBuilder('child')->startSpan(); $child->setAttribute('b', 1); $childScope = $child->activate(); - $tracerProvider->updateConfigurator(new TracerConfigurator()); //re-enable tracer two + $tracerProvider->updateConfigurator(new Configurator()); //re-enable tracer two $sibling = $tracerB->spanBuilder('sibling')->startSpan(); $siblingScope = $sibling->activate(); @@ -151,7 +150,7 @@ public function test_disable_scope_then_enable(): void public function test_conditions(Predicate $predicate, State $state, bool $expectDisabled): void { $tracerProvider = TracerProvider::builder() - ->setConfigurator(TracerConfigurator::builder()->addCondition($predicate, $state)->build()) + ->setConfigurator(Configurator::builder()->addCondition($predicate, $state)->build()) ->build(); $tracer = $tracerProvider->getTracer(name: 'two', attributes: ['foo' => 'bar']); $span = $tracer->spanBuilder('span')->startSpan(); @@ -180,7 +179,7 @@ public function test_enable_after_disable(): void { $tracerProvider = TracerProvider::builder() ->setConfigurator( - TracerConfigurator::builder() + Configurator::builder() ->addCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer A ->build() ) @@ -189,7 +188,7 @@ public function test_enable_after_disable(): void $this->assertInstanceOf(Tracer::class, $tracer); $this->assertFalse($tracer->enabled()); - $update = new TracerConfigurator(); + $update = new Configurator(); $tracerProvider->updateConfigurator($update); $this->assertTrue($tracer->enabled()); From 776f87a1a0555415ea38aa1f8fbcef7aa1dfbefa Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 20 Jul 2024 16:39:50 +1000 Subject: [PATCH 09/36] metrics reconfig --- src/SDK/Metrics/Meter.php | 65 ++++++++++--------- src/SDK/Metrics/MeterProvider.php | 24 +++++-- src/SDK/Metrics/ObservableInstrumentTrait.php | 27 +++----- .../Metrics/SynchronousInstrumentTrait.php | 9 ++- tests/Unit/SDK/Metrics/MeterConfigTest.php | 36 ++++++---- tests/Unit/SDK/Metrics/MeterProviderTest.php | 18 +++++ 6 files changed, 112 insertions(+), 67 deletions(-) diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index 0d314cb53..10e4c4ae9 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -15,7 +15,6 @@ use OpenTelemetry\API\Metrics\GaugeInterface; use OpenTelemetry\API\Metrics\HistogramInterface; use OpenTelemetry\API\Metrics\MeterInterface; -use OpenTelemetry\API\Metrics\Noop\NoopMeter; use OpenTelemetry\API\Metrics\ObservableCallbackInterface; use OpenTelemetry\API\Metrics\ObservableCounterInterface; use OpenTelemetry\API\Metrics\ObservableGaugeInterface; @@ -23,6 +22,7 @@ use OpenTelemetry\API\Metrics\UpDownCounterInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; +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; @@ -32,6 +32,7 @@ use OpenTelemetry\SDK\Metrics\StalenessHandler\MultiReferenceCounter; use OpenTelemetry\SDK\Resource\ResourceInfo; use function serialize; +use WeakMap; /** * @internal @@ -41,7 +42,8 @@ final class Meter implements MeterInterface use LogsMessagesTrait; private ?string $instrumentationScopeId = null; - private NoopMeter $noop; + private Config $config; + private WeakMap $instrumentsMap; /** * @param iterable $metricRegistries @@ -60,9 +62,10 @@ public function __construct( private readonly MetricRegistryInterface $registry, private readonly MetricWriterInterface $writer, private readonly ArrayAccess $destructors, - private readonly Config $config, + private Configurator $configurator, ) { - $this->noop = new NoopMeter(); + $this->instrumentsMap = new WeakMap(); + $this->config = $this->configurator->getConfig($this->instrumentationScope); } private static function dummyInstrument(): Instrument @@ -72,6 +75,19 @@ private static function dummyInstrument(): Instrument return $dummy ??= (new \ReflectionClass(Instrument::class))->newInstanceWithoutConstructor(); } + /** + * @internal + */ + public function updateConfigurator(Configurator $configurator): void + { + $this->configurator = $configurator; + $this->config = $configurator->getConfig($this->instrumentationScope); + + foreach ($this->instrumentsMap as $instrument) { + $instrument->updateConfig($this->config); + } + } + public function batchObserve(callable $callback, AsynchronousInstrument $instrument, AsynchronousInstrument ...$instruments): ObservableCallbackInterface { $referenceCounters = []; @@ -113,9 +129,6 @@ public function batchObserve(callable $callback, AsynchronousInstrument $instrum public function createCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): CounterInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createCounter($name); - } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::COUNTER, $name, @@ -124,14 +137,14 @@ public function createCounter(string $name, ?string $unit = null, ?string $descr $advisory, ); - return new Counter($this->writer, $instrument, $referenceCounter, $this->config); + $counter = new Counter($this->writer, $instrument, $referenceCounter, $this->config); + $this->instrumentsMap->offsetSet($counter, $counter); + + return $counter; } public function createObservableCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableCounterInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createObservableCounter($name); - } if (is_callable($advisory)) { array_unshift($callbacks, $advisory); $advisory = []; @@ -154,9 +167,6 @@ public function createObservableCounter(string $name, ?string $unit = null, ?str public function createHistogram(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): HistogramInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createHistogram($name); - } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::HISTOGRAM, $name, @@ -165,14 +175,14 @@ public function createHistogram(string $name, ?string $unit = null, ?string $des $advisory, ); - return new Histogram($this->writer, $instrument, $referenceCounter, $this->config); + $histogram = new Histogram($this->writer, $instrument, $referenceCounter, $this->config); + $this->instrumentsMap->offsetSet($histogram, $histogram); + + return $histogram; } public function createGauge(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): GaugeInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createGauge($name); - } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::GAUGE, $name, @@ -181,14 +191,14 @@ public function createGauge(string $name, ?string $unit = null, ?string $descrip $advisory, ); - return new Gauge($this->writer, $instrument, $referenceCounter, $this->config); + $gauge = new Gauge($this->writer, $instrument, $referenceCounter, $this->config); + $this->instrumentsMap->offsetSet($gauge, $gauge); + + return $gauge; } public function createObservableGauge(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableGaugeInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createObservableGauge($name); - } if (is_callable($advisory)) { array_unshift($callbacks, $advisory); $advisory = []; @@ -211,9 +221,6 @@ public function createObservableGauge(string $name, ?string $unit = null, ?strin public function createUpDownCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): UpDownCounterInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createUpDownCounter($name); - } [$instrument, $referenceCounter] = $this->createSynchronousWriter( InstrumentType::UP_DOWN_COUNTER, $name, @@ -222,14 +229,14 @@ public function createUpDownCounter(string $name, ?string $unit = null, ?string $advisory, ); - return new UpDownCounter($this->writer, $instrument, $referenceCounter, $this->config); + $counter = new UpDownCounter($this->writer, $instrument, $referenceCounter, $this->config); + $this->instrumentsMap->offsetSet($counter, $counter); + + return $counter; } public function createObservableUpDownCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableUpDownCounterInterface { - if ($this->config->isEnabled() === false) { - return $this->noop->createObservableUpDownCounter($name); - } if (is_callable($advisory)) { array_unshift($callbacks, $advisory); $advisory = []; diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index f4ecb7e1c..aa0e07890 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -30,7 +30,8 @@ final class MeterProvider implements MeterProviderInterface private readonly ArrayAccess $destructors; private bool $closed = false; - private readonly Configurator $configurator; + private Configurator $configurator; + private WeakMap $meters; /** * @param iterable $metricReaders @@ -56,6 +57,7 @@ public function __construct( $this->writer = $registry; $this->destructors = new WeakMap(); $this->configurator = $configurator ?? new Configurator(); + $this->meters = new WeakMap(); } public function getMeter( @@ -68,9 +70,7 @@ public function getMeter( return new NoopMeter(); } - $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); - - return new Meter( + $meter = new Meter( $this->metricFactory, $this->resource, $this->clock, @@ -79,12 +79,15 @@ public function getMeter( $this->viewRegistry, $this->exemplarFilter, $this->instruments, - $scope, + $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes), $this->registry, $this->writer, $this->destructors, - $this->configurator->getConfig($scope), + $this->configurator, ); + $this->meters->offsetSet($meter, $meter); + + return $meter; } public function shutdown(): bool @@ -125,4 +128,13 @@ public static function builder(): MeterProviderBuilder { return new MeterProviderBuilder(); } + + public function updateConfigurator(Configurator $configurator): void + { + $this->configurator = $configurator; + + foreach ($this->meters as $meter) { + $meter->updateConfigurator($configurator); + } + } } diff --git a/src/SDK/Metrics/ObservableInstrumentTrait.php b/src/SDK/Metrics/ObservableInstrumentTrait.php index fcc4fbccd..e8de2ae15 100644 --- a/src/SDK/Metrics/ObservableInstrumentTrait.php +++ b/src/SDK/Metrics/ObservableInstrumentTrait.php @@ -16,27 +16,15 @@ */ trait ObservableInstrumentTrait { - private MetricWriterInterface $writer; - private Instrument $instrument; - private ReferenceCounterInterface $referenceCounter; - private ArrayAccess $destructors; - private Config $config; - public function __construct( - MetricWriterInterface $writer, - Instrument $instrument, - ReferenceCounterInterface $referenceCounter, - ArrayAccess $destructors, - Config $config, + private readonly MetricWriterInterface $writer, + private readonly Instrument $instrument, + private readonly ReferenceCounterInterface $referenceCounter, + private readonly ArrayAccess $destructors, + private Config $config, ) { assert($this instanceof InstrumentHandle); - $this->writer = $writer; - $this->instrument = $instrument; - $this->referenceCounter = $referenceCounter; - $this->destructors = $destructors; - $this->config = $config; - $this->referenceCounter->acquire(); } @@ -68,4 +56,9 @@ public function enabled(): bool { return $this->writer->enabled($this->instrument); } + + public function updateConfig(Config $config): void + { + $this->config = $config; + } } diff --git a/src/SDK/Metrics/SynchronousInstrumentTrait.php b/src/SDK/Metrics/SynchronousInstrumentTrait.php index 231fbfb97..a27f4a952 100644 --- a/src/SDK/Metrics/SynchronousInstrumentTrait.php +++ b/src/SDK/Metrics/SynchronousInstrumentTrait.php @@ -42,11 +42,18 @@ public function getHandle(): Instrument public function write($amount, iterable $attributes = [], $context = null): void { - $this->writer->record($this->instrument, $amount, $attributes, $context); + if ($this->enabled()) { + $this->writer->record($this->instrument, $amount, $attributes, $context); + } } public function enabled(): bool { return $this->config->isEnabled(); } + + public function updateConfig(Config $config): void + { + $this->config = $config; + } } diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Unit/SDK/Metrics/MeterConfigTest.php index 0a6bdac9c..263c4d4f6 100644 --- a/tests/Unit/SDK/Metrics/MeterConfigTest.php +++ b/tests/Unit/SDK/Metrics/MeterConfigTest.php @@ -4,13 +4,6 @@ namespace OpenTelemetry\Tests\Unit\SDK\Metrics; -use OpenTelemetry\API\Metrics\Noop\NoopCounter; -use OpenTelemetry\API\Metrics\Noop\NoopGauge; -use OpenTelemetry\API\Metrics\Noop\NoopHistogram; -use OpenTelemetry\API\Metrics\Noop\NoopObservableCounter; -use OpenTelemetry\API\Metrics\Noop\NoopObservableGauge; -use OpenTelemetry\API\Metrics\Noop\NoopObservableUpDownCounter; -use OpenTelemetry\API\Metrics\Noop\NoopUpDownCounter; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; use OpenTelemetry\SDK\Common\InstrumentationScope\State; @@ -34,20 +27,35 @@ public function test_disable_scopes(): void ) ->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 $instrument) { + $this->assertFalse($instrument->enabled()); + } + $this->assertTrue($meter_one->isEnabled()); $this->assertFalse($meter_two->isEnabled()); $this->assertTrue($meter_three->isEnabled()); - $this->assertInstanceOf(NoopCounter::class, $meter_two->createCounter('a')); - $this->assertInstanceOf(NoopObservableCounter::class, $meter_two->createObservableCounter('b')); - $this->assertInstanceOf(NoopUpDownCounter::class, $meter_two->createUpDownCounter('c')); - $this->assertInstanceOf(NoopObservableUpDownCounter::class, $meter_two->createObservableUpDownCounter('d')); - $this->assertInstanceOf(NoopHistogram::class, $meter_two->createHistogram('e')); - $this->assertInstanceOf(NoopGauge::class, $meter_two->createGauge('f')); - $this->assertInstanceOf(NoopObservableGauge::class, $meter_two->createObservableGauge('g')); + $meterProvider->updateConfigurator(new Configurator()); + + $this->assertTrue($meter_two->isEnabled()); + + foreach ($instruments as $instrument) { + $this->assertTrue($instrument->enabled()); + } } } diff --git a/tests/Unit/SDK/Metrics/MeterProviderTest.php b/tests/Unit/SDK/Metrics/MeterProviderTest.php index df551d9d8..03b22c95a 100644 --- a/tests/Unit/SDK/Metrics/MeterProviderTest.php +++ b/tests/Unit/SDK/Metrics/MeterProviderTest.php @@ -10,8 +10,13 @@ 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\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface; 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 +109,19 @@ public function test_force_flush_calls_metric_reader_force_flush(): void ); $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->enabled()); + $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('~one~'), State::DISABLED)->build()); + $this->assertFalse($meter->isEnabled()); + $this->assertFalse($counter->enabled()); + } } interface MetricReaderSourceRegistryInterface extends MetricReaderInterface, MetricSourceRegistryInterface, DefaultAggregationProviderInterface From 3c8cd17870b5780fe9bbeb7e90d4f8df8d003f20 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 20 Jul 2024 16:43:15 +1000 Subject: [PATCH 10/36] gauge enabled --- src/API/Metrics/GaugeInterface.php | 2 +- src/API/Metrics/Noop/NoopGauge.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/API/Metrics/GaugeInterface.php b/src/API/Metrics/GaugeInterface.php index 9ae8e4276..6bb62cd28 100644 --- a/src/API/Metrics/GaugeInterface.php +++ b/src/API/Metrics/GaugeInterface.php @@ -13,7 +13,7 @@ * * @experimental */ -interface GaugeInterface +interface GaugeInterface extends SynchronousInstrument { /** diff --git a/src/API/Metrics/Noop/NoopGauge.php b/src/API/Metrics/Noop/NoopGauge.php index 5884b522f..f8409f1e3 100644 --- a/src/API/Metrics/Noop/NoopGauge.php +++ b/src/API/Metrics/Noop/NoopGauge.php @@ -15,4 +15,9 @@ public function record(float|int $amount, iterable $attributes = [], $context = { // no-op } + + public function enabled(): bool + { + return false; + } } From 46c5730a4c48a82b60956ea45621e0894e6ac32b Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 20 Jul 2024 16:43:59 +1000 Subject: [PATCH 11/36] rector --- src/SDK/Logs/LoggerProvider.php | 4 +--- src/SDK/Metrics/MeterProvider.php | 6 ++---- src/SDK/Trace/TracerProvider.php | 6 ++---- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index 3d43e3541..4f2bb018a 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -15,20 +15,18 @@ class LoggerProvider implements LoggerProviderInterface { private readonly LoggerSharedState $loggerSharedState; - private readonly Configurator $configurator; public function __construct( LogRecordProcessorInterface $processor, private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null, - ?Configurator $configurator = null, + private readonly Configurator $configurator = new Configurator(), ) { $this->loggerSharedState = new LoggerSharedState( $resource ?? ResourceInfoFactory::defaultResource(), (new LogRecordLimitsBuilder())->build(), $processor ); - $this->configurator = $configurator ?? new Configurator(); } /** diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index aa0e07890..6cb073254 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -30,8 +30,7 @@ final class MeterProvider implements MeterProviderInterface private readonly ArrayAccess $destructors; private bool $closed = false; - private Configurator $configurator; - private WeakMap $meters; + private readonly WeakMap $meters; /** * @param iterable $metricReaders @@ -47,7 +46,7 @@ public function __construct( private readonly ?ExemplarFilterInterface $exemplarFilter, private readonly StalenessHandlerFactoryInterface $stalenessHandlerFactory, MetricFactoryInterface $metricFactory = null, - ?Configurator $configurator = null, + private Configurator $configurator = new Configurator(), ) { $this->metricFactory = $metricFactory ?? new StreamFactory(); $this->instruments = new MeterInstruments(); @@ -56,7 +55,6 @@ public function __construct( $this->registry = $registry; $this->writer = $registry; $this->destructors = new WeakMap(); - $this->configurator = $configurator ?? new Configurator(); $this->meters = new WeakMap(); } diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index 3b595a16d..4730a1f97 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -22,8 +22,7 @@ final class TracerProvider implements TracerProviderInterface { private readonly TracerSharedState $tracerSharedState; private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory; - private Configurator $configurator; - private WeakMap $tracers; + private readonly WeakMap $tracers; /** @param list|SpanProcessorInterface|null $spanProcessors */ public function __construct( @@ -33,7 +32,7 @@ public function __construct( SpanLimits $spanLimits = null, IdGeneratorInterface $idGenerator = null, ?InstrumentationScopeFactoryInterface $instrumentationScopeFactory = null, - ?Configurator $configurator = null, + private Configurator $configurator = new Configurator(), ) { $spanProcessors ??= []; $spanProcessors = is_array($spanProcessors) ? $spanProcessors : [$spanProcessors]; @@ -50,7 +49,6 @@ public function __construct( $spanProcessors ); $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); - $this->configurator = $configurator ?? new Configurator(); $this->tracers = new WeakMap(); } From 3bdae48a4cfe23b6d00c614c8b803118a88ff933 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 20 Jul 2024 17:16:09 +1000 Subject: [PATCH 12/36] default values --- src/SDK/Logs/LoggerProviderBuilder.php | 2 +- src/SDK/Metrics/Meter.php | 1 + src/SDK/Metrics/MeterProviderBuilder.php | 2 +- src/SDK/Metrics/MetricRegistry/MetricRegistry.php | 11 +++++++++++ .../Metrics/MetricRegistry/MetricWriterInterface.php | 2 ++ src/SDK/Trace/TracerProviderBuilder.php | 2 +- tests/Unit/SDK/Metrics/InstrumentTest.php | 3 ++- 7 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/SDK/Logs/LoggerProviderBuilder.php b/src/SDK/Logs/LoggerProviderBuilder.php index ea6744665..994506ccf 100644 --- a/src/SDK/Logs/LoggerProviderBuilder.php +++ b/src/SDK/Logs/LoggerProviderBuilder.php @@ -38,7 +38,7 @@ public function build(): LoggerProviderInterface $this->buildProcessor(), new InstrumentationScopeFactory(Attributes::factory()), $this->resource, - configurator: $this->configurator, + configurator: $this->configurator ?? new Configurator(), ); } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index 10e4c4ae9..bee133828 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -86,6 +86,7 @@ public function updateConfigurator(Configurator $configurator): void foreach ($this->instrumentsMap as $instrument) { $instrument->updateConfig($this->config); } + $this->writer->updateConfig($this->config); } public function batchObserve(callable $callback, AsynchronousInstrument $instrument, AsynchronousInstrument ...$instruments): ObservableCallbackInterface diff --git a/src/SDK/Metrics/MeterProviderBuilder.php b/src/SDK/Metrics/MeterProviderBuilder.php index ebaf91c2a..3ec4ecd76 100644 --- a/src/SDK/Metrics/MeterProviderBuilder.php +++ b/src/SDK/Metrics/MeterProviderBuilder.php @@ -66,7 +66,7 @@ public function build(): MeterProviderInterface new CriteriaViewRegistry(), $this->exemplarFilter ?? new WithSampledTraceExemplarFilter(), new NoopStalenessHandlerFactory(), - configurator: $this->configurator, + configurator: $this->configurator ?? new Configurator(), ); } } diff --git a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php index 63d5c59a7..2c3b8cf98 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php +++ b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php @@ -4,6 +4,8 @@ namespace OpenTelemetry\SDK\Metrics\MetricRegistry; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; use function array_key_last; use Closure; use OpenTelemetry\API\Common\Time\ClockInterface; @@ -43,6 +45,7 @@ public function __construct( private readonly ?ContextStorageInterface $contextStorage, private readonly AttributesFactoryInterface $attributesFactory, private readonly ClockInterface $clock, + private Config $config = new Config(State::ENABLED), ) { } @@ -177,6 +180,14 @@ public function collectAndPush(iterable $streamIds): void public function enabled(Instrument $instrument): bool { + if (!$this->config->isEnabled()) { + return false; + } return isset($this->instrumentToStreams[spl_object_id($instrument)]); } + + public function updateConfig(Config $config): void + { + $this->config = $config; + } } diff --git a/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php b/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php index 0b64dfb40..4c1b11b3d 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php +++ b/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\SDK\Metrics\MetricRegistry; use Closure; +use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\Instrument; /** @@ -18,4 +19,5 @@ public function registerCallback(Closure $callback, Instrument $instrument, Inst public function unregisterCallback(int $callbackId): void; public function enabled(Instrument $instrument): bool; + public function updateConfig(Config $config): void; } diff --git a/src/SDK/Trace/TracerProviderBuilder.php b/src/SDK/Trace/TracerProviderBuilder.php index 583fdf6ef..6c8368fa8 100644 --- a/src/SDK/Trace/TracerProviderBuilder.php +++ b/src/SDK/Trace/TracerProviderBuilder.php @@ -49,7 +49,7 @@ public function build(): TracerProviderInterface $this->spanProcessors, $this->sampler, $this->resource, - configurator: $this->configurator, + configurator: $this->configurator ?? new Configurator(), ); } } diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index ecc4f437b..fb662aa4b 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -259,9 +259,10 @@ public function test_synchronous_enabled(): void $this->assertTrue($counter->enabled()); } - public function test_asynchronous_enabled(): void + public function test_asynchronous_enabled_if_writer_enabled(): 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(), $this->config); From 8447c8d50583a83734598b02b49d1fddd01a2970 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 20 Jul 2024 17:51:34 +1000 Subject: [PATCH 13/36] instrument disabled if meter disabled --- src/API/Metrics/Instrument.php | 5 +++ src/SDK/Metrics/Meter.php | 33 ++++--------------- .../Metrics/MetricRegistry/MetricRegistry.php | 9 ----- .../MetricRegistry/MetricWriterInterface.php | 1 - src/SDK/Metrics/ObservableInstrumentTrait.php | 11 +++---- .../Metrics/SynchronousInstrumentTrait.php | 17 +++++----- tests/Unit/SDK/Metrics/InstrumentTest.php | 33 +++++++++++-------- tests/Unit/SDK/Metrics/MeterConfigTest.php | 7 ++-- 8 files changed, 49 insertions(+), 67 deletions(-) diff --git a/src/API/Metrics/Instrument.php b/src/API/Metrics/Instrument.php index 034da34fb..d927c2e80 100644 --- a/src/API/Metrics/Instrument.php +++ b/src/API/Metrics/Instrument.php @@ -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; } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index bee133828..e94982df5 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -43,7 +43,6 @@ final class Meter implements MeterInterface private ?string $instrumentationScopeId = null; private Config $config; - private WeakMap $instrumentsMap; /** * @param iterable $metricRegistries @@ -64,7 +63,6 @@ public function __construct( private readonly ArrayAccess $destructors, private Configurator $configurator, ) { - $this->instrumentsMap = new WeakMap(); $this->config = $this->configurator->getConfig($this->instrumentationScope); } @@ -82,11 +80,6 @@ public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; $this->config = $configurator->getConfig($this->instrumentationScope); - - foreach ($this->instrumentsMap as $instrument) { - $instrument->updateConfig($this->config); - } - $this->writer->updateConfig($this->config); } public function batchObserve(callable $callback, AsynchronousInstrument $instrument, AsynchronousInstrument ...$instruments): ObservableCallbackInterface @@ -138,10 +131,7 @@ public function createCounter(string $name, ?string $unit = null, ?string $descr $advisory, ); - $counter = new Counter($this->writer, $instrument, $referenceCounter, $this->config); - $this->instrumentsMap->offsetSet($counter, $counter); - - return $counter; + return new Counter($this->writer, $instrument, $referenceCounter, $this); } public function createObservableCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableCounterInterface @@ -163,7 +153,7 @@ public function createObservableCounter(string $name, ?string $unit = null, ?str $referenceCounter->acquire(true); } - return new ObservableCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this->config); + return new ObservableCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this); } public function createHistogram(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): HistogramInterface @@ -176,10 +166,7 @@ public function createHistogram(string $name, ?string $unit = null, ?string $des $advisory, ); - $histogram = new Histogram($this->writer, $instrument, $referenceCounter, $this->config); - $this->instrumentsMap->offsetSet($histogram, $histogram); - - return $histogram; + return new Histogram($this->writer, $instrument, $referenceCounter, $this); } public function createGauge(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): GaugeInterface @@ -192,10 +179,7 @@ public function createGauge(string $name, ?string $unit = null, ?string $descrip $advisory, ); - $gauge = new Gauge($this->writer, $instrument, $referenceCounter, $this->config); - $this->instrumentsMap->offsetSet($gauge, $gauge); - - return $gauge; + return new Gauge($this->writer, $instrument, $referenceCounter, $this); } public function createObservableGauge(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableGaugeInterface @@ -217,7 +201,7 @@ public function createObservableGauge(string $name, ?string $unit = null, ?strin $referenceCounter->acquire(true); } - return new ObservableGauge($this->writer, $instrument, $referenceCounter, $this->destructors, $this->config); + return new ObservableGauge($this->writer, $instrument, $referenceCounter, $this->destructors, $this); } public function createUpDownCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): UpDownCounterInterface @@ -230,10 +214,7 @@ public function createUpDownCounter(string $name, ?string $unit = null, ?string $advisory, ); - $counter = new UpDownCounter($this->writer, $instrument, $referenceCounter, $this->config); - $this->instrumentsMap->offsetSet($counter, $counter); - - return $counter; + return new UpDownCounter($this->writer, $instrument, $referenceCounter, $this); } public function createObservableUpDownCounter(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableUpDownCounterInterface @@ -255,7 +236,7 @@ public function createObservableUpDownCounter(string $name, ?string $unit = null $referenceCounter->acquire(true); } - return new ObservableUpDownCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this->config); + return new ObservableUpDownCounter($this->writer, $instrument, $referenceCounter, $this->destructors, $this); } public function isEnabled(): bool diff --git a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php index 2c3b8cf98..08e5e9a6a 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php +++ b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php @@ -45,7 +45,6 @@ public function __construct( private readonly ?ContextStorageInterface $contextStorage, private readonly AttributesFactoryInterface $attributesFactory, private readonly ClockInterface $clock, - private Config $config = new Config(State::ENABLED), ) { } @@ -180,14 +179,6 @@ public function collectAndPush(iterable $streamIds): void public function enabled(Instrument $instrument): bool { - if (!$this->config->isEnabled()) { - return false; - } return isset($this->instrumentToStreams[spl_object_id($instrument)]); } - - public function updateConfig(Config $config): void - { - $this->config = $config; - } } diff --git a/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php b/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php index 4c1b11b3d..270c3d74a 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php +++ b/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php @@ -19,5 +19,4 @@ public function registerCallback(Closure $callback, Instrument $instrument, Inst public function unregisterCallback(int $callbackId): void; public function enabled(Instrument $instrument): bool; - public function updateConfig(Config $config): void; } diff --git a/src/SDK/Metrics/ObservableInstrumentTrait.php b/src/SDK/Metrics/ObservableInstrumentTrait.php index e8de2ae15..9aa22f2db 100644 --- a/src/SDK/Metrics/ObservableInstrumentTrait.php +++ b/src/SDK/Metrics/ObservableInstrumentTrait.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\SDK\Metrics; use ArrayAccess; +use OpenTelemetry\API\Metrics\MeterInterface; use function assert; use OpenTelemetry\API\Metrics\ObservableCallbackInterface; use OpenTelemetry\API\Metrics\ObserverInterface; @@ -21,7 +22,7 @@ public function __construct( private readonly Instrument $instrument, private readonly ReferenceCounterInterface $referenceCounter, private readonly ArrayAccess $destructors, - private Config $config, + private readonly MeterInterface $meter, ) { assert($this instanceof InstrumentHandle); @@ -54,11 +55,9 @@ public function observe(callable $callback): ObservableCallbackInterface public function enabled(): bool { + if (!$this->meter->isEnabled()) { + return false; + } return $this->writer->enabled($this->instrument); } - - public function updateConfig(Config $config): void - { - $this->config = $config; - } } diff --git a/src/SDK/Metrics/SynchronousInstrumentTrait.php b/src/SDK/Metrics/SynchronousInstrumentTrait.php index a27f4a952..5715c76cd 100644 --- a/src/SDK/Metrics/SynchronousInstrumentTrait.php +++ b/src/SDK/Metrics/SynchronousInstrumentTrait.php @@ -4,6 +4,7 @@ namespace OpenTelemetry\SDK\Metrics; +use OpenTelemetry\API\Metrics\MeterInterface; use function assert; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; @@ -16,16 +17,16 @@ trait SynchronousInstrumentTrait private MetricWriterInterface $writer; private Instrument $instrument; private ReferenceCounterInterface $referenceCounter; - private Config $config; + private MeterInterface $meter; - public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter, Config $config) + 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->config = $config; + $this->meter = $meter; $this->referenceCounter->acquire(); } @@ -49,11 +50,9 @@ public function write($amount, iterable $attributes = [], $context = null): void public function enabled(): bool { - return $this->config->isEnabled(); - } - - public function updateConfig(Config $config): void - { - $this->config = $config; + if (!$this->meter->isEnabled()) { + return false; + } + return $this->writer->enabled($this->instrument); } } diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index fb662aa4b..d1644939c 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -5,6 +5,7 @@ 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\Common\InstrumentationScope\Config; @@ -41,11 +42,12 @@ #[CoversClass(ObservableInstrumentTrait::class)] final class InstrumentTest extends TestCase { - private Config $config; + private MeterInterface $meter; public function setUp(): void { - $this->config = Config::default(); + $this->meter = $this->createMock(MeterInterface::class); + $this->meter->method('isEnabled')->willReturn(true); } public function test_counter(): void @@ -57,7 +59,7 @@ public function test_counter(): void $n = $w->registerSynchronousStream($i, $s, $a); $r = $s->register(Temporality::DELTA); - $c = new Counter($w, $i, new NoopStalenessHandler(), $this->config); + $c = new Counter($w, $i, new NoopStalenessHandler(), $this->meter); $c->add(5); $c->add(7); $c->add(3); @@ -86,7 +88,7 @@ public function test_asynchronous_counter(): void $n = $w->registerAsynchronousStream($i, $s, $a); $r = $s->register(Temporality::CUMULATIVE); - $c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->config); + $c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->meter); $c->observe(static function (ObserverInterface $observer): void { $observer->observe(5); }); @@ -122,7 +124,7 @@ public function __invoke(ObserverInterface $observer) } }; - $c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->config); + $c = new ObservableCounter($w, $i, new NoopStalenessHandler(), new WeakMap(), $this->meter); $c->observe($instance); $instance = null; @@ -143,7 +145,7 @@ public function test_up_down_counter(): void $n = $w->registerSynchronousStream($i, $s, $a); $r = $s->register(Temporality::DELTA); - $c = new UpDownCounter($w, $i, new NoopStalenessHandler(), $this->config); + $c = new UpDownCounter($w, $i, new NoopStalenessHandler(), $this->meter); $c->add(5); $c->add(7); $c->add(-8); @@ -172,7 +174,7 @@ public function test_histogram(): void $n = $w->registerSynchronousStream($i, $s, $a); $r = $s->register(Temporality::DELTA); - $h = new Histogram($w, $i, new NoopStalenessHandler(), $this->config); + $h = new Histogram($w, $i, new NoopStalenessHandler(), $this->meter); $h->record(1); $h->record(7); $h->record(9); @@ -249,24 +251,27 @@ public function test_observable_callback_does_not_acquire_persistent_on_destruct 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, $this->config); + $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->enabled()); } - public function test_asynchronous_enabled_if_writer_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(), $this->config); + $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->enabled()); } } diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Unit/SDK/Metrics/MeterConfigTest.php index 263c4d4f6..508dbe0e4 100644 --- a/tests/Unit/SDK/Metrics/MeterConfigTest.php +++ b/tests/Unit/SDK/Metrics/MeterConfigTest.php @@ -10,6 +10,8 @@ use OpenTelemetry\SDK\Metrics\MeterConfig; use OpenTelemetry\SDK\Metrics\MeterConfigurator; use OpenTelemetry\SDK\Metrics\MeterProvider; +use OpenTelemetry\SDK\Metrics\MetricExporter\InMemoryExporter; +use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -20,6 +22,7 @@ class MeterConfigTest extends TestCase public function test_disable_scopes(): void { $meterProvider = MeterProvider::builder() + ->addReader(new ExportingReader(new InMemoryExporter())) ->setConfigurator( Configurator::builder() ->addCondition(new Name('~two~'), State::DISABLED) @@ -42,8 +45,8 @@ public function test_disable_scopes(): void $instruments[] = $meter_two->createGauge('f'); // $instruments[] = $meter_two->createObservableGauge('g'); - foreach ($instruments as $instrument) { - $this->assertFalse($instrument->enabled()); + foreach ($instruments as $id => $instrument) { + $this->assertFalse($instrument->enabled(), sprintf('instrument %s is enabled', $id)); } $this->assertTrue($meter_one->isEnabled()); From 83f81c60ccf8598e9d4ab96e7a845851aceaeb21 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 20 Jul 2024 18:06:23 +1000 Subject: [PATCH 14/36] rename enabled to isEnabled --- src/API/Logs/LoggerInterface.php | 2 +- src/API/Logs/NoopLogger.php | 2 +- src/API/Metrics/Instrument.php | 2 +- src/API/Metrics/Noop/NoopCounter.php | 2 +- src/API/Metrics/Noop/NoopGauge.php | 2 +- src/API/Metrics/Noop/NoopHistogram.php | 2 +- src/API/Metrics/Noop/NoopObservableCounter.php | 2 +- src/API/Metrics/Noop/NoopObservableGauge.php | 2 +- src/API/Metrics/Noop/NoopObservableUpDownCounter.php | 2 +- src/API/Metrics/Noop/NoopUpDownCounter.php | 2 +- src/API/Trace/NoopTracer.php | 2 +- src/API/Trace/TracerInterface.php | 2 +- src/SDK/Logs/Logger.php | 2 +- src/SDK/Metrics/Meter.php | 1 - src/SDK/Metrics/MetricRegistry/MetricRegistry.php | 2 -- src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php | 1 - src/SDK/Metrics/ObservableInstrumentTrait.php | 6 +++--- src/SDK/Metrics/SynchronousInstrumentTrait.php | 8 ++++---- src/SDK/Trace/Tracer.php | 2 +- tests/Unit/API/Logs/NoopLoggerTest.php | 2 +- tests/Unit/API/Trace/NoopTracerTest.php | 2 +- tests/Unit/SDK/Logs/LoggerTest.php | 2 +- tests/Unit/SDK/Metrics/InstrumentTest.php | 5 ++--- tests/Unit/SDK/Metrics/MeterConfigTest.php | 4 ++-- tests/Unit/SDK/Metrics/MeterProviderTest.php | 4 ++-- tests/Unit/SDK/Trace/TracerConfigTest.php | 4 ++-- tests/Unit/SDK/Trace/TracerTest.php | 2 +- 27 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/API/Logs/LoggerInterface.php b/src/API/Logs/LoggerInterface.php index 9ab08e440..c8ea90ff0 100644 --- a/src/API/Logs/LoggerInterface.php +++ b/src/API/Logs/LoggerInterface.php @@ -17,5 +17,5 @@ public function emit(LogRecord $logRecord): void; * are about to generate a LogRecord, to avoid performing computationally expensive work. * @experimental */ - public function enabled(): bool; + public function isEnabled(): bool; } diff --git a/src/API/Logs/NoopLogger.php b/src/API/Logs/NoopLogger.php index 9267ca545..ac631af11 100644 --- a/src/API/Logs/NoopLogger.php +++ b/src/API/Logs/NoopLogger.php @@ -31,7 +31,7 @@ public function log($level, $message, array $context = []): void { } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Instrument.php b/src/API/Metrics/Instrument.php index d927c2e80..9c62c2171 100644 --- a/src/API/Metrics/Instrument.php +++ b/src/API/Metrics/Instrument.php @@ -15,5 +15,5 @@ interface Instrument * @experimental * @see https://opentelemetry.io/docs/specs/otel/metrics/sdk/#instrument-enabled */ - public function enabled(): bool; + public function isEnabled(): bool; } diff --git a/src/API/Metrics/Noop/NoopCounter.php b/src/API/Metrics/Noop/NoopCounter.php index 5622938bd..f4a57f31d 100644 --- a/src/API/Metrics/Noop/NoopCounter.php +++ b/src/API/Metrics/Noop/NoopCounter.php @@ -16,7 +16,7 @@ public function add($amount, iterable $attributes = [], $context = null): void // no-op } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Noop/NoopGauge.php b/src/API/Metrics/Noop/NoopGauge.php index f8409f1e3..c1f93e4f1 100644 --- a/src/API/Metrics/Noop/NoopGauge.php +++ b/src/API/Metrics/Noop/NoopGauge.php @@ -16,7 +16,7 @@ public function record(float|int $amount, iterable $attributes = [], $context = // no-op } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Noop/NoopHistogram.php b/src/API/Metrics/Noop/NoopHistogram.php index 60d415a85..0a0aee953 100644 --- a/src/API/Metrics/Noop/NoopHistogram.php +++ b/src/API/Metrics/Noop/NoopHistogram.php @@ -16,7 +16,7 @@ public function record($amount, iterable $attributes = [], $context = null): voi // no-op } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Noop/NoopObservableCounter.php b/src/API/Metrics/Noop/NoopObservableCounter.php index 437c4432f..8f957c9eb 100644 --- a/src/API/Metrics/Noop/NoopObservableCounter.php +++ b/src/API/Metrics/Noop/NoopObservableCounter.php @@ -17,7 +17,7 @@ public function observe(callable $callback, bool $weaken = false): ObservableCal return new NoopObservableCallback(); } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Noop/NoopObservableGauge.php b/src/API/Metrics/Noop/NoopObservableGauge.php index 0b66e9116..3aa0403b3 100644 --- a/src/API/Metrics/Noop/NoopObservableGauge.php +++ b/src/API/Metrics/Noop/NoopObservableGauge.php @@ -17,7 +17,7 @@ public function observe(callable $callback, bool $weaken = false): ObservableCal return new NoopObservableCallback(); } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Noop/NoopObservableUpDownCounter.php b/src/API/Metrics/Noop/NoopObservableUpDownCounter.php index 0e8cfa099..bb6ba4bb7 100644 --- a/src/API/Metrics/Noop/NoopObservableUpDownCounter.php +++ b/src/API/Metrics/Noop/NoopObservableUpDownCounter.php @@ -17,7 +17,7 @@ public function observe(callable $callback, bool $weaken = false): ObservableCal return new NoopObservableCallback(); } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Metrics/Noop/NoopUpDownCounter.php b/src/API/Metrics/Noop/NoopUpDownCounter.php index c54ddca5d..ca299d9d4 100644 --- a/src/API/Metrics/Noop/NoopUpDownCounter.php +++ b/src/API/Metrics/Noop/NoopUpDownCounter.php @@ -16,7 +16,7 @@ public function add($amount, iterable $attributes = [], $context = null): void // no-op } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Trace/NoopTracer.php b/src/API/Trace/NoopTracer.php index ec14e59e9..1841119b4 100644 --- a/src/API/Trace/NoopTracer.php +++ b/src/API/Trace/NoopTracer.php @@ -24,7 +24,7 @@ public function spanBuilder(string $spanName): SpanBuilderInterface return new NoopSpanBuilder(Context::storage()); } - public function enabled(): bool + public function isEnabled(): bool { return false; } diff --git a/src/API/Trace/TracerInterface.php b/src/API/Trace/TracerInterface.php index abe744677..12c25a533 100644 --- a/src/API/Trace/TracerInterface.php +++ b/src/API/Trace/TracerInterface.php @@ -14,5 +14,5 @@ public function spanBuilder(string $spanName): SpanBuilderInterface; * creating a new span. * @experimental */ - public function enabled(): bool; + public function isEnabled(): bool; } diff --git a/src/SDK/Logs/Logger.php b/src/SDK/Logs/Logger.php index 71e4ff50e..7a33d46c1 100644 --- a/src/SDK/Logs/Logger.php +++ b/src/SDK/Logs/Logger.php @@ -47,7 +47,7 @@ public function emit(LogRecord $logRecord): void } } - public function enabled(): bool + public function isEnabled(): bool { return $this->config->isEnabled(); } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index e94982df5..54c4e7e68 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -32,7 +32,6 @@ use OpenTelemetry\SDK\Metrics\StalenessHandler\MultiReferenceCounter; use OpenTelemetry\SDK\Resource\ResourceInfo; use function serialize; -use WeakMap; /** * @internal diff --git a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php index 08e5e9a6a..63d5c59a7 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php +++ b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php @@ -4,8 +4,6 @@ namespace OpenTelemetry\SDK\Metrics\MetricRegistry; -use OpenTelemetry\SDK\Common\InstrumentationScope\Config; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; use function array_key_last; use Closure; use OpenTelemetry\API\Common\Time\ClockInterface; diff --git a/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php b/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php index 270c3d74a..0b64dfb40 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php +++ b/src/SDK/Metrics/MetricRegistry/MetricWriterInterface.php @@ -5,7 +5,6 @@ namespace OpenTelemetry\SDK\Metrics\MetricRegistry; use Closure; -use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\Instrument; /** diff --git a/src/SDK/Metrics/ObservableInstrumentTrait.php b/src/SDK/Metrics/ObservableInstrumentTrait.php index 9aa22f2db..838d2e4a0 100644 --- a/src/SDK/Metrics/ObservableInstrumentTrait.php +++ b/src/SDK/Metrics/ObservableInstrumentTrait.php @@ -5,11 +5,10 @@ namespace OpenTelemetry\SDK\Metrics; use ArrayAccess; -use OpenTelemetry\API\Metrics\MeterInterface; use function assert; +use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\ObservableCallbackInterface; use OpenTelemetry\API\Metrics\ObserverInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; /** @@ -53,11 +52,12 @@ public function observe(callable $callback): ObservableCallbackInterface ); } - public function enabled(): bool + public function isEnabled(): bool { if (!$this->meter->isEnabled()) { return false; } + return $this->writer->enabled($this->instrument); } } diff --git a/src/SDK/Metrics/SynchronousInstrumentTrait.php b/src/SDK/Metrics/SynchronousInstrumentTrait.php index 5715c76cd..64e2a8611 100644 --- a/src/SDK/Metrics/SynchronousInstrumentTrait.php +++ b/src/SDK/Metrics/SynchronousInstrumentTrait.php @@ -4,9 +4,8 @@ namespace OpenTelemetry\SDK\Metrics; -use OpenTelemetry\API\Metrics\MeterInterface; use function assert; -use OpenTelemetry\SDK\Common\InstrumentationScope\Config; +use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface; /** @@ -43,16 +42,17 @@ public function getHandle(): Instrument public function write($amount, iterable $attributes = [], $context = null): void { - if ($this->enabled()) { + if ($this->isEnabled()) { $this->writer->record($this->instrument, $amount, $attributes, $context); } } - public function enabled(): bool + public function isEnabled(): bool { if (!$this->meter->isEnabled()) { return false; } + return $this->writer->enabled($this->instrument); } } diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index 935cb1b9f..f19db77c9 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -46,7 +46,7 @@ public function getInstrumentationScope(): InstrumentationScopeInterface return $this->instrumentationScope; } - public function enabled(): bool + public function isEnabled(): bool { return $this->config->isEnabled(); } diff --git a/tests/Unit/API/Logs/NoopLoggerTest.php b/tests/Unit/API/Logs/NoopLoggerTest.php index 4bc1f5263..fbe8712f2 100644 --- a/tests/Unit/API/Logs/NoopLoggerTest.php +++ b/tests/Unit/API/Logs/NoopLoggerTest.php @@ -18,6 +18,6 @@ public function test_get_instance(): void public function test_enabled(): void { - $this->assertFalse(NoopLogger::getInstance()->enabled()); + $this->assertFalse(NoopLogger::getInstance()->isEnabled()); } } diff --git a/tests/Unit/API/Trace/NoopTracerTest.php b/tests/Unit/API/Trace/NoopTracerTest.php index 1ee49eb9c..500e27e63 100644 --- a/tests/Unit/API/Trace/NoopTracerTest.php +++ b/tests/Unit/API/Trace/NoopTracerTest.php @@ -24,6 +24,6 @@ public function test_span_builder(): void public function test_enabled(): void { - $this->assertFalse(NoopTracer::getInstance()->enabled()); + $this->assertFalse(NoopTracer::getInstance()->isEnabled()); } } diff --git a/tests/Unit/SDK/Logs/LoggerTest.php b/tests/Unit/SDK/Logs/LoggerTest.php index 11670055b..5f4c2dfe4 100644 --- a/tests/Unit/SDK/Logs/LoggerTest.php +++ b/tests/Unit/SDK/Logs/LoggerTest.php @@ -113,6 +113,6 @@ public function test_logs_dropped_attributes(): void public function test_enabled(): void { $logger = new Logger($this->sharedState, $this->scope); - $this->assertTrue($logger->enabled()); + $this->assertTrue($logger->isEnabled()); } } diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index d1644939c..e9e1d1268 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -8,7 +8,6 @@ use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\SDK\Common\Attribute\Attributes; -use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Metrics\Aggregation\ExplicitBucketHistogramAggregation; use OpenTelemetry\SDK\Metrics\Aggregation\SumAggregation; use OpenTelemetry\SDK\Metrics\Counter; @@ -260,7 +259,7 @@ public function test_synchronous_disabled_if_meter_disabled(): void $meter->expects($this->once())->method('isEnabled')->willReturn(false); $counter = new Counter($w, $i, $c, $meter); - $this->assertFalse($counter->enabled()); + $this->assertFalse($counter->isEnabled()); } public function test_asynchronous_disabled_if_meter_disabled(): void @@ -272,6 +271,6 @@ public function test_asynchronous_disabled_if_meter_disabled(): void $meter->expects($this->once())->method('isEnabled')->willReturn(false); $counter = new ObservableCounter($w, $i, $c, new WeakMap(), $meter); - $this->assertFalse($counter->enabled()); + $this->assertFalse($counter->isEnabled()); } } diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Unit/SDK/Metrics/MeterConfigTest.php index 508dbe0e4..87f300ac7 100644 --- a/tests/Unit/SDK/Metrics/MeterConfigTest.php +++ b/tests/Unit/SDK/Metrics/MeterConfigTest.php @@ -46,7 +46,7 @@ public function test_disable_scopes(): void // $instruments[] = $meter_two->createObservableGauge('g'); foreach ($instruments as $id => $instrument) { - $this->assertFalse($instrument->enabled(), sprintf('instrument %s is enabled', $id)); + $this->assertFalse($instrument->isEnabled(), sprintf('instrument %s is enabled', $id)); } $this->assertTrue($meter_one->isEnabled()); @@ -58,7 +58,7 @@ public function test_disable_scopes(): void $this->assertTrue($meter_two->isEnabled()); foreach ($instruments as $instrument) { - $this->assertTrue($instrument->enabled()); + $this->assertTrue($instrument->isEnabled()); } } } diff --git a/tests/Unit/SDK/Metrics/MeterProviderTest.php b/tests/Unit/SDK/Metrics/MeterProviderTest.php index 03b22c95a..f07bda55a 100644 --- a/tests/Unit/SDK/Metrics/MeterProviderTest.php +++ b/tests/Unit/SDK/Metrics/MeterProviderTest.php @@ -117,10 +117,10 @@ public function test_disable(): void $meter = $meterProvider->getMeter('one'); $this->assertTrue($meter->isEnabled()); $counter = $meter->createCounter('A'); - $this->assertTrue($counter->enabled()); + $this->assertTrue($counter->isEnabled()); $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('~one~'), State::DISABLED)->build()); $this->assertFalse($meter->isEnabled()); - $this->assertFalse($counter->enabled()); + $this->assertFalse($counter->isEnabled()); } } diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Unit/SDK/Trace/TracerConfigTest.php index 5ea083c76..4d430e569 100644 --- a/tests/Unit/SDK/Trace/TracerConfigTest.php +++ b/tests/Unit/SDK/Trace/TracerConfigTest.php @@ -186,11 +186,11 @@ public function test_enable_after_disable(): void ->build(); $tracer = $tracerProvider->getTracer(name: 'two'); $this->assertInstanceOf(Tracer::class, $tracer); - $this->assertFalse($tracer->enabled()); + $this->assertFalse($tracer->isEnabled()); $update = new Configurator(); $tracerProvider->updateConfigurator($update); - $this->assertTrue($tracer->enabled()); + $this->assertTrue($tracer->isEnabled()); } } diff --git a/tests/Unit/SDK/Trace/TracerTest.php b/tests/Unit/SDK/Trace/TracerTest.php index 7719bc4bd..fbbc04ba4 100644 --- a/tests/Unit/SDK/Trace/TracerTest.php +++ b/tests/Unit/SDK/Trace/TracerTest.php @@ -66,6 +66,6 @@ public function test_returns_noop_span_builder_if_shared_state_is_shutdown(): vo public function test_enabled(): void { - $this->assertTrue($this->tracer->enabled()); + $this->assertTrue($this->tracer->isEnabled()); } } From ccf7da5c0596d6753a4fc502c4d9b018f307f17f Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sun, 21 Jul 2024 12:49:22 +1000 Subject: [PATCH 15/36] do not export metrics when meter disabled --- src/SDK/Metrics/Instrument.php | 3 + src/SDK/Metrics/Meter.php | 4 +- .../Metrics/MetricRegistry/MetricRegistry.php | 12 +++ tests/Unit/SDK/Metrics/InstrumentTest.php | 14 +-- tests/Unit/SDK/Metrics/MeterConfigTest.php | 39 ++++++++- tests/Unit/SDK/Metrics/MeterTest.php | 86 +++++++++++-------- .../Metrics/View/SelectionCriteriaTest.php | 13 ++- 7 files changed, 122 insertions(+), 49 deletions(-) diff --git a/src/SDK/Metrics/Instrument.php b/src/SDK/Metrics/Instrument.php index 8d9a5b363..ce2946f68 100644 --- a/src/SDK/Metrics/Instrument.php +++ b/src/SDK/Metrics/Instrument.php @@ -4,6 +4,8 @@ namespace OpenTelemetry\SDK\Metrics; +use OpenTelemetry\API\Metrics\MeterInterface; + final class Instrument { public function __construct( @@ -12,6 +14,7 @@ public function __construct( public readonly ?string $unit, public readonly ?string $description, public readonly array $advisory = [], + public readonly ?MeterInterface $meter = null, ) { } } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index 54c4e7e68..d8afd2947 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -264,7 +264,7 @@ private function getAsynchronousInstrument(Instrument $instrument, Instrumentati */ 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); @@ -310,7 +310,7 @@ private function createSynchronousWriter(string|InstrumentType $instrumentType, */ 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); diff --git a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php index 63d5c59a7..09961dc6a 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php +++ b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php @@ -38,6 +38,8 @@ final class MetricRegistry implements MetricRegistryInterface, MetricWriterInter private array $asynchronousCallbacks = []; /** @var array> */ private array $asynchronousCallbackArguments = []; + /** @var array */ + private array $instruments = []; public function __construct( private readonly ?ContextStorageInterface $contextStorage, @@ -81,6 +83,7 @@ public function unregisterStream(int $streamId): void $this->asynchronousAggregatorFactories[$streamId], $this->instrumentToStreams[$instrumentId][$streamId], $this->streamToInstrument[$streamId], + $this->instruments[$instrumentId], ); if (!$this->instrumentToStreams[$instrumentId]) { unset($this->instrumentToStreams[$instrumentId]); @@ -108,10 +111,12 @@ public function registerCallback(Closure $callback, Instrument $instrument, Inst $instrumentId = spl_object_id($instrument); $this->asynchronousCallbackArguments[$callbackId] = [$instrumentId]; $this->instrumentToCallbacks[$instrumentId][$callbackId] = $callbackId; + $this->instruments[$instrumentId] = $instrument; foreach ($instruments as $instrument) { $instrumentId = spl_object_id($instrument); $this->asynchronousCallbackArguments[$callbackId][] = $instrumentId; $this->instrumentToCallbacks[$instrumentId][$callbackId] = $callbackId; + $this->instruments[$instrumentId] = $instrument; } return $callbackId; @@ -143,6 +148,13 @@ public function collectAndPush(iterable $streamIds): void $aggregator = $this->asynchronousAggregatorFactories[$streamId]->create(); $instrumentId = $this->streamToInstrument[$streamId]; + if ( + array_key_exists($instrumentId, $this->instruments) + && $this->instruments[$instrumentId]->meter + && $this->instruments[$instrumentId]->meter->isEnabled() === false + ) { + continue; + } $observers[$instrumentId] ??= new MultiObserver($this->attributesFactory, $timestamp); $observers[$instrumentId]->writers[] = $aggregator; foreach ($this->instrumentToCallbacks[$instrumentId] ?? [] as $callbackId) { diff --git a/tests/Unit/SDK/Metrics/InstrumentTest.php b/tests/Unit/SDK/Metrics/InstrumentTest.php index e9e1d1268..a5620fd27 100644 --- a/tests/Unit/SDK/Metrics/InstrumentTest.php +++ b/tests/Unit/SDK/Metrics/InstrumentTest.php @@ -54,7 +54,7 @@ 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); @@ -83,7 +83,7 @@ public function test_asynchronous_counter(): void $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); @@ -112,7 +112,7 @@ public function test_asynchronous_counter_weaken(): void $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); @@ -140,7 +140,7 @@ public function test_up_down_counter(): void $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); @@ -169,7 +169,7 @@ public function test_histogram(): void $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); @@ -254,7 +254,7 @@ 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); + $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); @@ -266,7 +266,7 @@ public function test_asynchronous_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); + $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); diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Unit/SDK/Metrics/MeterConfigTest.php index 87f300ac7..56bc0a675 100644 --- a/tests/Unit/SDK/Metrics/MeterConfigTest.php +++ b/tests/Unit/SDK/Metrics/MeterConfigTest.php @@ -4,6 +4,7 @@ namespace OpenTelemetry\Tests\Unit\SDK\Metrics; +use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; use OpenTelemetry\SDK\Common\InstrumentationScope\State; @@ -38,12 +39,12 @@ public function test_disable_scopes(): void $instruments = []; $instruments[] = $meter_two->createCounter('a'); - // $instruments[] = $meter_two->createObservableCounter('b'); + $instruments[] = $meter_two->createObservableCounter('b'); $instruments[] = $meter_two->createUpDownCounter('c'); - // $instruments[] = $meter_two->createObservableUpDownCounter('d'); + $instruments[] = $meter_two->createObservableUpDownCounter('d'); $instruments[] = $meter_two->createHistogram('e'); $instruments[] = $meter_two->createGauge('f'); - // $instruments[] = $meter_two->createObservableGauge('g'); + $instruments[] = $meter_two->createObservableGauge('g'); foreach ($instruments as $id => $instrument) { $this->assertFalse($instrument->isEnabled(), sprintf('instrument %s is enabled', $id)); @@ -61,4 +62,36 @@ public function test_disable_scopes(): void $this->assertTrue($instrument->isEnabled()); } } + + public function test_metrics_not_exported_when_disabled(): void + { + $exporter = new InMemoryExporter(); + $reader = new ExportingReader($exporter); + $meterProvider = MeterProvider::builder() + ->addReader($reader) + ->setConfigurator( + Configurator::builder() + ->addCondition(new Name('~.*~'), State::DISABLED) + ->build() + ) + ->build(); + $meter = $meterProvider->getMeter('test'); + $this->assertFalse($meter->isEnabled()); + $counter = $meter->createCounter('a'); + $async_counter = $meter->createObservableCounter('b', callbacks: function (ObserverInterface $o) { + $o->observe(1); + }); + $this->assertFalse($counter->isEnabled()); + $this->assertFalse($async_counter->isEnabled()); + $counter->add(1); + $reader->collect(); + $metrics = $exporter->collect(true); + foreach ($metrics as $metric) { + /** + * @psalm-suppress NoInterfaceProperties + * @phpstan-ignore-next-line + * */ + $this->assertCount(0, $metric->data->dataPoints); + } + } } diff --git a/tests/Unit/SDK/Metrics/MeterTest.php b/tests/Unit/SDK/Metrics/MeterTest.php index 9e9362c81..2d93e9f3f 100644 --- a/tests/Unit/SDK/Metrics/MeterTest.php +++ b/tests/Unit/SDK/Metrics/MeterTest.php @@ -9,6 +9,9 @@ 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\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Metrics\AggregationInterface; use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface; use OpenTelemetry\SDK\Metrics\Instrument; @@ -32,46 +35,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 +88,7 @@ public function test_create_histogram_advisory(): void '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 +96,6 @@ public function test_create_histogram_advisory(): void ) ->willReturn([]); - $meterProvider = $this->createMeterProviderForMetricFactory($metricFactory); - $meter = $meterProvider->getMeter('test'); $meter->createHistogram( 'http.server.duration', 's', @@ -103,97 +107,97 @@ public function test_create_histogram_advisory(): void 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 +205,20 @@ public function test_create_observable_up_down_counter(): void 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 +226,20 @@ public function test_reuses_writer_when_not_stale(): void 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 +248,19 @@ public function test_releases_writer_on_stale(): void 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 +268,19 @@ public function test_reuses_observer_when_not_stale(): void 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 +377,18 @@ public function test_uses_default_view_if_null_views_returned(): void $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::builder()->addCondition(new Name('~test~'), State::DISABLED)->build()); + $this->assertFalse($meter->isEnabled()); + } + /** * @param iterable $metricReaders */ diff --git a/tests/Unit/SDK/Metrics/View/SelectionCriteriaTest.php b/tests/Unit/SDK/Metrics/View/SelectionCriteriaTest.php index 3038483c3..f1400fd71 100644 --- a/tests/Unit/SDK/Metrics/View/SelectionCriteriaTest.php +++ b/tests/Unit/SDK/Metrics/View/SelectionCriteriaTest.php @@ -4,6 +4,7 @@ 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([])), )); } From 9b33ef738f93ed035cbb2712226f99596d0b1127 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sun, 21 Jul 2024 13:35:15 +1000 Subject: [PATCH 16/36] add benchmark test --- tests/Benchmark/MetricBench.php | 79 +++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/Benchmark/MetricBench.php diff --git a/tests/Benchmark/MetricBench.php b/tests/Benchmark/MetricBench.php new file mode 100644 index 000000000..f668b4df6 --- /dev/null +++ b/tests/Benchmark/MetricBench.php @@ -0,0 +1,79 @@ +reader = new ExportingReader($exporter); + $meterProvider = MeterProvider::builder() + ->addReader($this->reader) + ->setConfigurator( + Configurator::builder() + ->addCondition(new Name('~disabled~'), State::DISABLED) + ->build() + ) + ->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; + for ($i=0; $i < $params['count']; $i++) { + $meter->createObservableCounter('b', callbacks: function (ObserverInterface $o) { + $o->observe(1); + }); + } + $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]; + } +} From 705bfc4050884ba76a57002d1ad89034e83b35d7 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sun, 21 Jul 2024 14:40:26 +1000 Subject: [PATCH 17/36] update logger config on provider config update --- phpstan.neon.dist | 2 +- src/SDK/Logs/Logger.php | 16 ++++- src/SDK/Logs/LoggerProvider.php | 20 +++++-- tests/Benchmark/MetricBench.php | 8 +-- .../Integration/SDK/Logs/LoggerConfigTest.php | 59 +++++++++++++++++++ .../SDK/Metrics/MeterConfigTest.php | 9 +-- .../SDK/Trace/TracerConfigTest.php | 44 +------------- .../InstrumentationScope/ConditionTest.php | 24 ++++++++ tests/Unit/SDK/Logs/LoggerProviderTest.php | 29 +-------- tests/Unit/SDK/Logs/LoggerTest.php | 18 ++++++ 10 files changed, 141 insertions(+), 88 deletions(-) create mode 100644 tests/Integration/SDK/Logs/LoggerConfigTest.php rename tests/{Unit => Integration}/SDK/Metrics/MeterConfigTest.php (92%) rename tests/{Unit => Integration}/SDK/Trace/TracerConfigTest.php (74%) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 1e0e5527e..b63139019 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -41,4 +41,4 @@ parameters: - message: "#Cannot call method .* on null#" paths: - - tests/Unit/SDK/Trace + - tests/Integration/SDK/Trace diff --git a/src/SDK/Logs/Logger.php b/src/SDK/Logs/Logger.php index 7a33d46c1..56b1c689c 100644 --- a/src/SDK/Logs/Logger.php +++ b/src/SDK/Logs/Logger.php @@ -9,6 +9,7 @@ use OpenTelemetry\API\Logs\LogRecord; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; +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 @@ -19,7 +20,7 @@ class Logger implements LoggerInterface { use LogsMessagesTrait; - private readonly Config $config; + private Config $config; /** * @internal @@ -27,13 +28,17 @@ class Logger implements LoggerInterface public function __construct( private readonly LoggerSharedState $loggerSharedState, private readonly InstrumentationScopeInterface $scope, - ?Config $config = null, + ?Configurator $configurator = null, ) { - $this->config = $config ?? Config::default(); + $this->config = $configurator ? $configurator->getConfig($scope) : Config::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( @@ -51,4 +56,9 @@ public function isEnabled(): bool { return $this->config->isEnabled(); } + + public function updateConfig(Configurator $configurator): void + { + $this->config = $configurator->getConfig($this->scope); + } } diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index 4f2bb018a..a5db6b42c 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -11,22 +11,25 @@ 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; public function __construct( LogRecordProcessorInterface $processor, private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null, - private readonly Configurator $configurator = new Configurator(), + private Configurator $configurator = new Configurator(), ) { $this->loggerSharedState = new LoggerSharedState( $resource ?? ResourceInfoFactory::defaultResource(), (new LogRecordLimitsBuilder())->build(), $processor ); + $this->loggers = new WeakMap(); } /** @@ -38,11 +41,10 @@ public function getLogger(string $name, ?string $version = null, ?string $schema return NoopLogger::getInstance(); } $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); - if ($this->configurator->getConfig($scope)->isEnabled() === false) { - return NoopLogger::getInstance(); - } + $logger = new Logger($this->loggerSharedState, $scope, $this->configurator); + $this->loggers->offsetSet($logger, $logger); - return new Logger($this->loggerSharedState, $scope, $this->configurator->getConfig($scope)); + return $logger; } public function shutdown(CancellationInterface $cancellation = null): bool @@ -59,4 +61,12 @@ public static function builder(): LoggerProviderBuilder { return new LoggerProviderBuilder(); } + + public function updateConfigurator(Configurator $configurator): void + { + $this->configurator = $configurator; + foreach ($this->loggers as $logger) { + $logger->updateConfig($configurator); + } + } } diff --git a/tests/Benchmark/MetricBench.php b/tests/Benchmark/MetricBench.php index f668b4df6..9907c176d 100644 --- a/tests/Benchmark/MetricBench.php +++ b/tests/Benchmark/MetricBench.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Benchmark; +namespace OpenTelemetry\Tests\Benchmark; use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\ObserverInterface; @@ -16,9 +16,9 @@ class MetricBench { - private MeterInterface $enabled; - private MeterInterface $disabled; - private MetricReaderInterface $reader; + private readonly MeterInterface $enabled; + private readonly MeterInterface $disabled; + private readonly MetricReaderInterface $reader; public function __construct() { $exporter = new NoopMetricExporter(); diff --git a/tests/Integration/SDK/Logs/LoggerConfigTest.php b/tests/Integration/SDK/Logs/LoggerConfigTest.php new file mode 100644 index 000000000..3fa2ec86a --- /dev/null +++ b/tests/Integration/SDK/Logs/LoggerConfigTest.php @@ -0,0 +1,59 @@ +addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) + ->setConfigurator( + Configurator::builder() + ->addCondition(new Name('~two~'), State::DISABLED) //disable logger named 'two' + ->build() + ) + ->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::builder()->build()); //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'); + } +} diff --git a/tests/Unit/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php similarity index 92% rename from tests/Unit/SDK/Metrics/MeterConfigTest.php rename to tests/Integration/SDK/Metrics/MeterConfigTest.php index 56bc0a675..7ed9aea08 100644 --- a/tests/Unit/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -2,22 +2,19 @@ declare(strict_types=1); -namespace OpenTelemetry\Tests\Unit\SDK\Metrics; +namespace OpenTelemetry\Tests\Integration\SDK\Metrics; use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; use OpenTelemetry\SDK\Common\InstrumentationScope\State; -use OpenTelemetry\SDK\Metrics\MeterConfig; -use OpenTelemetry\SDK\Metrics\MeterConfigurator; use OpenTelemetry\SDK\Metrics\MeterProvider; use OpenTelemetry\SDK\Metrics\MetricExporter\InMemoryExporter; use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader; -use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\TestCase; -#[CoversClass(MeterConfigurator::class)] -#[CoversClass(MeterConfig::class)] +#[CoversNothing] class MeterConfigTest extends TestCase { public function test_disable_scopes(): void diff --git a/tests/Unit/SDK/Trace/TracerConfigTest.php b/tests/Integration/SDK/Trace/TracerConfigTest.php similarity index 74% rename from tests/Unit/SDK/Trace/TracerConfigTest.php rename to tests/Integration/SDK/Trace/TracerConfigTest.php index 4d430e569..cf5689885 100644 --- a/tests/Unit/SDK/Trace/TracerConfigTest.php +++ b/tests/Integration/SDK/Trace/TracerConfigTest.php @@ -2,12 +2,9 @@ declare(strict_types=1); -namespace OpenTelemetry\Tests\SDK\Trace; +namespace OpenTelemetry\Tests\Integration\SDK\Trace; use ArrayObject; -use OpenTelemetry\API\Trace\NonRecordingSpan; -use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; -use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; use OpenTelemetry\SDK\Common\InstrumentationScope\State; @@ -15,16 +12,10 @@ use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; use OpenTelemetry\SDK\Trace\Tracer; use OpenTelemetry\SDK\Trace\TracerProvider; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\TestCase; -#[CoversClass(Config::class)] -#[CoversClass(Configurator::class)] -#[CoversClass(Predicate\Attribute::class)] -#[CoversClass(Predicate\AttributeExists::class)] -#[CoversClass(Predicate\Name::class)] -#[CoversClass(Condition::class)] +#[CoversNothing] class TracerConfigTest extends TestCase { public function test_disable_scopes(): void @@ -146,35 +137,6 @@ public function test_disable_scope_then_enable(): void $this->assertSame($s->getParentContext()->getSpanId(), $p->getContext()->getSpanId(), 'parent is the parent of sibling'); } - #[DataProvider('conditionsProvider')] - public function test_conditions(Predicate $predicate, State $state, bool $expectDisabled): void - { - $tracerProvider = TracerProvider::builder() - ->setConfigurator(Configurator::builder()->addCondition($predicate, $state)->build()) - ->build(); - $tracer = $tracerProvider->getTracer(name: 'two', attributes: ['foo' => 'bar']); - $span = $tracer->spanBuilder('span')->startSpan(); - if ($expectDisabled) { - $this->assertInstanceOf(NonRecordingSpan::class, $span); - } else { - $this->assertNotInstanceOf(NonRecordingSpan::class, $span); - } - } - - public static function conditionsProvider(): array - { - return [ - 'match name + disable' => [new Predicate\Name('~two~'), State::DISABLED, true], - 'match name + enable' => [new Predicate\Name('~two~'), State::ENABLED, false], - 'no match name + disable' => [new Predicate\Name('~one~'), State::DISABLED, false], - 'no match name + enable' => [new Predicate\Name('~one~'), State::ENABLED, false], - 'attribute exists + disable' => [new Predicate\AttributeExists('foo'), State::DISABLED, true], - 'attribute exists + enable' => [new Predicate\AttributeExists('foo'), State::ENABLED, false], - 'attributes matches + disable' => [new Predicate\Attribute('foo', 'bar'), State::DISABLED, true], - 'attribute does not match' => [new Predicate\Attribute('foo', 'no-match'), State::DISABLED, false], - ]; - } - public function test_enable_after_disable(): void { $tracerProvider = TracerProvider::builder() diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php index 90866f105..22b1bab2c 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php @@ -4,14 +4,18 @@ namespace OpenTelemetry\Tests\Unit\SDK\Common\InstrumentationScope; +use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Condition; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; use OpenTelemetry\SDK\Common\InstrumentationScope\State; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; #[CoversClass(Condition::class)] +#[CoversClass(Predicate::class)] class ConditionTest extends TestCase { public function test_predicate_match(): void @@ -21,4 +25,24 @@ public function test_predicate_match(): void $condition = new Condition($predicate, State::DISABLED); $this->assertTrue($condition->match($this->createMock(InstrumentationScopeInterface::class))); } + + #[DataProvider('conditionsProvider')] + public function test_conditions(Predicate $predicate, bool $match): void + { + $condition = new Condition($predicate, State::ENABLED); + $scope = new InstrumentationScope('two', null, null, Attributes::create(['foo' => 'bar'])); + $this->assertSame($match, $condition->match($scope)); + } + + public static function conditionsProvider(): array + { + return [ + 'match name' => [new Predicate\Name('~two~'), true], + 'no match name' => [new Predicate\Name('~one~'), false], + 'attribute exists' => [new Predicate\AttributeExists('foo'), true], + 'attribute does not exist' => [new Predicate\Attribute('bar', 'anything'), false], + 'attributes matches' => [new Predicate\Attribute('foo', 'bar'), true], + 'attribute does not match' => [new Predicate\Attribute('foo', 'no-match'), false], + ]; + } } diff --git a/tests/Unit/SDK/Logs/LoggerProviderTest.php b/tests/Unit/SDK/Logs/LoggerProviderTest.php index 6c7f2ea7a..5065476ce 100644 --- a/tests/Unit/SDK/Logs/LoggerProviderTest.php +++ b/tests/Unit/SDK/Logs/LoggerProviderTest.php @@ -4,19 +4,14 @@ namespace OpenTelemetry\Tests\Unit\SDK\Logs; -use ArrayObject; use OpenTelemetry\API\Logs\NoopLogger; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; -use OpenTelemetry\SDK\Logs\Exporter\InMemoryExporter; use OpenTelemetry\SDK\Logs\Logger; use OpenTelemetry\SDK\Logs\LoggerProvider; use OpenTelemetry\SDK\Logs\LoggerProviderBuilder; use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; -use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor; use OpenTelemetry\SDK\Resource\ResourceInfo; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; @@ -64,7 +59,7 @@ public function test_get_logger_if_disabled(): void { $this->config->method('isEnabled')->willReturn(false); $logger = $this->provider->getLogger('name'); - $this->assertInstanceOf(NoopLogger::class, $logger); + $this->assertFalse($logger->isEnabled()); } public function test_shutdown_calls_processor_shutdown(): void @@ -83,26 +78,4 @@ public function test_builder(): void { $this->assertInstanceOf(LoggerProviderBuilder::class, $this->provider->builder()); } - - public function test_disable_with_configurator(): void - { - $storage = new ArrayObject([]); - $exporter = new InMemoryExporter($storage); - $loggerProvider = LoggerProvider::builder() - ->addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) - ->setConfigurator( - Configurator::builder() - ->addCondition(new Name('~two~'), State::DISABLED) //disable logger named 'two' - ->build() - ) - ->build(); - - $logger_one = $loggerProvider->getLogger('one'); - $logger_two = $loggerProvider->getLogger('two'); - $logger_three = $loggerProvider->getLogger('three'); - - $this->assertNotInstanceOf(NoopLogger::class, $logger_one); - $this->assertInstanceOf(NoopLogger::class, $logger_two); - $this->assertNotInstanceOf(NoopLogger::class, $logger_three); - } } diff --git a/tests/Unit/SDK/Logs/LoggerTest.php b/tests/Unit/SDK/Logs/LoggerTest.php index 5f4c2dfe4..9eefbdb24 100644 --- a/tests/Unit/SDK/Logs/LoggerTest.php +++ b/tests/Unit/SDK/Logs/LoggerTest.php @@ -10,6 +10,9 @@ 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\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Logs\Logger; use OpenTelemetry\SDK\Logs\LoggerSharedState; use OpenTelemetry\SDK\Logs\LogRecordLimitsBuilder; @@ -114,5 +117,20 @@ public function test_enabled(): void { $logger = new Logger($this->sharedState, $this->scope); $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::builder()->addCondition(new Name('~foo~'), State::DISABLED)->build(); + $logger = new Logger($this->sharedState, $this->scope, $configurator); + $this->assertFalse($logger->isEnabled()); + + $this->processor->expects($this->never())->method('onEmit'); + + $logger->emit(new LogRecord()); } } From 0feb99530850b44ce512ead78ae28510da8617ec Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sun, 21 Jul 2024 22:31:56 +1000 Subject: [PATCH 18/36] tests --- src/SDK/Metrics/MeterConfig.php | 24 --------- src/SDK/Metrics/MeterConfigurator.php | 32 ------------ .../InstrumentationScope/ConditionTest.php | 10 +++- .../InstrumentationScope/ConfigTest.php | 34 +++++++++++++ .../InstrumentationScope/ConfiguratorTest.php | 51 +++++++++++++++++++ tests/Unit/SDK/Logs/LoggerProviderTest.php | 17 +++++++ tests/Unit/SDK/Trace/TracerProviderTest.php | 19 +++++++ 7 files changed, 130 insertions(+), 57 deletions(-) delete mode 100644 src/SDK/Metrics/MeterConfig.php delete mode 100644 src/SDK/Metrics/MeterConfigurator.php create mode 100644 tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php create mode 100644 tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php diff --git a/src/SDK/Metrics/MeterConfig.php b/src/SDK/Metrics/MeterConfig.php deleted file mode 100644 index 7cb2058bb..000000000 --- a/src/SDK/Metrics/MeterConfig.php +++ /dev/null @@ -1,24 +0,0 @@ -state === State::ENABLED; - } - - public static function default(): self - { - return new self(); - } -} diff --git a/src/SDK/Metrics/MeterConfigurator.php b/src/SDK/Metrics/MeterConfigurator.php deleted file mode 100644 index 5064f3259..000000000 --- a/src/SDK/Metrics/MeterConfigurator.php +++ /dev/null @@ -1,32 +0,0 @@ - $conditions - */ - public function __construct(private readonly array $conditions = []) - { - } - - public function getConfig(InstrumentationScopeInterface $scope): MeterConfig - { - foreach ($this->conditions as $condition) { - if ($condition->match($scope)) { - return new MeterConfig($condition->state()); - } - } - - return MeterConfig::default(); - } -} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php index 22b1bab2c..1b8ce58fe 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php @@ -15,7 +15,9 @@ use PHPUnit\Framework\TestCase; #[CoversClass(Condition::class)] -#[CoversClass(Predicate::class)] +#[CoversClass(Predicate\Name::class)] +#[CoversClass(Predicate\Attribute::class)] +#[CoversClass(Predicate\AttributeExists::class)] class ConditionTest extends TestCase { public function test_predicate_match(): void @@ -45,4 +47,10 @@ public static function conditionsProvider(): array 'attribute does not match' => [new Predicate\Attribute('foo', 'no-match'), false], ]; } + + public function test_state(): void + { + $condition = new Condition($this->createMock(Predicate::class), State::DISABLED); + $this->assertSame(State::DISABLED, $condition->state()); + } } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php new file mode 100644 index 000000000..d14ff954c --- /dev/null +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php @@ -0,0 +1,34 @@ +assertSame($expected, $config->isEnabled()); + } + + public static function enabledProvider(): array + { + return [ + [State::ENABLED, true], + [State::DISABLED, false], + ]; + } + + public function test_default_is_enabled(): void + { + $config = Config::default(); + $this->assertTrue($config->isEnabled()); + } +} \ No newline at end of file diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php new file mode 100644 index 000000000..84483daa6 --- /dev/null +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php @@ -0,0 +1,51 @@ +scope = new InstrumentationScope('test', null, null, $this->createMock(AttributesInterface::class)); + $builder = new ConfiguratorBuilder(); + $this->predicate = $this->createMock(Predicate::class); + $builder->addCondition($this->predicate, State::DISABLED); + $this->configurator = $builder->build(); + } + + public function test_match(): void + { + $this->predicate->expects($this->once())->method('match')->with($this->equalTo($this->scope))->willReturn(true); + $config = $this->configurator->getConfig($this->scope); + + $this->assertFalse($config->isEnabled()); + } + + public function test_returns_default_on_no_match(): void + { + $this->predicate->expects($this->once())->method('match')->with($this->equalTo($this->scope))->willReturn(false); + $config = $this->configurator->getConfig($this->scope); + + $this->assertTrue($config->isEnabled()); + } + + public function test_builder(): void + { + $this->assertInstanceOf(ConfiguratorBuilder::class, Configurator::builder()); + } +} \ No newline at end of file diff --git a/tests/Unit/SDK/Logs/LoggerProviderTest.php b/tests/Unit/SDK/Logs/LoggerProviderTest.php index 5065476ce..3cf151ca3 100644 --- a/tests/Unit/SDK/Logs/LoggerProviderTest.php +++ b/tests/Unit/SDK/Logs/LoggerProviderTest.php @@ -8,6 +8,8 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; use OpenTelemetry\SDK\Logs\Logger; use OpenTelemetry\SDK\Logs\LoggerProvider; use OpenTelemetry\SDK\Logs\LoggerProviderBuilder; @@ -78,4 +80,19 @@ 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::builder()->addCondition(new Name('~.*~'), State::DISABLED)->build()); + $this->assertFalse($one->isEnabled()); + $this->assertFalse($two->isEnabled()); + } } diff --git a/tests/Unit/SDK/Trace/TracerProviderTest.php b/tests/Unit/SDK/Trace/TracerProviderTest.php index d83d4ccf0..9baac7cc4 100644 --- a/tests/Unit/SDK/Trace/TracerProviderTest.php +++ b/tests/Unit/SDK/Trace/TracerProviderTest.php @@ -5,6 +5,10 @@ namespace OpenTelemetry\Tests\Unit\SDK\Trace; use OpenTelemetry\API\Trace\NoopTracer; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SDK\Common\InstrumentationScope\State; +use OpenTelemetry\SDK\Logs\LoggerProvider; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\TracerProvider; use PHPUnit\Framework\Attributes\CoversClass; @@ -93,4 +97,19 @@ public function test_get_tracer_returns_noop_tracer_after_shutdown(): void $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::builder()->addCondition(new Name('~.*~'), State::DISABLED)->build()); + $this->assertFalse($one->isEnabled()); + $this->assertFalse($two->isEnabled()); + } } From 3955dba13ff72a791e9b37276bfecf2720bdd468 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 11:00:33 +1000 Subject: [PATCH 19/36] rename method, add tests --- .../Common/InstrumentationScope/Condition.php | 2 +- .../InstrumentationScope/Configurator.php | 6 +-- .../Common/InstrumentationScope/Predicate.php | 2 +- .../Predicate/Attribute.php | 2 +- .../Predicate/AttributeExists.php | 2 +- .../InstrumentationScope/Predicate/Name.php | 24 +++++++++++- .../Integration/SDK/Logs/LoggerConfigTest.php | 5 +++ .../SDK/Metrics/MeterConfigTest.php | 5 +++ .../SDK/Trace/TracerConfigTest.php | 7 +++- .../InstrumentationScope/ConditionTest.php | 2 +- .../InstrumentationScope/ConfigTest.php | 4 +- .../InstrumentationScope/ConfiguratorTest.php | 10 +++-- .../Predicate/AttributeExistsTest.php | 4 +- .../Predicate/AttributeTest.php | 6 +-- .../Predicate/NameTest.php | 39 +++++++++++++++++++ tests/Unit/SDK/Trace/TracerProviderTest.php | 1 - 16 files changed, 101 insertions(+), 20 deletions(-) create mode 100644 tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php diff --git a/src/SDK/Common/InstrumentationScope/Condition.php b/src/SDK/Common/InstrumentationScope/Condition.php index cb9d761ee..6886dc667 100644 --- a/src/SDK/Common/InstrumentationScope/Condition.php +++ b/src/SDK/Common/InstrumentationScope/Condition.php @@ -16,7 +16,7 @@ public function __construct( public function match(InstrumentationScopeInterface $scope): ?bool { - return $this->predicate->match($scope); + return $this->predicate->matches($scope); } public function state(): State diff --git a/src/SDK/Common/InstrumentationScope/Configurator.php b/src/SDK/Common/InstrumentationScope/Configurator.php index 8d4d2ad66..6db30009e 100644 --- a/src/SDK/Common/InstrumentationScope/Configurator.php +++ b/src/SDK/Common/InstrumentationScope/Configurator.php @@ -6,9 +6,6 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; -/** - * @internal - */ class Configurator { /** @@ -18,6 +15,9 @@ public function __construct(private readonly array $conditions = []) { } + /** + * @internal + */ public function getConfig(InstrumentationScopeInterface $scope): Config { foreach ($this->conditions as $condition) { diff --git a/src/SDK/Common/InstrumentationScope/Predicate.php b/src/SDK/Common/InstrumentationScope/Predicate.php index 66b952179..69e99ac7c 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate.php +++ b/src/SDK/Common/InstrumentationScope/Predicate.php @@ -8,5 +8,5 @@ interface Predicate { - public function match(InstrumentationScopeInterface $scope): bool; + public function matches(InstrumentationScopeInterface $scope): bool; } diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php b/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php index 894f38416..47dd8508a 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php @@ -15,7 +15,7 @@ public function __construct( ) { } - public function match(InstrumentationScopeInterface $scope): bool + public function matches(InstrumentationScopeInterface $scope): bool { if (!$scope->getAttributes()->has($this->key)) { return false; diff --git a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php index 63937fbce..1296f5430 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php @@ -14,7 +14,7 @@ public function __construct( ) { } - public function match(InstrumentationScopeInterface $scope): bool + public function matches(InstrumentationScopeInterface $scope): bool { return $scope->getAttributes()->has($this->key); } diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php index f1cec7156..e4740bc3a 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Name.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Name.php @@ -4,22 +4,44 @@ namespace OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; +use InvalidArgumentException; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; class Name implements Predicate { + /** + * @throws InvalidArgumentException + */ public function __construct(private readonly string $regex) { + self::validate_regex($this->regex); } /** * @psalm-suppress ArgumentTypeCoercion */ - public function match(InstrumentationScopeInterface $scope): bool + public function matches(InstrumentationScopeInterface $scope): bool { $result = preg_match($this->regex, $scope->getName()); return $result > 0; } + + /** + * @throws InvalidArgumentException + * @phan-suppress PhanParamSuspiciousOrder + * @psalm-suppress ArgumentTypeCoercion + */ + private static function validate_regex(string $regex): void + { + set_error_handler(static fn (int $errno, string $errstr) + => throw new InvalidArgumentException('Invalid regex pattern', $errno)); + + try { + preg_match($regex, ''); + } finally { + restore_error_handler(); + } + } } diff --git a/tests/Integration/SDK/Logs/LoggerConfigTest.php b/tests/Integration/SDK/Logs/LoggerConfigTest.php index 3fa2ec86a..2ae3880b2 100644 --- a/tests/Integration/SDK/Logs/LoggerConfigTest.php +++ b/tests/Integration/SDK/Logs/LoggerConfigTest.php @@ -13,11 +13,16 @@ 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([]); diff --git a/tests/Integration/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php index 7ed9aea08..5aa26fbab 100644 --- a/tests/Integration/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -12,6 +12,7 @@ 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] @@ -60,6 +61,10 @@ public function test_disable_scopes(): void } } + /** + * 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(); diff --git a/tests/Integration/SDK/Trace/TracerConfigTest.php b/tests/Integration/SDK/Trace/TracerConfigTest.php index cf5689885..38cb24d94 100644 --- a/tests/Integration/SDK/Trace/TracerConfigTest.php +++ b/tests/Integration/SDK/Trace/TracerConfigTest.php @@ -13,11 +13,16 @@ use OpenTelemetry\SDK\Trace\Tracer; 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(); @@ -137,7 +142,7 @@ public function test_disable_scope_then_enable(): void $this->assertSame($s->getParentContext()->getSpanId(), $p->getContext()->getSpanId(), 'parent is the parent of sibling'); } - public function test_enable_after_disable(): void + public function test_reenable_enables_tracer(): void { $tracerProvider = TracerProvider::builder() ->setConfigurator( diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php index 1b8ce58fe..7cde80a24 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php @@ -23,7 +23,7 @@ class ConditionTest extends TestCase public function test_predicate_match(): void { $predicate = $this->createMock(Predicate::class); - $predicate->expects($this->once())->method('match')->willReturn(true); + $predicate->expects($this->once())->method('matches')->willReturn(true); $condition = new Condition($predicate, State::DISABLED); $this->assertTrue($condition->match($this->createMock(InstrumentationScopeInterface::class))); } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php index d14ff954c..9176beb67 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php @@ -1,5 +1,7 @@ assertTrue($config->isEnabled()); } -} \ No newline at end of file +} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php index 84483daa6..57843d609 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php @@ -1,5 +1,7 @@ predicate->expects($this->once())->method('match')->with($this->equalTo($this->scope))->willReturn(true); + $this->predicate->expects($this->once())->method('matches')->with($this->equalTo($this->scope))->willReturn(true); $config = $this->configurator->getConfig($this->scope); $this->assertFalse($config->isEnabled()); @@ -38,7 +42,7 @@ public function test_match(): void public function test_returns_default_on_no_match(): void { - $this->predicate->expects($this->once())->method('match')->with($this->equalTo($this->scope))->willReturn(false); + $this->predicate->expects($this->once())->method('matches')->with($this->equalTo($this->scope))->willReturn(false); $config = $this->configurator->getConfig($this->scope); $this->assertTrue($config->isEnabled()); @@ -48,4 +52,4 @@ public function test_builder(): void { $this->assertInstanceOf(ConfiguratorBuilder::class, Configurator::builder()); } -} \ No newline at end of file +} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php index f0529ca35..3391b8ff0 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php @@ -23,9 +23,9 @@ public function test_match(): void }); $predicate = new AttributeExists('foo'); - $this->assertTrue($predicate->match($scope)); + $this->assertTrue($predicate->matches($scope)); $predicate = new AttributeExists('bar'); - $this->assertFalse($predicate->match($scope)); + $this->assertFalse($predicate->matches($scope)); } } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php index 1f168a6c4..24a849a14 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php @@ -20,12 +20,12 @@ public function test_match(): void $scope->method('getAttributes')->willReturn($attributes); $predicate = new Attribute('foo', 'bar'); - $this->assertTrue($predicate->match($scope), 'found and matches'); + $this->assertTrue($predicate->matches($scope), 'found and matches'); $predicate = new Attribute('foo', 'baz'); - $this->assertFalse($predicate->match($scope), 'found but does not match'); + $this->assertFalse($predicate->matches($scope), 'found but does not match'); $predicate = new Attribute('bar', 'bat'); - $this->assertFalse($predicate->match($scope), 'no attribute found'); + $this->assertFalse($predicate->matches($scope), 'no attribute found'); } } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php new file mode 100644 index 000000000..b47799ac0 --- /dev/null +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php @@ -0,0 +1,39 @@ +expectException(InvalidArgumentException::class); + new Name($regex); + } + + public static function invalidRegexProvider(): array + { + return [ + ['invalid-regex'], + ['~[0-9]'], + ]; + } + + public function test_match(): void + { + $scope = new InstrumentationScope('foo', null, null, $this->createMock(AttributesInterface::class)); + $this->assertTrue((new Name('~^foo$~'))->matches($scope)); + } + +} diff --git a/tests/Unit/SDK/Trace/TracerProviderTest.php b/tests/Unit/SDK/Trace/TracerProviderTest.php index 9baac7cc4..9ccaf0d25 100644 --- a/tests/Unit/SDK/Trace/TracerProviderTest.php +++ b/tests/Unit/SDK/Trace/TracerProviderTest.php @@ -8,7 +8,6 @@ use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; use OpenTelemetry\SDK\Common\InstrumentationScope\State; -use OpenTelemetry\SDK\Logs\LoggerProvider; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\TracerProvider; use PHPUnit\Framework\Attributes\CoversClass; From 0eb8707f2e90164a2e4a9f95402235806d5e3b6c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 11:59:37 +1000 Subject: [PATCH 20/36] rename method, tests --- .../Common/InstrumentationScope/Condition.php | 4 +-- .../ConditionInterface.php | 13 +++++++ .../InstrumentationScope/Configurator.php | 2 +- .../Predicate/Attribute.php | 3 ++ .../Predicate/AttributeExists.php | 3 ++ .../InstrumentationScope/Predicate/Name.php | 4 +++ .../InstrumentationScope/ConditionTest.php | 4 +-- .../Predicate/AttributeTest.php | 34 +++++++++++++++---- 8 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 src/SDK/Common/InstrumentationScope/ConditionInterface.php diff --git a/src/SDK/Common/InstrumentationScope/Condition.php b/src/SDK/Common/InstrumentationScope/Condition.php index 6886dc667..19e7b4db3 100644 --- a/src/SDK/Common/InstrumentationScope/Condition.php +++ b/src/SDK/Common/InstrumentationScope/Condition.php @@ -6,7 +6,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; -class Condition +class Condition implements ConditionInterface { public function __construct( private readonly Predicate $predicate, @@ -14,7 +14,7 @@ public function __construct( ) { } - public function match(InstrumentationScopeInterface $scope): ?bool + public function matches(InstrumentationScopeInterface $scope): bool { return $this->predicate->matches($scope); } diff --git a/src/SDK/Common/InstrumentationScope/ConditionInterface.php b/src/SDK/Common/InstrumentationScope/ConditionInterface.php new file mode 100644 index 000000000..b473451bf --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/ConditionInterface.php @@ -0,0 +1,13 @@ +conditions as $condition) { - if ($condition->match($scope)) { + if ($condition->matches($scope)) { return new Config($condition->state()); } } diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php b/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php index 47dd8508a..82153cee8 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Attribute.php @@ -7,6 +7,9 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; +/** + * Predicate which matches exactly on key+value on an InstrumentationScope attribute. + */ class Attribute implements Predicate { public function __construct( diff --git a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php index 1296f5430..b3eef4bd3 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php @@ -7,6 +7,9 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; +/** + * Predicate which matches on the existence of an InstrumentationScope attribute. + */ class AttributeExists implements Predicate { public function __construct( diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php index e4740bc3a..84435c3d0 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Name.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Name.php @@ -8,6 +8,10 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; +/** + * Predicate which performs a regular expression match on InstrumentationScope name. + * The regular expression must be accepted by preg_match. + */ class Name implements Predicate { /** diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php index 7cde80a24..3730f8133 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php @@ -25,7 +25,7 @@ public function test_predicate_match(): void $predicate = $this->createMock(Predicate::class); $predicate->expects($this->once())->method('matches')->willReturn(true); $condition = new Condition($predicate, State::DISABLED); - $this->assertTrue($condition->match($this->createMock(InstrumentationScopeInterface::class))); + $this->assertTrue($condition->matches($this->createMock(InstrumentationScopeInterface::class))); } #[DataProvider('conditionsProvider')] @@ -33,7 +33,7 @@ public function test_conditions(Predicate $predicate, bool $match): void { $condition = new Condition($predicate, State::ENABLED); $scope = new InstrumentationScope('two', null, null, Attributes::create(['foo' => 'bar'])); - $this->assertSame($match, $condition->match($scope)); + $this->assertSame($match, $condition->matches($scope)); } public static function conditionsProvider(): array diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php index 24a849a14..4b44655fd 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php @@ -6,26 +6,46 @@ use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Attribute; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; #[CoversClass(Attribute::class)] class AttributeTest extends TestCase { - public function test_match(): void + #[DataProvider('matchProvider')] + public function test_matches(Predicate $predicate, bool $expected): void { $attributes = new Attributes(['foo' => 'bar'], 0); $scope = $this->createMock(InstrumentationScopeInterface::class); $scope->method('getAttributes')->willReturn($attributes); - $predicate = new Attribute('foo', 'bar'); - $this->assertTrue($predicate->matches($scope), 'found and matches'); + $this->assertSame($expected, $predicate->matches($scope)); + } - $predicate = new Attribute('foo', 'baz'); - $this->assertFalse($predicate->matches($scope), 'found but does not match'); + public static function matchProvider(): array + { + return [ + 'found and matches' => [ + new Attribute('foo', 'bar'), + true, + ], + 'found but does not match' => [ + new Attribute('foo', 'baz'), + false, + ], + 'no attribute found' => [ + new Attribute('bar', 'bat'), + false, + ], + ]; + } - $predicate = new Attribute('bar', 'bat'); - $this->assertFalse($predicate->matches($scope), 'no attribute found'); + public function test_construct(): void + { + $p = new Attribute('foo', 'bar'); + $this->assertInstanceOf(Attribute::class, $p); } } From 0447da6ebb603fde97802ddb41f0891c377ee00b Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 12:10:36 +1000 Subject: [PATCH 21/36] add configurable interface to providers --- src/SDK/Common/InstrumentationScope/Configurable.php | 10 ++++++++++ .../InstrumentationScope/Predicate/Attribute.php | 2 +- .../InstrumentationScope/Predicate/AttributeExists.php | 2 +- src/SDK/Common/InstrumentationScope/Predicate/Name.php | 2 +- src/SDK/Logs/LoggerProvider.php | 8 +++++++- src/SDK/Metrics/MeterProvider.php | 8 +++++++- src/SDK/Trace/TracerProvider.php | 8 +++++++- 7 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/SDK/Common/InstrumentationScope/Configurable.php diff --git a/src/SDK/Common/InstrumentationScope/Configurable.php b/src/SDK/Common/InstrumentationScope/Configurable.php new file mode 100644 index 000000000..5c239cd36 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/Configurable.php @@ -0,0 +1,10 @@ +configurator = $configurator; diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index 6cb073254..abd861465 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\ContextStorageInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface; use OpenTelemetry\SDK\Metrics\MetricFactory\StreamFactory; @@ -21,7 +22,7 @@ use OpenTelemetry\SDK\Sdk; use WeakMap; -final class MeterProvider implements MeterProviderInterface +final class MeterProvider implements MeterProviderInterface, Configurable { private readonly MetricFactoryInterface $metricFactory; private readonly MeterInstruments $instruments; @@ -127,6 +128,11 @@ public static function builder(): MeterProviderBuilder return new MeterProviderBuilder(); } + /** + * Update the {@link Configurator} for a {@link MeterProvider}, which will + * reconfigure all meters created from the provider. + * @experimental + */ public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index 4730a1f97..57addb970 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -11,6 +11,7 @@ use OpenTelemetry\SDK\Common\Future\CancellationInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; @@ -18,7 +19,7 @@ use OpenTelemetry\SDK\Trace\Sampler\ParentBased; use WeakMap; -final class TracerProvider implements TracerProviderInterface +final class TracerProvider implements TracerProviderInterface, Configurable { private readonly TracerSharedState $tracerSharedState; private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory; @@ -103,6 +104,11 @@ public static function builder(): TracerProviderBuilder 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; From 471d391e8196c24ffdb8817824185e3ec8383ce7 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 12:18:47 +1000 Subject: [PATCH 22/36] interface --- src/SDK/Common/InstrumentationScope/Configurator.php | 2 +- .../Common/InstrumentationScope/ScopeConfigurator.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/SDK/Common/InstrumentationScope/ScopeConfigurator.php diff --git a/src/SDK/Common/InstrumentationScope/Configurator.php b/src/SDK/Common/InstrumentationScope/Configurator.php index 8f1950190..f70936a0c 100644 --- a/src/SDK/Common/InstrumentationScope/Configurator.php +++ b/src/SDK/Common/InstrumentationScope/Configurator.php @@ -6,7 +6,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; -class Configurator +class Configurator implements ScopeConfigurator { /** * @param list $conditions diff --git a/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php b/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php new file mode 100644 index 000000000..bc5dda957 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php @@ -0,0 +1,10 @@ + Date: Mon, 22 Jul 2024 12:53:38 +1000 Subject: [PATCH 23/36] ScopeConfigurator interface --- src/SDK/Common/InstrumentationScope/Configurable.php | 2 +- src/SDK/Common/InstrumentationScope/Configurator.php | 5 +++++ .../Common/InstrumentationScope/ScopeConfigurator.php | 5 ++++- src/SDK/Logs/Logger.php | 3 ++- src/SDK/Logs/LoggerProvider.php | 7 +++++-- src/SDK/Logs/LoggerProviderBuilder.php | 2 +- src/SDK/Logs/LoggerProviderInterface.php | 3 ++- src/SDK/Logs/NoopLoggerProvider.php | 6 ++++++ src/SDK/Metrics/Meter.php | 9 +++++---- src/SDK/Metrics/MeterProvider.php | 7 +++++-- src/SDK/Metrics/MeterProviderBuilder.php | 2 +- src/SDK/Metrics/MeterProviderInterface.php | 4 +++- src/SDK/Metrics/NoopMeterProvider.php | 6 ++++++ src/SDK/Trace/NoopTracerProvider.php | 4 ++-- src/SDK/Trace/Tracer.php | 1 + src/SDK/Trace/TracerProvider.php | 7 +++++-- src/SDK/Trace/TracerProviderBuilder.php | 2 +- src/SDK/Trace/TracerProviderInterface.php | 6 ++---- 18 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/SDK/Common/InstrumentationScope/Configurable.php b/src/SDK/Common/InstrumentationScope/Configurable.php index 5c239cd36..9565e8e62 100644 --- a/src/SDK/Common/InstrumentationScope/Configurable.php +++ b/src/SDK/Common/InstrumentationScope/Configurable.php @@ -6,5 +6,5 @@ interface Configurable { - public function updateConfigurator(Configurator $configurator): void; + public function updateConfigurator(ScopeConfigurator $configurator): void; } diff --git a/src/SDK/Common/InstrumentationScope/Configurator.php b/src/SDK/Common/InstrumentationScope/Configurator.php index f70936a0c..2484d6dbb 100644 --- a/src/SDK/Common/InstrumentationScope/Configurator.php +++ b/src/SDK/Common/InstrumentationScope/Configurator.php @@ -33,4 +33,9 @@ public static function builder(): ConfiguratorBuilder { return new ConfiguratorBuilder(); } + + public static function default(): ScopeConfigurator + { + return new self(); + } } diff --git a/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php b/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php index bc5dda957..6224c5497 100644 --- a/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php +++ b/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php @@ -1,5 +1,7 @@ config = $configurator ? $configurator->getConfig($scope) : Config::default(); } diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index e217d617f..389cc3d72 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use WeakMap; @@ -18,12 +19,13 @@ class LoggerProvider implements LoggerProviderInterface, Configurable { private readonly LoggerSharedState $loggerSharedState; private readonly WeakMap $loggers; + private ScopeConfigurator $configurator; public function __construct( LogRecordProcessorInterface $processor, private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null, - private Configurator $configurator = new Configurator(), + ?ScopeConfigurator $configurator = null, ) { $this->loggerSharedState = new LoggerSharedState( $resource ?? ResourceInfoFactory::defaultResource(), @@ -31,6 +33,7 @@ public function __construct( $processor ); $this->loggers = new WeakMap(); + $this->configurator = $configurator ?? Configurator::default(); } /** @@ -68,7 +71,7 @@ public static function builder(): LoggerProviderBuilder * reconfigure all loggers created from the provider. * @experimental */ - public function updateConfigurator(Configurator $configurator): void + public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; foreach ($this->loggers as $logger) { diff --git a/src/SDK/Logs/LoggerProviderBuilder.php b/src/SDK/Logs/LoggerProviderBuilder.php index 994506ccf..15302babd 100644 --- a/src/SDK/Logs/LoggerProviderBuilder.php +++ b/src/SDK/Logs/LoggerProviderBuilder.php @@ -38,7 +38,7 @@ public function build(): LoggerProviderInterface $this->buildProcessor(), new InstrumentationScopeFactory(Attributes::factory()), $this->resource, - configurator: $this->configurator ?? new Configurator(), + configurator: $this->configurator ?? Configurator::default(), ); } diff --git a/src/SDK/Logs/LoggerProviderInterface.php b/src/SDK/Logs/LoggerProviderInterface.php index 5debb13cc..8d7a416d6 100644 --- a/src/SDK/Logs/LoggerProviderInterface.php +++ b/src/SDK/Logs/LoggerProviderInterface.php @@ -5,8 +5,9 @@ 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; diff --git a/src/SDK/Logs/NoopLoggerProvider.php b/src/SDK/Logs/NoopLoggerProvider.php index 819e02ee5..428789f01 100644 --- a/src/SDK/Logs/NoopLoggerProvider.php +++ b/src/SDK/Logs/NoopLoggerProvider.php @@ -6,6 +6,7 @@ use OpenTelemetry\API\Logs\LoggerInterface; use OpenTelemetry\API\Logs\NoopLogger; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; class NoopLoggerProvider implements LoggerProviderInterface { @@ -30,4 +31,9 @@ public function forceFlush(): bool { return true; } + + public function updateConfigurator(ScopeConfigurator $configurator): void + { + //no-op + } } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index d8afd2947..563b93ef3 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -22,7 +22,8 @@ use OpenTelemetry\API\Metrics\UpDownCounterInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; -use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use function OpenTelemetry\SDK\Common\Util\closure; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface; use OpenTelemetry\SDK\Metrics\MetricRegistration\MultiRegistryRegistration; @@ -36,7 +37,7 @@ /** * @internal */ -final class Meter implements MeterInterface +final class Meter implements MeterInterface, Configurable { use LogsMessagesTrait; @@ -60,7 +61,7 @@ public function __construct( private readonly MetricRegistryInterface $registry, private readonly MetricWriterInterface $writer, private readonly ArrayAccess $destructors, - private Configurator $configurator, + private ScopeConfigurator $configurator, ) { $this->config = $this->configurator->getConfig($this->instrumentationScope); } @@ -75,7 +76,7 @@ private static function dummyInstrument(): Instrument /** * @internal */ - public function updateConfigurator(Configurator $configurator): void + public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; $this->config = $configurator->getConfig($this->instrumentationScope); diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index abd861465..0d763c540 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface; use OpenTelemetry\SDK\Metrics\MetricFactory\StreamFactory; use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricRegistry; @@ -32,6 +33,7 @@ final class MeterProvider implements MeterProviderInterface, Configurable private bool $closed = false; private readonly WeakMap $meters; + private ScopeConfigurator $configurator; /** * @param iterable $metricReaders @@ -47,7 +49,7 @@ public function __construct( private readonly ?ExemplarFilterInterface $exemplarFilter, private readonly StalenessHandlerFactoryInterface $stalenessHandlerFactory, MetricFactoryInterface $metricFactory = null, - private Configurator $configurator = new Configurator(), + ?ScopeConfigurator $configurator = null, ) { $this->metricFactory = $metricFactory ?? new StreamFactory(); $this->instruments = new MeterInstruments(); @@ -57,6 +59,7 @@ public function __construct( $this->writer = $registry; $this->destructors = new WeakMap(); $this->meters = new WeakMap(); + $this->configurator = $configurator ?? Configurator::default(); } public function getMeter( @@ -133,7 +136,7 @@ public static function builder(): MeterProviderBuilder * reconfigure all meters created from the provider. * @experimental */ - public function updateConfigurator(Configurator $configurator): void + public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; diff --git a/src/SDK/Metrics/MeterProviderBuilder.php b/src/SDK/Metrics/MeterProviderBuilder.php index 3ec4ecd76..a9d4de0a2 100644 --- a/src/SDK/Metrics/MeterProviderBuilder.php +++ b/src/SDK/Metrics/MeterProviderBuilder.php @@ -66,7 +66,7 @@ public function build(): MeterProviderInterface new CriteriaViewRegistry(), $this->exemplarFilter ?? new WithSampledTraceExemplarFilter(), new NoopStalenessHandlerFactory(), - configurator: $this->configurator ?? new Configurator(), + configurator: $this->configurator ?? Configurator::default(), ); } } diff --git a/src/SDK/Metrics/MeterProviderInterface.php b/src/SDK/Metrics/MeterProviderInterface.php index fcb951106..84d336b1d 100644 --- a/src/SDK/Metrics/MeterProviderInterface.php +++ b/src/SDK/Metrics/MeterProviderInterface.php @@ -4,7 +4,9 @@ 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; diff --git a/src/SDK/Metrics/NoopMeterProvider.php b/src/SDK/Metrics/NoopMeterProvider.php index 2efb484d3..3f02068e9 100644 --- a/src/SDK/Metrics/NoopMeterProvider.php +++ b/src/SDK/Metrics/NoopMeterProvider.php @@ -6,6 +6,7 @@ use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\Noop\NoopMeter; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; class NoopMeterProvider implements MeterProviderInterface { @@ -23,4 +24,9 @@ public function getMeter(string $name, ?string $version = null, ?string $schemaU { return new NoopMeter(); } + + public function updateConfigurator(ScopeConfigurator $configurator): void + { + // no-op + } } diff --git a/src/SDK/Trace/NoopTracerProvider.php b/src/SDK/Trace/NoopTracerProvider.php index e29edbf8a..f062988fc 100644 --- a/src/SDK/Trace/NoopTracerProvider.php +++ b/src/SDK/Trace/NoopTracerProvider.php @@ -6,7 +6,7 @@ use OpenTelemetry\API; use OpenTelemetry\SDK\Common\Future\CancellationInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; class NoopTracerProvider extends API\Trace\NoopTracerProvider implements TracerProviderInterface { @@ -20,7 +20,7 @@ public function shutdown(?CancellationInterface $cancellation = null): bool return true; } - public function updateConfigurator(Configurator $configurator): void + public function updateConfigurator(ScopeConfigurator $configurator): void { } } diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index f19db77c9..e45f53a08 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -30,6 +30,7 @@ public function spanBuilder(string $spanName): API\SpanBuilderInterface if (ctype_space($spanName)) { $spanName = self::FALLBACK_SPAN_NAME; } + // 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()); } diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index 57addb970..b36ea04c3 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler; @@ -23,6 +24,7 @@ final class TracerProvider implements TracerProviderInterface, Configurable { private readonly TracerSharedState $tracerSharedState; private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory; + private ScopeConfigurator $configurator; private readonly WeakMap $tracers; /** @param list|SpanProcessorInterface|null $spanProcessors */ @@ -33,7 +35,7 @@ public function __construct( SpanLimits $spanLimits = null, IdGeneratorInterface $idGenerator = null, ?InstrumentationScopeFactoryInterface $instrumentationScopeFactory = null, - private Configurator $configurator = new Configurator(), + ?ScopeConfigurator $configurator = null, ) { $spanProcessors ??= []; $spanProcessors = is_array($spanProcessors) ? $spanProcessors : [$spanProcessors]; @@ -51,6 +53,7 @@ public function __construct( ); $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); $this->tracers = new WeakMap(); + $this->configurator = $configurator ?? Configurator::default(); } public function forceFlush(?CancellationInterface $cancellation = null): bool @@ -109,7 +112,7 @@ public static function builder(): TracerProviderBuilder * reconfigure all tracers created from the provider. * @experimental */ - public function updateConfigurator(Configurator $configurator): void + public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; diff --git a/src/SDK/Trace/TracerProviderBuilder.php b/src/SDK/Trace/TracerProviderBuilder.php index 6c8368fa8..667d34ea6 100644 --- a/src/SDK/Trace/TracerProviderBuilder.php +++ b/src/SDK/Trace/TracerProviderBuilder.php @@ -49,7 +49,7 @@ public function build(): TracerProviderInterface $this->spanProcessors, $this->sampler, $this->resource, - configurator: $this->configurator ?? new Configurator(), + configurator: $this->configurator ?? Configurator::default(), ); } } diff --git a/src/SDK/Trace/TracerProviderInterface.php b/src/SDK/Trace/TracerProviderInterface.php index aa6ae8d3a..d9afc93b7 100644 --- a/src/SDK/Trace/TracerProviderInterface.php +++ b/src/SDK/Trace/TracerProviderInterface.php @@ -6,13 +6,11 @@ use OpenTelemetry\API\Trace as API; use OpenTelemetry\SDK\Common\Future\CancellationInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; -interface TracerProviderInterface extends API\TracerProviderInterface +interface TracerProviderInterface extends API\TracerProviderInterface, Configurable { public function forceFlush(?CancellationInterface $cancellation = null): bool; public function shutdown(?CancellationInterface $cancellation = null): bool; - - public function updateConfigurator(Configurator $configurator): void; } From 4d21c6d304f566aa3e5e974bc583de9891a5deff Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 13:02:48 +1000 Subject: [PATCH 24/36] param --- src/SDK/Trace/Tracer.php | 5 +++-- src/SDK/Trace/TracerProvider.php | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index e45f53a08..ccd861b64 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; class Tracer implements API\TracerInterface { @@ -19,9 +20,9 @@ class Tracer implements API\TracerInterface public function __construct( private readonly TracerSharedState $tracerSharedState, private readonly InstrumentationScopeInterface $instrumentationScope, - ?Config $config = null, + ?ScopeConfigurator $configurator = null, ) { - $this->config = $config ?? Config::default(); + $this->config = $configurator ? $configurator->getConfig($this->instrumentationScope) : Config::default(); } /** @inheritDoc */ diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index b36ea04c3..2c0899a15 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -78,7 +78,7 @@ public function getTracer( $tracer = new Tracer( $this->tracerSharedState, $scope, - $this->configurator->getConfig($scope), + $this->configurator, ); $this->tracers->offsetSet($tracer, $tracer); From 25c7249425488763815dec7ba4ff65c771ca4280 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 13:28:15 +1000 Subject: [PATCH 25/36] remove duplicate interface implementation --- src/SDK/Logs/LoggerProvider.php | 3 +-- src/SDK/Metrics/MeterProvider.php | 3 +-- src/SDK/Trace/TracerProvider.php | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index 389cc3d72..1df6b602f 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -8,14 +8,13 @@ use OpenTelemetry\API\Logs\NoopLogger; use OpenTelemetry\SDK\Common\Future\CancellationInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use WeakMap; -class LoggerProvider implements LoggerProviderInterface, Configurable +class LoggerProvider implements LoggerProviderInterface { private readonly LoggerSharedState $loggerSharedState; private readonly WeakMap $loggers; diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index 0d763c540..84004bb7d 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -11,7 +11,6 @@ use OpenTelemetry\Context\ContextStorageInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface; @@ -23,7 +22,7 @@ use OpenTelemetry\SDK\Sdk; use WeakMap; -final class MeterProvider implements MeterProviderInterface, Configurable +final class MeterProvider implements MeterProviderInterface { private readonly MetricFactoryInterface $metricFactory; private readonly MeterInstruments $instruments; diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index 2c0899a15..525c14928 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -11,7 +11,6 @@ use OpenTelemetry\SDK\Common\Future\CancellationInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; use OpenTelemetry\SDK\Resource\ResourceInfo; @@ -20,7 +19,7 @@ use OpenTelemetry\SDK\Trace\Sampler\ParentBased; use WeakMap; -final class TracerProvider implements TracerProviderInterface, Configurable +final class TracerProvider implements TracerProviderInterface { private readonly TracerSharedState $tracerSharedState; private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory; From f30df5739ae1bf0c37fea1430779a56ce6964d3b Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 22 Jul 2024 14:57:57 +1000 Subject: [PATCH 26/36] nullsafe, rename method --- src/SDK/Common/InstrumentationScope/Predicate/Name.php | 4 ++-- src/SDK/Metrics/MetricRegistry/MetricRegistry.php | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php index 99fbdfbe3..7d1d44c80 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Name.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Name.php @@ -19,7 +19,7 @@ class Name implements Predicate */ public function __construct(private readonly string $regex) { - self::validate_regex($this->regex); + self::validateRegex($this->regex); } /** @@ -37,7 +37,7 @@ public function matches(InstrumentationScopeInterface $scope): bool * @phan-suppress PhanParamSuspiciousOrder * @psalm-suppress ArgumentTypeCoercion */ - private static function validate_regex(string $regex): void + private static function validateRegex(string $regex): void { set_error_handler(static fn (int $errno, string $errstr) => throw new InvalidArgumentException('Invalid regex pattern', $errno)); diff --git a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php index 09961dc6a..79a76ea4c 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php +++ b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php @@ -150,8 +150,7 @@ public function collectAndPush(iterable $streamIds): void $instrumentId = $this->streamToInstrument[$streamId]; if ( array_key_exists($instrumentId, $this->instruments) - && $this->instruments[$instrumentId]->meter - && $this->instruments[$instrumentId]->meter->isEnabled() === false + && $this->instruments[$instrumentId]->meter?->isEnabled() === false ) { continue; } From 98072153306597d346cc28d253730e2d83e45655 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 23 Jul 2024 14:44:27 +1000 Subject: [PATCH 27/36] fix weakmap GC --- src/SDK/Logs/LoggerProvider.php | 4 ++-- src/SDK/Metrics/MeterProvider.php | 4 ++-- src/SDK/Trace/TracerProvider.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/SDK/Logs/LoggerProvider.php b/src/SDK/Logs/LoggerProvider.php index 1df6b602f..cb2dc1210 100644 --- a/src/SDK/Logs/LoggerProvider.php +++ b/src/SDK/Logs/LoggerProvider.php @@ -45,7 +45,7 @@ public function getLogger(string $name, ?string $version = null, ?string $schema } $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); $logger = new Logger($this->loggerSharedState, $scope, $this->configurator); - $this->loggers->offsetSet($logger, $logger); + $this->loggers->offsetSet($logger, null); return $logger; } @@ -73,7 +73,7 @@ public static function builder(): LoggerProviderBuilder public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; - foreach ($this->loggers as $logger) { + foreach ($this->loggers as $logger => $unused) { $logger->updateConfig($configurator); } } diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index 84004bb7d..a36c203bf 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -86,7 +86,7 @@ public function getMeter( $this->destructors, $this->configurator, ); - $this->meters->offsetSet($meter, $meter); + $this->meters->offsetSet($meter, null); return $meter; } @@ -139,7 +139,7 @@ public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; - foreach ($this->meters as $meter) { + foreach ($this->meters as $meter => $unused) { $meter->updateConfigurator($configurator); } } diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index 525c14928..26932ca82 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -79,7 +79,7 @@ public function getTracer( $scope, $this->configurator, ); - $this->tracers->offsetSet($tracer, $tracer); + $this->tracers->offsetSet($tracer, null); return $tracer; } @@ -115,7 +115,7 @@ public function updateConfigurator(ScopeConfigurator $configurator): void { $this->configurator = $configurator; - foreach ($this->tracers as $tracer) { + foreach ($this->tracers as $tracer => $unused) { $tracer->updateConfig($configurator); } } From 48cf8fa53689e764be887d808a70c72acf4a4983 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 23 Jul 2024 20:05:07 +1000 Subject: [PATCH 28/36] do not export metrics of disabled meters --- src/SDK/Metrics/Instrument.php | 5 +++++ src/SDK/Metrics/MetricFactory/StreamMetricSource.php | 5 +++++ src/SDK/Metrics/MetricReader/ExportingReader.php | 4 +++- src/SDK/Metrics/MetricSourceInterface.php | 1 + tests/Integration/SDK/Metrics/MeterConfigTest.php | 10 ++-------- .../SDK/Metrics/MetricReader/ExportingReaderTest.php | 2 ++ 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/SDK/Metrics/Instrument.php b/src/SDK/Metrics/Instrument.php index ce2946f68..efacb8614 100644 --- a/src/SDK/Metrics/Instrument.php +++ b/src/SDK/Metrics/Instrument.php @@ -17,4 +17,9 @@ public function __construct( public readonly ?MeterInterface $meter = null, ) { } + + public function isEnabled(): bool + { + return $this->meter?->isEnabled() ?? true; + } } diff --git a/src/SDK/Metrics/MetricFactory/StreamMetricSource.php b/src/SDK/Metrics/MetricFactory/StreamMetricSource.php index 5b105a5a5..a96c0e7e4 100644 --- a/src/SDK/Metrics/MetricFactory/StreamMetricSource.php +++ b/src/SDK/Metrics/MetricFactory/StreamMetricSource.php @@ -39,4 +39,9 @@ public function __destruct() { $this->provider->stream->unregister($this->reader); } + + public function isEnabled(): bool + { + return $this->provider->instrument->isEnabled(); + } } diff --git a/src/SDK/Metrics/MetricReader/ExportingReader.php b/src/SDK/Metrics/MetricReader/ExportingReader.php index b7eef1d7b..45585689b 100644 --- a/src/SDK/Metrics/MetricReader/ExportingReader.php +++ b/src/SDK/Metrics/MetricReader/ExportingReader.php @@ -102,7 +102,9 @@ private function doCollect(): bool $metrics = []; foreach ($this->sources as $source) { - $metrics[] = $source->collect(); + if ($source->isEnabled()) { + $metrics[] = $source->collect(); + } } if ($metrics === []) { diff --git a/src/SDK/Metrics/MetricSourceInterface.php b/src/SDK/Metrics/MetricSourceInterface.php index 5f00a0717..ba91e776f 100644 --- a/src/SDK/Metrics/MetricSourceInterface.php +++ b/src/SDK/Metrics/MetricSourceInterface.php @@ -21,4 +21,5 @@ public function collectionTimestamp(): int; * @return Metric collected metric */ public function collect(): Metric; + public function isEnabled(): bool; } diff --git a/tests/Integration/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php index 5aa26fbab..72576a8c4 100644 --- a/tests/Integration/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -81,19 +81,13 @@ public function test_metrics_not_exported_when_disabled(): void $this->assertFalse($meter->isEnabled()); $counter = $meter->createCounter('a'); $async_counter = $meter->createObservableCounter('b', callbacks: function (ObserverInterface $o) { - $o->observe(1); + $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); - foreach ($metrics as $metric) { - /** - * @psalm-suppress NoInterfaceProperties - * @phpstan-ignore-next-line - * */ - $this->assertCount(0, $metric->data->dataPoints); - } + $this->assertSame([], $metrics); } } diff --git a/tests/Unit/SDK/Metrics/MetricReader/ExportingReaderTest.php b/tests/Unit/SDK/Metrics/MetricReader/ExportingReaderTest.php index d9bb3e05a..2150de98c 100644 --- a/tests/Unit/SDK/Metrics/MetricReader/ExportingReaderTest.php +++ b/tests/Unit/SDK/Metrics/MetricReader/ExportingReaderTest.php @@ -148,6 +148,7 @@ public function test_collect_collects_sources_with_current_timestamp(): void $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 @@ public function test_shutdown_exports_metrics(): void $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); From 4dcdb0141bcfa30756c3aa6a2cbb7441b3688831 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 23 Jul 2024 20:12:02 +1000 Subject: [PATCH 29/36] update benchmark per review feedback --- tests/Benchmark/MetricBench.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/Benchmark/MetricBench.php b/tests/Benchmark/MetricBench.php index 9907c176d..99d3d8e92 100644 --- a/tests/Benchmark/MetricBench.php +++ b/tests/Benchmark/MetricBench.php @@ -60,12 +60,12 @@ public function bench_sync_measurements(array $params): void 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++) { - $meter->createObservableCounter('b', callbacks: function (ObserverInterface $o) { - $o->observe(1); - }); + $this->reader->collect(); } - $this->reader->collect(); } public function provideMeasurementCounts(): \Generator @@ -75,5 +75,6 @@ public function provideMeasurementCounts(): \Generator 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]; } } From 65ff1d306b333d2c5b1830d622c963ac8609ac6e Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 23 Jul 2024 20:25:59 +1000 Subject: [PATCH 30/36] use wildcards instead of regex pattern in name predicate --- .../InstrumentationScope/Predicate/Name.php | 31 ++++------------- tests/Benchmark/MetricBench.php | 2 +- .../Integration/SDK/Logs/LoggerConfigTest.php | 2 +- .../SDK/Metrics/MeterConfigTest.php | 4 +-- .../SDK/Trace/TracerConfigTest.php | 6 ++-- .../InstrumentationScope/ConditionTest.php | 4 +-- .../Predicate/NameTest.php | 33 +++++++++++-------- tests/Unit/SDK/Logs/LoggerProviderTest.php | 2 +- tests/Unit/SDK/Logs/LoggerTest.php | 2 +- tests/Unit/SDK/Metrics/MeterProviderTest.php | 2 +- tests/Unit/SDK/Metrics/MeterTest.php | 2 +- tests/Unit/SDK/Trace/TracerProviderTest.php | 2 +- 12 files changed, 40 insertions(+), 52 deletions(-) diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php index 7d1d44c80..62050ecc2 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Name.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Name.php @@ -9,17 +9,19 @@ use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; /** - * Predicate which performs a regular expression match on {@link InstrumentationScope} name. - * The regular expression must be accepted by preg_match. + * Predicate which performs a match on {@link InstrumentationScope} name. + * The name may use wildcards: * and ? */ class Name implements Predicate { + private string $pattern; + /** * @throws InvalidArgumentException */ - public function __construct(private readonly string $regex) + public function __construct(string $name) { - self::validateRegex($this->regex); + $this->pattern = sprintf('/^%s$/', strtr(preg_quote($name, '/'), ['\\?' => '.', '\\*' => '.*'])); } /** @@ -27,25 +29,6 @@ public function __construct(private readonly string $regex) */ public function matches(InstrumentationScopeInterface $scope): bool { - $result = preg_match($this->regex, $scope->getName()); - - return $result > 0; - } - - /** - * @throws InvalidArgumentException - * @phan-suppress PhanParamSuspiciousOrder - * @psalm-suppress ArgumentTypeCoercion - */ - private static function validateRegex(string $regex): void - { - set_error_handler(static fn (int $errno, string $errstr) - => throw new InvalidArgumentException('Invalid regex pattern', $errno)); - - try { - preg_match($regex, ''); - } finally { - restore_error_handler(); - } + return (bool) preg_match($this->pattern, $scope->getName()); } } diff --git a/tests/Benchmark/MetricBench.php b/tests/Benchmark/MetricBench.php index 99d3d8e92..a12af8119 100644 --- a/tests/Benchmark/MetricBench.php +++ b/tests/Benchmark/MetricBench.php @@ -27,7 +27,7 @@ public function __construct() ->addReader($this->reader) ->setConfigurator( Configurator::builder() - ->addCondition(new Name('~disabled~'), State::DISABLED) + ->addCondition(new Name('disabled'), State::DISABLED) ->build() ) ->build(); diff --git a/tests/Integration/SDK/Logs/LoggerConfigTest.php b/tests/Integration/SDK/Logs/LoggerConfigTest.php index 2ae3880b2..ad2646f45 100644 --- a/tests/Integration/SDK/Logs/LoggerConfigTest.php +++ b/tests/Integration/SDK/Logs/LoggerConfigTest.php @@ -31,7 +31,7 @@ public function test_disable_scope_then_enable(): void ->addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) ->setConfigurator( Configurator::builder() - ->addCondition(new Name('~two~'), State::DISABLED) //disable logger named 'two' + ->addCondition(new Name('two'), State::DISABLED) //disable logger named 'two' ->build() ) ->build(); diff --git a/tests/Integration/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php index 72576a8c4..76e3a5711 100644 --- a/tests/Integration/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -24,7 +24,7 @@ public function test_disable_scopes(): void ->addReader(new ExportingReader(new InMemoryExporter())) ->setConfigurator( Configurator::builder() - ->addCondition(new Name('~two~'), State::DISABLED) + ->addCondition(new Name('two'), State::DISABLED) ->build() ) ->build(); @@ -73,7 +73,7 @@ public function test_metrics_not_exported_when_disabled(): void ->addReader($reader) ->setConfigurator( Configurator::builder() - ->addCondition(new Name('~.*~'), State::DISABLED) + ->addCondition(new Name('*'), State::DISABLED) ->build() ) ->build(); diff --git a/tests/Integration/SDK/Trace/TracerConfigTest.php b/tests/Integration/SDK/Trace/TracerConfigTest.php index 38cb24d94..9c835ecf2 100644 --- a/tests/Integration/SDK/Trace/TracerConfigTest.php +++ b/tests/Integration/SDK/Trace/TracerConfigTest.php @@ -29,7 +29,7 @@ public function test_disable_scopes(): void $exporter = new InMemoryExporter($storage); $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) - ->setConfigurator(Configurator::builder()->addCondition(new Predicate\Name('~B~'), State::DISABLED)->build()) //disable tracer B + ->setConfigurator(Configurator::builder()->addCondition(new Predicate\Name('B'), State::DISABLED)->build()) //disable tracer B ->build(); $tracerA = $tracerProvider->getTracer('A'); $tracerB = $tracerProvider->getTracer('B'); @@ -83,7 +83,7 @@ public function test_disable_scope_then_enable(): void ->addSpanProcessor(new SimpleSpanProcessor($exporter)) ->setConfigurator( Configurator::builder() - ->addCondition(new Predicate\Name('~B~'), State::DISABLED) //disable tracer B + ->addCondition(new Predicate\Name('B'), State::DISABLED) //disable tracer B ->build() ) ->build(); @@ -147,7 +147,7 @@ public function test_reenable_enables_tracer(): void $tracerProvider = TracerProvider::builder() ->setConfigurator( Configurator::builder() - ->addCondition(new Predicate\Name('~two~'), State::DISABLED) //disable tracer A + ->addCondition(new Predicate\Name('two'), State::DISABLED) //disable tracer A ->build() ) ->build(); diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php index 3730f8133..42120317d 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php @@ -39,8 +39,8 @@ public function test_conditions(Predicate $predicate, bool $match): void public static function conditionsProvider(): array { return [ - 'match name' => [new Predicate\Name('~two~'), true], - 'no match name' => [new Predicate\Name('~one~'), false], + 'match name' => [new Predicate\Name('two'), true], + 'no match name' => [new Predicate\Name('one'), false], 'attribute exists' => [new Predicate\AttributeExists('foo'), true], 'attribute does not exist' => [new Predicate\Attribute('bar', 'anything'), false], 'attributes matches' => [new Predicate\Attribute('foo', 'bar'), true], diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php index b47799ac0..b7f71b532 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php @@ -8,6 +8,7 @@ use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; +use OpenTelemetry\SemConv\Version; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -15,25 +16,29 @@ #[CoversClass(Name::class)] class NameTest extends TestCase { - #[DataProvider('invalidRegexProvider')] - public function test_invalid_regex_throws(string $regex): void + #[DataProvider('nameProvider')] + public function test_match(string $pattern, bool $expected): void { - $this->expectException(InvalidArgumentException::class); - new Name($regex); + $scope = new InstrumentationScope( + 'io.opentelemetry.php.example.foo', + '1.0', + Version::VERSION_1_26_0->url(), + $this->createMock(AttributesInterface::class), + ); + $this->assertSame($expected, (new Name($pattern))->matches($scope)); } - public static function invalidRegexProvider(): array + public static function nameProvider(): array { return [ - ['invalid-regex'], - ['~[0-9]'], + ['io.opentelemetry.php.example.foo', true], + ['io.opentelemetry.php.example.*', true], + ['io.opentelemetry.php.*', true], + ['*', true], + ['foo', false], + ['*.foo', true], + ['*.bar', false], + ['*.?oo', true], ]; } - - public function test_match(): void - { - $scope = new InstrumentationScope('foo', null, null, $this->createMock(AttributesInterface::class)); - $this->assertTrue((new Name('~^foo$~'))->matches($scope)); - } - } diff --git a/tests/Unit/SDK/Logs/LoggerProviderTest.php b/tests/Unit/SDK/Logs/LoggerProviderTest.php index 3cf151ca3..530471712 100644 --- a/tests/Unit/SDK/Logs/LoggerProviderTest.php +++ b/tests/Unit/SDK/Logs/LoggerProviderTest.php @@ -91,7 +91,7 @@ public function test_update_configurator_updates_loggers(): void $this->assertTrue($one->isEnabled()); $this->assertTrue($two->isEnabled()); - $lp->updateConfigurator(Configurator::builder()->addCondition(new Name('~.*~'), State::DISABLED)->build()); + $lp->updateConfigurator(Configurator::builder()->addCondition(new Name('*'), State::DISABLED)->build()); $this->assertFalse($one->isEnabled()); $this->assertFalse($two->isEnabled()); } diff --git a/tests/Unit/SDK/Logs/LoggerTest.php b/tests/Unit/SDK/Logs/LoggerTest.php index 9eefbdb24..aeb0f53fb 100644 --- a/tests/Unit/SDK/Logs/LoggerTest.php +++ b/tests/Unit/SDK/Logs/LoggerTest.php @@ -125,7 +125,7 @@ public function test_enabled(): void public function test_does_not_log_if_disabled(): void { - $configurator = Configurator::builder()->addCondition(new Name('~foo~'), State::DISABLED)->build(); + $configurator = Configurator::builder()->addCondition(new Name('foo'), State::DISABLED)->build(); $logger = new Logger($this->sharedState, $this->scope, $configurator); $this->assertFalse($logger->isEnabled()); diff --git a/tests/Unit/SDK/Metrics/MeterProviderTest.php b/tests/Unit/SDK/Metrics/MeterProviderTest.php index f07bda55a..17eeced23 100644 --- a/tests/Unit/SDK/Metrics/MeterProviderTest.php +++ b/tests/Unit/SDK/Metrics/MeterProviderTest.php @@ -118,7 +118,7 @@ public function test_disable(): void $this->assertTrue($meter->isEnabled()); $counter = $meter->createCounter('A'); $this->assertTrue($counter->isEnabled()); - $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('~one~'), State::DISABLED)->build()); + $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('one'), State::DISABLED)->build()); $this->assertFalse($meter->isEnabled()); $this->assertFalse($counter->isEnabled()); } diff --git a/tests/Unit/SDK/Metrics/MeterTest.php b/tests/Unit/SDK/Metrics/MeterTest.php index 2d93e9f3f..79ea0c9c7 100644 --- a/tests/Unit/SDK/Metrics/MeterTest.php +++ b/tests/Unit/SDK/Metrics/MeterTest.php @@ -385,7 +385,7 @@ public function test_update_configurator(): void $meterProvider = $this->createMeterProviderForMetricFactory($metricFactory); $meter = $meterProvider->getMeter('test'); $this->assertTrue($meter->isEnabled()); - $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('~test~'), State::DISABLED)->build()); + $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('test'), State::DISABLED)->build()); $this->assertFalse($meter->isEnabled()); } diff --git a/tests/Unit/SDK/Trace/TracerProviderTest.php b/tests/Unit/SDK/Trace/TracerProviderTest.php index 9ccaf0d25..b84d9dcfc 100644 --- a/tests/Unit/SDK/Trace/TracerProviderTest.php +++ b/tests/Unit/SDK/Trace/TracerProviderTest.php @@ -107,7 +107,7 @@ public function test_update_configurator_updates_tracers(): void $this->assertTrue($one->isEnabled()); $this->assertTrue($two->isEnabled()); - $tp->updateConfigurator(Configurator::builder()->addCondition(new Name('~.*~'), State::DISABLED)->build()); + $tp->updateConfigurator(Configurator::builder()->addCondition(new Name('*'), State::DISABLED)->build()); $this->assertFalse($one->isEnabled()); $this->assertFalse($two->isEnabled()); } From 6d018cc947751607484896c2ce77859227faa8e3 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 23 Jul 2024 20:37:44 +1000 Subject: [PATCH 31/36] rector + style --- src/SDK/Common/InstrumentationScope/Predicate/Name.php | 2 +- .../Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php index 62050ecc2..9b0fa1dca 100644 --- a/src/SDK/Common/InstrumentationScope/Predicate/Name.php +++ b/src/SDK/Common/InstrumentationScope/Predicate/Name.php @@ -14,7 +14,7 @@ */ class Name implements Predicate { - private string $pattern; + private readonly string $pattern; /** * @throws InvalidArgumentException diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php index b7f71b532..606ae8c21 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php @@ -4,7 +4,6 @@ namespace OpenTelemetry\Tests\Unit\SDK\Common\InstrumentationScope\Predicate; -use InvalidArgumentException; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope; use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; From d2c9793c9947bacf47b1c16e779654ebcc61420f Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 23 Jul 2024 20:57:18 +1000 Subject: [PATCH 32/36] add isEnabled to late binding tracer/logger/meter --- src/API/Logs/LateBindingLogger.php | 5 +++++ src/API/Metrics/LateBindingMeter.php | 5 +++++ src/API/Trace/LateBindingTracer.php | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/API/Logs/LateBindingLogger.php b/src/API/Logs/LateBindingLogger.php index 84f9ed81f..12ac83b7a 100644 --- a/src/API/Logs/LateBindingLogger.php +++ b/src/API/Logs/LateBindingLogger.php @@ -20,4 +20,9 @@ public function emit(LogRecord $logRecord): void { ($this->logger ??= ($this->factory)())->emit($logRecord); } + + public function isEnabled(): bool + { + return true; + } } diff --git a/src/API/Metrics/LateBindingMeter.php b/src/API/Metrics/LateBindingMeter.php index b146bfbbb..18dd1112d 100644 --- a/src/API/Metrics/LateBindingMeter.php +++ b/src/API/Metrics/LateBindingMeter.php @@ -58,4 +58,9 @@ public function createObservableUpDownCounter(string $name, ?string $unit = null { return ($this->meter ??= ($this->factory)())->createObservableUpDownCounter($name, $unit, $description, $advisory, $callbacks); } + + public function isEnabled(): bool + { + return true; + } } diff --git a/src/API/Trace/LateBindingTracer.php b/src/API/Trace/LateBindingTracer.php index 9f3defcb2..25b5244aa 100644 --- a/src/API/Trace/LateBindingTracer.php +++ b/src/API/Trace/LateBindingTracer.php @@ -20,4 +20,9 @@ public function spanBuilder(string $spanName): SpanBuilderInterface { return ($this->tracer ??= ($this->factory)())->spanBuilder($spanName); } + + public function isEnabled(): bool + { + return true; + } } From b5f0c721e3f797f623fcedb9399d6e9aeb0cb162 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Jul 2024 11:24:43 +1000 Subject: [PATCH 33/36] disable metrics streams instead of callbacks --- .../Metrics/MetricRegistry/MetricRegistry.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php index 79a76ea4c..2c553419e 100644 --- a/src/SDK/Metrics/MetricRegistry/MetricRegistry.php +++ b/src/SDK/Metrics/MetricRegistry/MetricRegistry.php @@ -57,6 +57,7 @@ public function registerSynchronousStream(Instrument $instrument, MetricStreamIn $this->synchronousAggregators[$streamId] = $aggregator; $this->instrumentToStreams[$instrumentId][$streamId] = $streamId; $this->streamToInstrument[$streamId] = $instrumentId; + $this->instruments[$instrumentId] = $instrument; return $streamId; } @@ -70,6 +71,7 @@ public function registerAsynchronousStream(Instrument $instrument, MetricStreamI $this->asynchronousAggregatorFactories[$streamId] = $aggregatorFactory; $this->instrumentToStreams[$instrumentId][$streamId] = $streamId; $this->streamToInstrument[$streamId] = $instrumentId; + $this->instruments[$instrumentId] = $instrument; return $streamId; } @@ -111,12 +113,10 @@ public function registerCallback(Closure $callback, Instrument $instrument, Inst $instrumentId = spl_object_id($instrument); $this->asynchronousCallbackArguments[$callbackId] = [$instrumentId]; $this->instrumentToCallbacks[$instrumentId][$callbackId] = $callbackId; - $this->instruments[$instrumentId] = $instrument; foreach ($instruments as $instrument) { $instrumentId = spl_object_id($instrument); $this->asynchronousCallbackArguments[$callbackId][] = $instrumentId; $this->instrumentToCallbacks[$instrumentId][$callbackId] = $callbackId; - $this->instruments[$instrumentId] = $instrument; } return $callbackId; @@ -144,16 +144,16 @@ public function collectAndPush(iterable $streamIds): void $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]; - if ( - array_key_exists($instrumentId, $this->instruments) - && $this->instruments[$instrumentId]->meter?->isEnabled() === false - ) { - continue; - } $observers[$instrumentId] ??= new MultiObserver($this->attributesFactory, $timestamp); $observers[$instrumentId]->writers[] = $aggregator; foreach ($this->instrumentToCallbacks[$instrumentId] ?? [] as $callbackId) { From 6fb6b1d2e0842405506c106768862334bdf422f6 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Jul 2024 22:57:56 +1000 Subject: [PATCH 34/36] add skipped test for disabling metric streams the feature is not implemented yet --- .../InstrumentationScope/Configurator.php | 3 + src/SDK/Metrics/MeterProviderBuilder.php | 11 +++- .../SDK/Metrics/MeterConfigTest.php | 56 ++++++++++++++++++- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/SDK/Common/InstrumentationScope/Configurator.php b/src/SDK/Common/InstrumentationScope/Configurator.php index 2484d6dbb..f92176d68 100644 --- a/src/SDK/Common/InstrumentationScope/Configurator.php +++ b/src/SDK/Common/InstrumentationScope/Configurator.php @@ -34,6 +34,9 @@ public static function builder(): ConfiguratorBuilder return new ConfiguratorBuilder(); } + /** + * Create a default, everything-enabled, configurator. + */ public static function default(): ScopeConfigurator { return new self(); diff --git a/src/SDK/Metrics/MeterProviderBuilder.php b/src/SDK/Metrics/MeterProviderBuilder.php index a9d4de0a2..c2fc5182b 100644 --- a/src/SDK/Metrics/MeterProviderBuilder.php +++ b/src/SDK/Metrics/MeterProviderBuilder.php @@ -5,6 +5,7 @@ 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; @@ -22,6 +23,7 @@ class MeterProviderBuilder private ?ResourceInfo $resource = null; private ?ExemplarFilterInterface $exemplarFilter = null; private ?Configurator $configurator = null; + private ?ClockInterface $clock = null; public function setResource(ResourceInfo $resource): self { @@ -51,6 +53,13 @@ public function setConfigurator(Configurator $configurator): self return $this; } + public function setClock(ClockInterface $clock): self + { + $this->clock = $clock; + + return $this; + } + /** * @psalm-suppress PossiblyInvalidArgument */ @@ -59,7 +68,7 @@ public function build(): MeterProviderInterface return new MeterProvider( null, $this->resource ?? ResourceInfoFactory::emptyResource(), - Clock::getDefault(), + $this->clock ?? Clock::getDefault(), Attributes::factory(), new InstrumentationScopeFactory(Attributes::factory()), $this->metricReaders, diff --git a/tests/Integration/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php index 76e3a5711..63b4784b1 100644 --- a/tests/Integration/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -4,10 +4,12 @@ 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\Common\InstrumentationScope\Predicate\Name; use OpenTelemetry\SDK\Common\InstrumentationScope\State; +use OpenTelemetry\SDK\Metrics\Data\Temporality; use OpenTelemetry\SDK\Metrics\MeterProvider; use OpenTelemetry\SDK\Metrics\MetricExporter\InMemoryExporter; use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader; @@ -18,6 +20,10 @@ #[CoversNothing] class MeterConfigTest extends TestCase { + const T0 = 0; + const T1 = 1; + const T2 = 2; + public function test_disable_scopes(): void { $meterProvider = MeterProvider::builder() @@ -45,14 +51,14 @@ public function test_disable_scopes(): void $instruments[] = $meter_two->createObservableGauge('g'); foreach ($instruments as $id => $instrument) { - $this->assertFalse($instrument->isEnabled(), sprintf('instrument %s is enabled', $id)); + $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(new Configurator()); + $meterProvider->updateConfigurator(Configurator::default()); $this->assertTrue($meter_two->isEnabled()); @@ -90,4 +96,50 @@ public function test_metrics_not_exported_when_disabled(): void $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::builder() + ->addCondition(new Name('*'), State::DISABLED) + ->build(); + $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::default()); + $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); + } } From e7e0104fa2e484da607c7fe2b0870b1dfff6c84f Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 25 Jul 2024 11:28:23 +1000 Subject: [PATCH 35/36] note a todo on reconfiguring meters --- src/SDK/Metrics/MeterProvider.php | 5 +++-- tests/Integration/SDK/Metrics/MeterConfigTest.php | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/SDK/Metrics/MeterProvider.php b/src/SDK/Metrics/MeterProvider.php index a36c203bf..cd1b9f941 100644 --- a/src/SDK/Metrics/MeterProvider.php +++ b/src/SDK/Metrics/MeterProvider.php @@ -131,8 +131,9 @@ public static function builder(): MeterProviderBuilder } /** - * Update the {@link Configurator} for a {@link MeterProvider}, which will - * reconfigure all meters created from the provider. + * 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(ScopeConfigurator $configurator): void diff --git a/tests/Integration/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php index 63b4784b1..9eaf1c957 100644 --- a/tests/Integration/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -104,7 +104,7 @@ public function test_metrics_not_exported_when_disabled(): void */ public function test_streams_recreated_on_enable(): void { - $this->markTestSkipped('TODO implement drop/create streams'); /* @phpstan-ignore-next-line */ + $this->markTestSkipped('TODO implement drop/create streams'); // @phpstan-ignore-next-line $clock = new TestClock(self::T0); $disabledConfigurator = Configurator::builder() ->addCondition(new Name('*'), State::DISABLED) From 1d784016836047ca42525e3f5beea9844bb37f6c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 25 Jul 2024 18:01:11 +1000 Subject: [PATCH 36/36] replace scope configurator implementation use Nevay's implementation, provided in PR feedback --- .phan/config.php | 1 + phpstan.neon.dist | 8 ++ .../Common/InstrumentationScope/Condition.php | 26 ------ .../ConditionInterface.php | 13 --- .../Common/InstrumentationScope/Config.php | 17 +--- .../InstrumentationScope/ConfigTrait.php | 20 +++++ .../InstrumentationScope/Configurable.php | 2 +- .../InstrumentationScope/Configurator.php | 88 ++++++++++++++++--- .../ConfiguratorBuilder.php | 23 ----- .../ConfiguratorClosure.php | 33 +++++++ .../Common/InstrumentationScope/Predicate.php | 12 --- .../Predicate/Attribute.php | 30 ------- .../Predicate/AttributeExists.php | 24 ----- .../InstrumentationScope/Predicate/Name.php | 34 ------- .../ScopeConfigurator.php | 13 --- src/SDK/Common/InstrumentationScope/State.php | 11 --- src/SDK/Logs/Logger.php | 14 +-- src/SDK/Logs/LoggerConfig.php | 18 ++++ src/SDK/Logs/LoggerProvider.php | 10 +-- src/SDK/Logs/LoggerProviderBuilder.php | 2 +- src/SDK/Logs/NoopLoggerProvider.php | 4 +- src/SDK/Metrics/Meter.php | 10 +-- src/SDK/Metrics/MeterConfig.php | 18 ++++ src/SDK/Metrics/MeterProvider.php | 7 +- src/SDK/Metrics/MeterProviderBuilder.php | 2 +- src/SDK/Metrics/NoopMeterProvider.php | 4 +- src/SDK/Trace/NoopTracerProvider.php | 4 +- src/SDK/Trace/Tracer.php | 7 +- src/SDK/Trace/TracerConfig.php | 18 ++++ src/SDK/Trace/TracerProvider.php | 7 +- src/SDK/Trace/TracerProviderBuilder.php | 2 +- tests/Benchmark/MetricBench.php | 8 +- .../Integration/SDK/Logs/LoggerConfigTest.php | 10 +-- .../SDK/Metrics/MeterConfigTest.php | 22 ++--- .../SDK/Trace/TracerConfigTest.php | 24 ++--- .../InstrumentationScope/ConditionTest.php | 56 ------------ .../InstrumentationScope/ConfigTest.php | 26 ++++-- .../InstrumentationScope/ConfiguratorTest.php | 42 ++++----- .../Predicate/AttributeExistsTest.php | 31 ------- .../Predicate/AttributeTest.php | 51 ----------- .../Predicate/NameTest.php | 43 --------- tests/Unit/SDK/Logs/LoggerProviderTest.php | 11 +-- tests/Unit/SDK/Logs/LoggerTest.php | 5 +- tests/Unit/SDK/Metrics/MeterProviderTest.php | 5 +- tests/Unit/SDK/Metrics/MeterTest.php | 5 +- tests/Unit/SDK/Trace/TracerProviderTest.php | 5 +- 46 files changed, 306 insertions(+), 520 deletions(-) delete mode 100644 src/SDK/Common/InstrumentationScope/Condition.php delete mode 100644 src/SDK/Common/InstrumentationScope/ConditionInterface.php create mode 100644 src/SDK/Common/InstrumentationScope/ConfigTrait.php delete mode 100644 src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php create mode 100644 src/SDK/Common/InstrumentationScope/ConfiguratorClosure.php delete mode 100644 src/SDK/Common/InstrumentationScope/Predicate.php delete mode 100644 src/SDK/Common/InstrumentationScope/Predicate/Attribute.php delete mode 100644 src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php delete mode 100644 src/SDK/Common/InstrumentationScope/Predicate/Name.php delete mode 100644 src/SDK/Common/InstrumentationScope/ScopeConfigurator.php delete mode 100644 src/SDK/Common/InstrumentationScope/State.php create mode 100644 src/SDK/Logs/LoggerConfig.php create mode 100644 src/SDK/Metrics/MeterConfig.php create mode 100644 src/SDK/Trace/TracerConfig.php delete mode 100644 tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php delete mode 100644 tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php delete mode 100644 tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php delete mode 100644 tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php diff --git a/.phan/config.php b/.phan/config.php index a1258a628..ed5c34e5e 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -284,6 +284,7 @@ 'PhanAccessClassInternal', 'PhanAccessMethodInternal', 'PhanAccessPropertyInternal', + 'PhanTypeMismatchPropertyReal', 'PhanTemplateTypeNotUsedInFunctionReturn', ], diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b63139019..569545a4d 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -42,3 +42,11 @@ parameters: 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 \ No newline at end of file diff --git a/src/SDK/Common/InstrumentationScope/Condition.php b/src/SDK/Common/InstrumentationScope/Condition.php deleted file mode 100644 index 19e7b4db3..000000000 --- a/src/SDK/Common/InstrumentationScope/Condition.php +++ /dev/null @@ -1,26 +0,0 @@ -predicate->matches($scope); - } - - public function state(): State - { - return $this->state; - } -} diff --git a/src/SDK/Common/InstrumentationScope/ConditionInterface.php b/src/SDK/Common/InstrumentationScope/ConditionInterface.php deleted file mode 100644 index b473451bf..000000000 --- a/src/SDK/Common/InstrumentationScope/ConditionInterface.php +++ /dev/null @@ -1,13 +0,0 @@ -state === State::ENABLED; - } - - public static function default(): self - { - return new self(); - } + public function setDisabled(bool $disabled): void; + public function isEnabled(): bool; } diff --git a/src/SDK/Common/InstrumentationScope/ConfigTrait.php b/src/SDK/Common/InstrumentationScope/ConfigTrait.php new file mode 100644 index 000000000..c8c122184 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/ConfigTrait.php @@ -0,0 +1,20 @@ +disabled = $disabled; + } + + public function isEnabled(): bool + { + return $this->disabled === false; + } +} diff --git a/src/SDK/Common/InstrumentationScope/Configurable.php b/src/SDK/Common/InstrumentationScope/Configurable.php index 9565e8e62..5c239cd36 100644 --- a/src/SDK/Common/InstrumentationScope/Configurable.php +++ b/src/SDK/Common/InstrumentationScope/Configurable.php @@ -6,5 +6,5 @@ interface Configurable { - public function updateConfigurator(ScopeConfigurator $configurator): void; + public function updateConfigurator(Configurator $configurator): void; } diff --git a/src/SDK/Common/InstrumentationScope/Configurator.php b/src/SDK/Common/InstrumentationScope/Configurator.php index f92176d68..3ed5816a4 100644 --- a/src/SDK/Common/InstrumentationScope/Configurator.php +++ b/src/SDK/Common/InstrumentationScope/Configurator.php @@ -4,41 +4,101 @@ 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; -class Configurator implements ScopeConfigurator +/** + * @template T + */ +final class Configurator { + /** @var Closure(InstrumentationScopeInterface): T */ + private readonly Closure $factory; + /** @var WeakMap */ + private WeakMap $configs; + /** @var list */ + private array $configurators = []; + /** - * @param list $conditions + * @param Closure(InstrumentationScopeInterface): T $factory + * @psalm-suppress PropertyTypeCoercion */ - public function __construct(private readonly array $conditions = []) + public function __construct(Closure $factory) { + $this->configs = new WeakMap(); + $this->factory = $factory; } /** - * @internal + * @param Closure(T, InstrumentationScopeInterface): void $closure */ - public function getConfig(InstrumentationScopeInterface $scope): Config + public function with(Closure $closure, ?string $name, ?string $version = null, ?string $schemaUrl = null): self { - foreach ($this->conditions as $condition) { - if ($condition->matches($scope)) { - return new Config($condition->state()); + $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 Config::default(); + return $this->configs[$instrumentationScope] ??= $config; } - public static function builder(): ConfiguratorBuilder + /** + * Create a default Configurator for a LoggerConfig + * @return Configurator + */ + public static function logger(): self { - return new ConfiguratorBuilder(); + return (new Configurator(static fn () => new LoggerConfig())); } /** - * Create a default, everything-enabled, configurator. + * Create a default Configurator for a MeterConfig + * @return Configurator */ - public static function default(): ScopeConfigurator + public static function meter(): self + { + return (new Configurator(static fn () => new MeterConfig())); + } + + /** + * Create a default Configurator for a TracerConfig + * @return Configurator + */ + public static function tracer(): self + { + return (new Configurator(static fn () => new TracerConfig())); + } + + private static function namePattern(?string $name): ?string { - return new self(); + return $name !== null + ? sprintf('/^%s$/', strtr(preg_quote($name, '/'), ['\\?' => '.', '\\*' => '.*'])) + : null; } } diff --git a/src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php b/src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php deleted file mode 100644 index 674fdd519..000000000 --- a/src/SDK/Common/InstrumentationScope/ConfiguratorBuilder.php +++ /dev/null @@ -1,23 +0,0 @@ - */ - private array $conditions = []; - - public function addCondition(Predicate $predicate, State $state): ConfiguratorBuilder - { - $this->conditions[] = new Condition($predicate, $state); - - return $this; - } - - public function build(): Configurator - { - return new Configurator($this->conditions); - } -} diff --git a/src/SDK/Common/InstrumentationScope/ConfiguratorClosure.php b/src/SDK/Common/InstrumentationScope/ConfiguratorClosure.php new file mode 100644 index 000000000..ff043fa94 --- /dev/null +++ b/src/SDK/Common/InstrumentationScope/ConfiguratorClosure.php @@ -0,0 +1,33 @@ +name === null || preg_match($this->name, $instrumentationScope->getName())) + && ($this->version === null || $this->version === $instrumentationScope->getVersion()) + && ($this->schemaUrl === null || $this->schemaUrl === $instrumentationScope->getSchemaUrl()); + } +} diff --git a/src/SDK/Common/InstrumentationScope/Predicate.php b/src/SDK/Common/InstrumentationScope/Predicate.php deleted file mode 100644 index 69e99ac7c..000000000 --- a/src/SDK/Common/InstrumentationScope/Predicate.php +++ /dev/null @@ -1,12 +0,0 @@ -getAttributes()->has($this->key)) { - return false; - } - $attribute = $scope->getAttributes()->get($this->key); - - return $attribute === $this->value; - } -} diff --git a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php b/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php deleted file mode 100644 index 298e0b4c1..000000000 --- a/src/SDK/Common/InstrumentationScope/Predicate/AttributeExists.php +++ /dev/null @@ -1,24 +0,0 @@ -getAttributes()->has($this->key); - } -} diff --git a/src/SDK/Common/InstrumentationScope/Predicate/Name.php b/src/SDK/Common/InstrumentationScope/Predicate/Name.php deleted file mode 100644 index 9b0fa1dca..000000000 --- a/src/SDK/Common/InstrumentationScope/Predicate/Name.php +++ /dev/null @@ -1,34 +0,0 @@ -pattern = sprintf('/^%s$/', strtr(preg_quote($name, '/'), ['\\?' => '.', '\\*' => '.*'])); - } - - /** - * @psalm-suppress ArgumentTypeCoercion - */ - public function matches(InstrumentationScopeInterface $scope): bool - { - return (bool) preg_match($this->pattern, $scope->getName()); - } -} diff --git a/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php b/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php deleted file mode 100644 index 6224c5497..000000000 --- a/src/SDK/Common/InstrumentationScope/ScopeConfigurator.php +++ /dev/null @@ -1,13 +0,0 @@ -|null $configurator */ public function __construct( private readonly LoggerSharedState $loggerSharedState, private readonly InstrumentationScopeInterface $scope, - ?ScopeConfigurator $configurator = null, + ?Configurator $configurator = null, ) { - $this->config = $configurator ? $configurator->getConfig($scope) : Config::default(); + $this->config = $configurator ? $configurator->resolve($scope) : LoggerConfig::default(); } public function emit(LogRecord $logRecord): void @@ -58,8 +57,11 @@ public function isEnabled(): bool return $this->config->isEnabled(); } + /** + * @param Configurator $configurator + */ public function updateConfig(Configurator $configurator): void { - $this->config = $configurator->getConfig($this->scope); + $this->config = $configurator->resolve($this->scope); } } diff --git a/src/SDK/Logs/LoggerConfig.php b/src/SDK/Logs/LoggerConfig.php new file mode 100644 index 000000000..2c126f34e --- /dev/null +++ b/src/SDK/Logs/LoggerConfig.php @@ -0,0 +1,18 @@ +|null $configurator + */ public function __construct( LogRecordProcessorInterface $processor, private readonly InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null, - ?ScopeConfigurator $configurator = null, + private ?Configurator $configurator = null, ) { $this->loggerSharedState = new LoggerSharedState( $resource ?? ResourceInfoFactory::defaultResource(), @@ -32,7 +33,6 @@ public function __construct( $processor ); $this->loggers = new WeakMap(); - $this->configurator = $configurator ?? Configurator::default(); } /** @@ -70,7 +70,7 @@ public static function builder(): LoggerProviderBuilder * reconfigure all loggers created from the provider. * @experimental */ - public function updateConfigurator(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; foreach ($this->loggers as $logger => $unused) { diff --git a/src/SDK/Logs/LoggerProviderBuilder.php b/src/SDK/Logs/LoggerProviderBuilder.php index 15302babd..6dabdb308 100644 --- a/src/SDK/Logs/LoggerProviderBuilder.php +++ b/src/SDK/Logs/LoggerProviderBuilder.php @@ -38,7 +38,7 @@ public function build(): LoggerProviderInterface $this->buildProcessor(), new InstrumentationScopeFactory(Attributes::factory()), $this->resource, - configurator: $this->configurator ?? Configurator::default(), + configurator: $this->configurator ?? Configurator::logger(), ); } diff --git a/src/SDK/Logs/NoopLoggerProvider.php b/src/SDK/Logs/NoopLoggerProvider.php index 428789f01..f27fad10d 100644 --- a/src/SDK/Logs/NoopLoggerProvider.php +++ b/src/SDK/Logs/NoopLoggerProvider.php @@ -6,7 +6,7 @@ use OpenTelemetry\API\Logs\LoggerInterface; use OpenTelemetry\API\Logs\NoopLogger; -use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; class NoopLoggerProvider implements LoggerProviderInterface { @@ -32,7 +32,7 @@ public function forceFlush(): bool return true; } - public function updateConfigurator(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { //no-op } diff --git a/src/SDK/Metrics/Meter.php b/src/SDK/Metrics/Meter.php index 563b93ef3..40eb129ae 100644 --- a/src/SDK/Metrics/Meter.php +++ b/src/SDK/Metrics/Meter.php @@ -23,7 +23,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurable; -use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; +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; @@ -61,9 +61,9 @@ public function __construct( private readonly MetricRegistryInterface $registry, private readonly MetricWriterInterface $writer, private readonly ArrayAccess $destructors, - private ScopeConfigurator $configurator, + private ?Configurator $configurator = null, ) { - $this->config = $this->configurator->getConfig($this->instrumentationScope); + $this->config = $this->configurator?->resolve($this->instrumentationScope) ?? MeterConfig::default(); } private static function dummyInstrument(): Instrument @@ -76,10 +76,10 @@ private static function dummyInstrument(): Instrument /** * @internal */ - public function updateConfigurator(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; - $this->config = $configurator->getConfig($this->instrumentationScope); + $this->config = $configurator->resolve($this->instrumentationScope); } public function batchObserve(callable $callback, AsynchronousInstrument $instrument, AsynchronousInstrument ...$instruments): ObservableCallbackInterface diff --git a/src/SDK/Metrics/MeterConfig.php b/src/SDK/Metrics/MeterConfig.php new file mode 100644 index 000000000..58ca9591c --- /dev/null +++ b/src/SDK/Metrics/MeterConfig.php @@ -0,0 +1,18 @@ + $metricReaders @@ -48,7 +46,7 @@ public function __construct( private readonly ?ExemplarFilterInterface $exemplarFilter, private readonly StalenessHandlerFactoryInterface $stalenessHandlerFactory, MetricFactoryInterface $metricFactory = null, - ?ScopeConfigurator $configurator = null, + private ?Configurator $configurator = null, ) { $this->metricFactory = $metricFactory ?? new StreamFactory(); $this->instruments = new MeterInstruments(); @@ -58,7 +56,6 @@ public function __construct( $this->writer = $registry; $this->destructors = new WeakMap(); $this->meters = new WeakMap(); - $this->configurator = $configurator ?? Configurator::default(); } public function getMeter( @@ -136,7 +133,7 @@ public static function builder(): MeterProviderBuilder * @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(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; diff --git a/src/SDK/Metrics/MeterProviderBuilder.php b/src/SDK/Metrics/MeterProviderBuilder.php index c2fc5182b..7aec06804 100644 --- a/src/SDK/Metrics/MeterProviderBuilder.php +++ b/src/SDK/Metrics/MeterProviderBuilder.php @@ -75,7 +75,7 @@ public function build(): MeterProviderInterface new CriteriaViewRegistry(), $this->exemplarFilter ?? new WithSampledTraceExemplarFilter(), new NoopStalenessHandlerFactory(), - configurator: $this->configurator ?? Configurator::default(), + configurator: $this->configurator ?? Configurator::meter(), ); } } diff --git a/src/SDK/Metrics/NoopMeterProvider.php b/src/SDK/Metrics/NoopMeterProvider.php index 3f02068e9..2af13f206 100644 --- a/src/SDK/Metrics/NoopMeterProvider.php +++ b/src/SDK/Metrics/NoopMeterProvider.php @@ -6,7 +6,7 @@ use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\Noop\NoopMeter; -use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; class NoopMeterProvider implements MeterProviderInterface { @@ -25,7 +25,7 @@ public function getMeter(string $name, ?string $version = null, ?string $schemaU return new NoopMeter(); } - public function updateConfigurator(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { // no-op } diff --git a/src/SDK/Trace/NoopTracerProvider.php b/src/SDK/Trace/NoopTracerProvider.php index f062988fc..e29edbf8a 100644 --- a/src/SDK/Trace/NoopTracerProvider.php +++ b/src/SDK/Trace/NoopTracerProvider.php @@ -6,7 +6,7 @@ use OpenTelemetry\API; use OpenTelemetry\SDK\Common\Future\CancellationInterface; -use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; +use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; class NoopTracerProvider extends API\Trace\NoopTracerProvider implements TracerProviderInterface { @@ -20,7 +20,7 @@ public function shutdown(?CancellationInterface $cancellation = null): bool return true; } - public function updateConfigurator(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { } } diff --git a/src/SDK/Trace/Tracer.php b/src/SDK/Trace/Tracer.php index ccd861b64..8e67a90f2 100644 --- a/src/SDK/Trace/Tracer.php +++ b/src/SDK/Trace/Tracer.php @@ -10,7 +10,6 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\ScopeConfigurator; class Tracer implements API\TracerInterface { @@ -20,9 +19,9 @@ class Tracer implements API\TracerInterface public function __construct( private readonly TracerSharedState $tracerSharedState, private readonly InstrumentationScopeInterface $instrumentationScope, - ?ScopeConfigurator $configurator = null, + ?Configurator $configurator = null, ) { - $this->config = $configurator ? $configurator->getConfig($this->instrumentationScope) : Config::default(); + $this->config = $configurator ? $configurator->resolve($this->instrumentationScope) : TracerConfig::default(); } /** @inheritDoc */ @@ -55,6 +54,6 @@ public function isEnabled(): bool public function updateConfig(Configurator $configurator): void { - $this->config = $configurator->getConfig($this->instrumentationScope); + $this->config = $configurator->resolve($this->instrumentationScope); } } diff --git a/src/SDK/Trace/TracerConfig.php b/src/SDK/Trace/TracerConfig.php new file mode 100644 index 000000000..82500c12f --- /dev/null +++ b/src/SDK/Trace/TracerConfig.php @@ -0,0 +1,18 @@ +|SpanProcessorInterface|null $spanProcessors */ @@ -34,7 +32,7 @@ public function __construct( SpanLimits $spanLimits = null, IdGeneratorInterface $idGenerator = null, ?InstrumentationScopeFactoryInterface $instrumentationScopeFactory = null, - ?ScopeConfigurator $configurator = null, + private ?Configurator $configurator = null, ) { $spanProcessors ??= []; $spanProcessors = is_array($spanProcessors) ? $spanProcessors : [$spanProcessors]; @@ -52,7 +50,6 @@ public function __construct( ); $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); $this->tracers = new WeakMap(); - $this->configurator = $configurator ?? Configurator::default(); } public function forceFlush(?CancellationInterface $cancellation = null): bool @@ -111,7 +108,7 @@ public static function builder(): TracerProviderBuilder * reconfigure all tracers created from the provider. * @experimental */ - public function updateConfigurator(ScopeConfigurator $configurator): void + public function updateConfigurator(Configurator $configurator): void { $this->configurator = $configurator; diff --git a/src/SDK/Trace/TracerProviderBuilder.php b/src/SDK/Trace/TracerProviderBuilder.php index 667d34ea6..7403a2c91 100644 --- a/src/SDK/Trace/TracerProviderBuilder.php +++ b/src/SDK/Trace/TracerProviderBuilder.php @@ -49,7 +49,7 @@ public function build(): TracerProviderInterface $this->spanProcessors, $this->sampler, $this->resource, - configurator: $this->configurator ?? Configurator::default(), + configurator: $this->configurator ?? Configurator::tracer(), ); } } diff --git a/tests/Benchmark/MetricBench.php b/tests/Benchmark/MetricBench.php index a12af8119..623604dbf 100644 --- a/tests/Benchmark/MetricBench.php +++ b/tests/Benchmark/MetricBench.php @@ -7,8 +7,7 @@ use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; +use OpenTelemetry\SDK\Metrics\MeterConfig; use OpenTelemetry\SDK\Metrics\MeterProvider; use OpenTelemetry\SDK\Metrics\MetricExporter\NoopMetricExporter; use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader; @@ -26,9 +25,8 @@ public function __construct() $meterProvider = MeterProvider::builder() ->addReader($this->reader) ->setConfigurator( - Configurator::builder() - ->addCondition(new Name('disabled'), State::DISABLED) - ->build() + Configurator::meter() + ->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'disabled') ) ->build(); $this->enabled = $meterProvider->getMeter('enabled'); diff --git a/tests/Integration/SDK/Logs/LoggerConfigTest.php b/tests/Integration/SDK/Logs/LoggerConfigTest.php index ad2646f45..8976265f5 100644 --- a/tests/Integration/SDK/Logs/LoggerConfigTest.php +++ b/tests/Integration/SDK/Logs/LoggerConfigTest.php @@ -7,9 +7,8 @@ use ArrayObject; use OpenTelemetry\API\Logs\LogRecord; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -30,9 +29,8 @@ public function test_disable_scope_then_enable(): void $loggerProvider = LoggerProvider::builder() ->addLogRecordProcessor(new SimpleLogRecordProcessor($exporter)) ->setConfigurator( - Configurator::builder() - ->addCondition(new Name('two'), State::DISABLED) //disable logger named 'two' - ->build() + Configurator::logger() + ->with(static fn (LoggerConfig $config) => $config->setDisabled(true), name: 'two') ) ->build(); $this->assertInstanceOf(LoggerProvider::class, $loggerProvider); @@ -51,7 +49,7 @@ public function test_disable_scope_then_enable(): void $logger_two->emit(new LogRecord()); $this->assertCount(1, $storage, 'no record emitted'); - $loggerProvider->updateConfigurator(Configurator::builder()->build()); //re-enable all + $loggerProvider->updateConfigurator(Configurator::logger()); //re-enable all $this->assertTrue($logger_one->isEnabled()); $this->assertTrue($logger_two->isEnabled()); $this->assertTrue($logger_three->isEnabled()); diff --git a/tests/Integration/SDK/Metrics/MeterConfigTest.php b/tests/Integration/SDK/Metrics/MeterConfigTest.php index 9eaf1c957..63ca4e408 100644 --- a/tests/Integration/SDK/Metrics/MeterConfigTest.php +++ b/tests/Integration/SDK/Metrics/MeterConfigTest.php @@ -7,9 +7,8 @@ use OpenTelemetry\API\Common\Time\TestClock; use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -29,9 +28,8 @@ public function test_disable_scopes(): void $meterProvider = MeterProvider::builder() ->addReader(new ExportingReader(new InMemoryExporter())) ->setConfigurator( - Configurator::builder() - ->addCondition(new Name('two'), State::DISABLED) - ->build() + Configurator::meter() + ->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'two') ) ->build(); @@ -58,7 +56,7 @@ public function test_disable_scopes(): void $this->assertFalse($meter_two->isEnabled()); $this->assertTrue($meter_three->isEnabled()); - $meterProvider->updateConfigurator(Configurator::default()); + $meterProvider->updateConfigurator(Configurator::meter()); $this->assertTrue($meter_two->isEnabled()); @@ -78,9 +76,8 @@ public function test_metrics_not_exported_when_disabled(): void $meterProvider = MeterProvider::builder() ->addReader($reader) ->setConfigurator( - Configurator::builder() - ->addCondition(new Name('*'), State::DISABLED) - ->build() + Configurator::meter() + ->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: '*') ) ->build(); $meter = $meterProvider->getMeter('test'); @@ -106,9 +103,8 @@ 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::builder() - ->addCondition(new Name('*'), State::DISABLED) - ->build(); + $disabledConfigurator = Configurator::meter() + ->with(static fn (MeterConfig $config) => $config->setDisabled(false), name: '*'); $exporter = new InMemoryExporter(Temporality::CUMULATIVE); $reader = new ExportingReader($exporter); $meterProvider = MeterProvider::builder() @@ -128,7 +124,7 @@ public function test_streams_recreated_on_enable(): void //t2, {sum=100, startTimestamp=t2}; must not export {sum=101, startTimestamp=t0} $clock->setTime(self::T2); - $meterProvider->updateConfigurator(Configurator::default()); + $meterProvider->updateConfigurator(Configurator::meter()); $c->add(100); $reader->collect(); diff --git a/tests/Integration/SDK/Trace/TracerConfigTest.php b/tests/Integration/SDK/Trace/TracerConfigTest.php index 9c835ecf2..439eb38cd 100644 --- a/tests/Integration/SDK/Trace/TracerConfigTest.php +++ b/tests/Integration/SDK/Trace/TracerConfigTest.php @@ -6,11 +6,10 @@ use ArrayObject; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -29,7 +28,11 @@ public function test_disable_scopes(): void $exporter = new InMemoryExporter($storage); $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) - ->setConfigurator(Configurator::builder()->addCondition(new Predicate\Name('B'), State::DISABLED)->build()) //disable tracer B + ->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'); @@ -82,9 +85,8 @@ public function test_disable_scope_then_enable(): void $tracerProvider = TracerProvider::builder() ->addSpanProcessor(new SimpleSpanProcessor($exporter)) ->setConfigurator( - Configurator::builder() - ->addCondition(new Predicate\Name('B'), State::DISABLED) //disable tracer B - ->build() + Configurator::tracer() + ->with(static fn (TracerConfig $config) => $config->setDisabled(true), name: 'B') ) ->build(); $tracerA = $tracerProvider->getTracer('A'); @@ -100,7 +102,7 @@ public function test_disable_scope_then_enable(): void $child = $tracerB->spanBuilder('child')->startSpan(); $child->setAttribute('b', 1); $childScope = $child->activate(); - $tracerProvider->updateConfigurator(new Configurator()); //re-enable tracer two + $tracerProvider->updateConfigurator(Configurator::tracer()); //re-enable tracer two $sibling = $tracerB->spanBuilder('sibling')->startSpan(); $siblingScope = $sibling->activate(); @@ -146,17 +148,15 @@ public function test_reenable_enables_tracer(): void { $tracerProvider = TracerProvider::builder() ->setConfigurator( - Configurator::builder() - ->addCondition(new Predicate\Name('two'), State::DISABLED) //disable tracer A - ->build() + 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()); - $update = new Configurator(); - $tracerProvider->updateConfigurator($update); + $tracerProvider->updateConfigurator(Configurator::tracer()); //reset $this->assertTrue($tracer->isEnabled()); } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php deleted file mode 100644 index 42120317d..000000000 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConditionTest.php +++ /dev/null @@ -1,56 +0,0 @@ -createMock(Predicate::class); - $predicate->expects($this->once())->method('matches')->willReturn(true); - $condition = new Condition($predicate, State::DISABLED); - $this->assertTrue($condition->matches($this->createMock(InstrumentationScopeInterface::class))); - } - - #[DataProvider('conditionsProvider')] - public function test_conditions(Predicate $predicate, bool $match): void - { - $condition = new Condition($predicate, State::ENABLED); - $scope = new InstrumentationScope('two', null, null, Attributes::create(['foo' => 'bar'])); - $this->assertSame($match, $condition->matches($scope)); - } - - public static function conditionsProvider(): array - { - return [ - 'match name' => [new Predicate\Name('two'), true], - 'no match name' => [new Predicate\Name('one'), false], - 'attribute exists' => [new Predicate\AttributeExists('foo'), true], - 'attribute does not exist' => [new Predicate\Attribute('bar', 'anything'), false], - 'attributes matches' => [new Predicate\Attribute('foo', 'bar'), true], - 'attribute does not match' => [new Predicate\Attribute('foo', 'no-match'), false], - ]; - } - - public function test_state(): void - { - $condition = new Condition($this->createMock(Predicate::class), State::DISABLED); - $this->assertSame(State::DISABLED, $condition->state()); - } -} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php index 9176beb67..cb152621b 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConfigTest.php @@ -5,32 +5,42 @@ namespace OpenTelemetry\Tests\Unit\SDK\Common\InstrumentationScope; use OpenTelemetry\SDK\Common\InstrumentationScope\Config; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; +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(Config::class)] +#[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(State $state, bool $expected): void + public function test_is_enabled(bool $disabled, bool $expected): void { - $config = new Config($state); - $this->assertSame($expected, $config->isEnabled()); + $this->config->setDisabled($disabled); + $this->assertSame($expected, $this->config->isEnabled()); } public static function enabledProvider(): array { return [ - [State::ENABLED, true], - [State::DISABLED, false], + [false, true], + [true, false], ]; } public function test_default_is_enabled(): void { - $config = Config::default(); + $config = TracerConfig::default(); $this->assertTrue($config->isEnabled()); } } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php b/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php index 57843d609..40c80d0b6 100644 --- a/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php +++ b/tests/Unit/SDK/Common/InstrumentationScope/ConfiguratorTest.php @@ -6,50 +6,44 @@ 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 OpenTelemetry\SDK\Common\InstrumentationScope\ConfiguratorBuilder; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; #[CoversClass(Configurator::class)] -#[CoversClass(ConfiguratorBuilder::class)] class ConfiguratorTest extends TestCase { - /** @var Predicate&MockObject */ - private Predicate $predicate; private Configurator $configurator; private InstrumentationScope $scope; public function setUp(): void { - $this->scope = new InstrumentationScope('test', null, null, $this->createMock(AttributesInterface::class)); - $builder = new ConfiguratorBuilder(); - $this->predicate = $this->createMock(Predicate::class); - $builder->addCondition($this->predicate, State::DISABLED); - $this->configurator = $builder->build(); + $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(): void + public function test_match_name(): void { - $this->predicate->expects($this->once())->method('matches')->with($this->equalTo($this->scope))->willReturn(true); - $config = $this->configurator->getConfig($this->scope); - - $this->assertFalse($config->isEnabled()); + $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 { - $this->predicate->expects($this->once())->method('matches')->with($this->equalTo($this->scope))->willReturn(false); - $config = $this->configurator->getConfig($this->scope); + $config = $this->configurator->resolve($this->scope); $this->assertTrue($config->isEnabled()); } - - public function test_builder(): void - { - $this->assertInstanceOf(ConfiguratorBuilder::class, Configurator::builder()); - } } diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php deleted file mode 100644 index 3391b8ff0..000000000 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeExistsTest.php +++ /dev/null @@ -1,31 +0,0 @@ -createMock(InstrumentationScopeInterface::class); - $attributes = $this->createMock(AttributesInterface::class); - $scope->method('getAttributes')->willReturn($attributes); - $attributes->method('has')->willReturnCallback(function (string $key) { - return $key === 'foo'; - }); - - $predicate = new AttributeExists('foo'); - $this->assertTrue($predicate->matches($scope)); - - $predicate = new AttributeExists('bar'); - $this->assertFalse($predicate->matches($scope)); - } -} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php deleted file mode 100644 index 4b44655fd..000000000 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/AttributeTest.php +++ /dev/null @@ -1,51 +0,0 @@ - 'bar'], 0); - $scope = $this->createMock(InstrumentationScopeInterface::class); - $scope->method('getAttributes')->willReturn($attributes); - - $this->assertSame($expected, $predicate->matches($scope)); - } - - public static function matchProvider(): array - { - return [ - 'found and matches' => [ - new Attribute('foo', 'bar'), - true, - ], - 'found but does not match' => [ - new Attribute('foo', 'baz'), - false, - ], - 'no attribute found' => [ - new Attribute('bar', 'bat'), - false, - ], - ]; - } - - public function test_construct(): void - { - $p = new Attribute('foo', 'bar'); - $this->assertInstanceOf(Attribute::class, $p); - } -} diff --git a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php b/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php deleted file mode 100644 index 606ae8c21..000000000 --- a/tests/Unit/SDK/Common/InstrumentationScope/Predicate/NameTest.php +++ /dev/null @@ -1,43 +0,0 @@ -url(), - $this->createMock(AttributesInterface::class), - ); - $this->assertSame($expected, (new Name($pattern))->matches($scope)); - } - - public static function nameProvider(): array - { - return [ - ['io.opentelemetry.php.example.foo', true], - ['io.opentelemetry.php.example.*', true], - ['io.opentelemetry.php.*', true], - ['*', true], - ['foo', false], - ['*.foo', true], - ['*.bar', false], - ['*.?oo', true], - ]; - } -} diff --git a/tests/Unit/SDK/Logs/LoggerProviderTest.php b/tests/Unit/SDK/Logs/LoggerProviderTest.php index 530471712..aab31318a 100644 --- a/tests/Unit/SDK/Logs/LoggerProviderTest.php +++ b/tests/Unit/SDK/Logs/LoggerProviderTest.php @@ -5,12 +5,12 @@ 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\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -36,10 +36,11 @@ public function setUp(): void { $this->processor = $this->createMock(LogRecordProcessorInterface::class); $instrumentationScopeFactory = $this->createMock(InstrumentationScopeFactoryInterface::class); + $instrumentationScopeFactory->method('create')->willReturn($this->createMock(InstrumentationScope::class)); $resource = $this->createMock(ResourceInfo::class); - $this->config = $this->createMock(Config::class); + $this->config = $this->createMock(LoggerConfig::class); $configurator = $this->createMock(Configurator::class); - $configurator->method('getConfig')->willReturn($this->config); + $configurator->method('resolve')->willReturn($this->config); $this->provider = new LoggerProvider($this->processor, $instrumentationScopeFactory, $resource, $configurator); } @@ -91,7 +92,7 @@ public function test_update_configurator_updates_loggers(): void $this->assertTrue($one->isEnabled()); $this->assertTrue($two->isEnabled()); - $lp->updateConfigurator(Configurator::builder()->addCondition(new Name('*'), State::DISABLED)->build()); + $lp->updateConfigurator(Configurator::logger()->with(static fn (LoggerConfig $config) => $config->setDisabled(true), name: '*')); $this->assertFalse($one->isEnabled()); $this->assertFalse($two->isEnabled()); } diff --git a/tests/Unit/SDK/Logs/LoggerTest.php b/tests/Unit/SDK/Logs/LoggerTest.php index aeb0f53fb..0b9735203 100644 --- a/tests/Unit/SDK/Logs/LoggerTest.php +++ b/tests/Unit/SDK/Logs/LoggerTest.php @@ -11,9 +11,8 @@ use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -125,7 +124,7 @@ public function test_enabled(): void public function test_does_not_log_if_disabled(): void { - $configurator = Configurator::builder()->addCondition(new Name('foo'), State::DISABLED)->build(); + $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()); diff --git a/tests/Unit/SDK/Metrics/MeterProviderTest.php b/tests/Unit/SDK/Metrics/MeterProviderTest.php index 17eeced23..7df3c7802 100644 --- a/tests/Unit/SDK/Metrics/MeterProviderTest.php +++ b/tests/Unit/SDK/Metrics/MeterProviderTest.php @@ -11,9 +11,8 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -118,7 +117,7 @@ public function test_disable(): void $this->assertTrue($meter->isEnabled()); $counter = $meter->createCounter('A'); $this->assertTrue($counter->isEnabled()); - $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('one'), State::DISABLED)->build()); + $meterProvider->updateConfigurator(Configurator::meter()->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'one')); $this->assertFalse($meter->isEnabled()); $this->assertFalse($counter->isEnabled()); } diff --git a/tests/Unit/SDK/Metrics/MeterTest.php b/tests/Unit/SDK/Metrics/MeterTest.php index 79ea0c9c7..1558e7ca1 100644 --- a/tests/Unit/SDK/Metrics/MeterTest.php +++ b/tests/Unit/SDK/Metrics/MeterTest.php @@ -10,13 +10,12 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScope; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -385,7 +384,7 @@ public function test_update_configurator(): void $meterProvider = $this->createMeterProviderForMetricFactory($metricFactory); $meter = $meterProvider->getMeter('test'); $this->assertTrue($meter->isEnabled()); - $meterProvider->updateConfigurator(Configurator::builder()->addCondition(new Name('test'), State::DISABLED)->build()); + $meterProvider->updateConfigurator(Configurator::meter()->with(static fn (MeterConfig $config) => $config->setDisabled(true), name: 'test')); $this->assertFalse($meter->isEnabled()); } diff --git a/tests/Unit/SDK/Trace/TracerProviderTest.php b/tests/Unit/SDK/Trace/TracerProviderTest.php index b84d9dcfc..0429e182a 100644 --- a/tests/Unit/SDK/Trace/TracerProviderTest.php +++ b/tests/Unit/SDK/Trace/TracerProviderTest.php @@ -6,9 +6,8 @@ use OpenTelemetry\API\Trace\NoopTracer; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; -use OpenTelemetry\SDK\Common\InstrumentationScope\Predicate\Name; -use OpenTelemetry\SDK\Common\InstrumentationScope\State; 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; @@ -107,7 +106,7 @@ public function test_update_configurator_updates_tracers(): void $this->assertTrue($one->isEnabled()); $this->assertTrue($two->isEnabled()); - $tp->updateConfigurator(Configurator::builder()->addCondition(new Name('*'), State::DISABLED)->build()); + $tp->updateConfigurator(Configurator::tracer()->with(static fn (TracerConfig $config) => $config->setDisabled(true), name: '*')); $this->assertFalse($one->isEnabled()); $this->assertFalse($two->isEnabled()); }