From add7191e6c3689bc6f439fe90526df1f0aa45e04 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 1 Jul 2024 18:17:07 +1000 Subject: [PATCH 01/13] initial port from Nevay/otel-sdk-contrib-sampler --- .../RuleBased/AlwaysRecordingSampler.php | 39 +++++++++ .../AlwaysRecordingSamplingResult.php | 31 +++++++ .../Configuration/SamplerAlwaysRecording.php | 35 ++++++++ .../Configuration/SamplerRuleBased.php | 63 ++++++++++++++ .../Configuration/SamplingRuleAttribute.php | 45 ++++++++++ .../Configuration/SamplingRuleLink.php | 37 ++++++++ .../Configuration/SamplingRuleParent.php | 37 ++++++++ .../Configuration/SamplingRuleSpanKind.php | 50 +++++++++++ .../Configuration/SamplingRuleSpanName.php | 38 ++++++++ src/Sampler/RuleBased/README.md | 87 +++++++++++++++++++ src/Sampler/RuleBased/RuleBasedSampler.php | 50 +++++++++++ src/Sampler/RuleBased/RuleSet.php | 21 +++++ src/Sampler/RuleBased/SamplingRule.php | 35 ++++++++ .../RuleBased/SamplingRule/AttributeRule.php | 36 ++++++++ .../RuleBased/SamplingRule/LinkRule.php | 46 ++++++++++ .../RuleBased/SamplingRule/ParentRule.php | 40 +++++++++ .../RuleBased/SamplingRule/SpanKindRule.php | 33 +++++++ .../RuleBased/SamplingRule/SpanNameRule.php | 31 +++++++ src/Sampler/RuleBased/composer.json | 36 ++++++++ 19 files changed, 790 insertions(+) create mode 100644 src/Sampler/RuleBased/AlwaysRecordingSampler.php create mode 100644 src/Sampler/RuleBased/AlwaysRecordingSamplingResult.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplerAlwaysRecording.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplerRuleBased.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplingRuleAttribute.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplingRuleLink.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplingRuleParent.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplingRuleSpanKind.php create mode 100644 src/Sampler/RuleBased/Configuration/SamplingRuleSpanName.php create mode 100644 src/Sampler/RuleBased/README.md create mode 100644 src/Sampler/RuleBased/RuleBasedSampler.php create mode 100644 src/Sampler/RuleBased/RuleSet.php create mode 100644 src/Sampler/RuleBased/SamplingRule.php create mode 100644 src/Sampler/RuleBased/SamplingRule/AttributeRule.php create mode 100644 src/Sampler/RuleBased/SamplingRule/LinkRule.php create mode 100644 src/Sampler/RuleBased/SamplingRule/ParentRule.php create mode 100644 src/Sampler/RuleBased/SamplingRule/SpanKindRule.php create mode 100644 src/Sampler/RuleBased/SamplingRule/SpanNameRule.php create mode 100644 src/Sampler/RuleBased/composer.json diff --git a/src/Sampler/RuleBased/AlwaysRecordingSampler.php b/src/Sampler/RuleBased/AlwaysRecordingSampler.php new file mode 100644 index 00000000..74327fce --- /dev/null +++ b/src/Sampler/RuleBased/AlwaysRecordingSampler.php @@ -0,0 +1,39 @@ +sampler->shouldSample($context, $traceId, $spanName, $spanKind, $attributes, $links); + if (!$result->shouldRecord()) { + $result = new AlwaysRecordingSamplingResult($result); + } + + return $result; + } + + public function __toString(): string { + return sprintf('AlwaysRecordingSampler{%s}', $this->sampler); + } +} diff --git a/src/Sampler/RuleBased/AlwaysRecordingSamplingResult.php b/src/Sampler/RuleBased/AlwaysRecordingSamplingResult.php new file mode 100644 index 00000000..dfda9b94 --- /dev/null +++ b/src/Sampler/RuleBased/AlwaysRecordingSamplingResult.php @@ -0,0 +1,31 @@ +samplingResult->traceFlags(); + } + + public function traceState(): ?TraceStateInterface { + return $this->samplingResult->traceState(); + } + + public function additionalAttributes(): iterable { + return $this->samplingResult->additionalAttributes(); + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplerAlwaysRecording.php b/src/Sampler/RuleBased/Configuration/SamplerAlwaysRecording.php new file mode 100644 index 00000000..c3e44226 --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplerAlwaysRecording.php @@ -0,0 +1,35 @@ + + * } $properties + */ + public function createPlugin(array $properties, Context $context): Sampler { + return new AlwaysRecordingSampler( + $properties['sampler']->create($context), + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('always_recording'); + $node + ->children() + ->append($registry->component('sampler', Sampler::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplerRuleBased.php b/src/Sampler/RuleBased/Configuration/SamplerRuleBased.php new file mode 100644 index 00000000..1559da79 --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplerRuleBased.php @@ -0,0 +1,63 @@ +>, + * delegate: ComponentPlugin, + * }>, + * fallback: ComponentPlugin, + * } $properties + */ + public function createPlugin(array $properties, Context $context): Sampler { + $ruleSets = []; + foreach ($properties['rule_sets'] as $ruleSet) { + $samplingRules = []; + foreach ($ruleSet['rules'] as $rule) { + $samplingRules[] = $rule->create($context); + } + + $ruleSets[] = new RuleSet( + $samplingRules, + $ruleSet['delegate']->create($context), + ); + } + + return new RuleBasedSampler( + $ruleSets, + $properties['fallback']->create($context), + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('rule_based'); + $node + ->children() + ->arrayNode('rule_sets') + ->arrayPrototype() + ->children() + ->append($registry->componentList('rules', SamplingRule::class)->isRequired()->cannotBeEmpty()) + ->append($registry->component('delegate', Sampler::class)->isRequired()) + ->end() + ->end() + ->end() + ->append($registry->component('fallback', Sampler::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleAttribute.php b/src/Sampler/RuleBased/Configuration/SamplingRuleAttribute.php new file mode 100644 index 00000000..1635835f --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplingRuleAttribute.php @@ -0,0 +1,45 @@ +children() + ->scalarNode('key') + ->isRequired() + ->cannotBeEmpty() + ->validate()->always(Validation::ensureString())->end() + ->end() + ->scalarNode('pattern') + ->isRequired() + ->validate()->always(Validation::ensureRegexPattern())->end() + ->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleLink.php b/src/Sampler/RuleBased/Configuration/SamplingRuleLink.php new file mode 100644 index 00000000..a8104cb4 --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplingRuleLink.php @@ -0,0 +1,37 @@ +children() + ->booleanNode('sampled')->isRequired()->end() + ->booleanNode('remote')->defaultNull()->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleParent.php b/src/Sampler/RuleBased/Configuration/SamplingRuleParent.php new file mode 100644 index 00000000..5f4a8eec --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplingRuleParent.php @@ -0,0 +1,37 @@ +children() + ->booleanNode('sampled')->isRequired()->end() + ->booleanNode('remote')->defaultNull()->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleSpanKind.php b/src/Sampler/RuleBased/Configuration/SamplingRuleSpanKind.php new file mode 100644 index 00000000..8c8f7da4 --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplingRuleSpanKind.php @@ -0,0 +1,50 @@ + Kind::Internal, + 'CLIENT' => Kind::Client, + 'SERVER' => Kind::Server, + 'PRODUCER' => Kind::Producer, + 'CONSUMER' => Kind::Consumer, + }, + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('span_kind'); + $node + ->children() + ->enumNode('kind') + ->isRequired() + ->values([ + 'INTERNAL', + 'CLIENT', + 'SERVER', + 'PRODUCER', + 'CONSUMER', + ]) + ->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleSpanName.php b/src/Sampler/RuleBased/Configuration/SamplingRuleSpanName.php new file mode 100644 index 00000000..9e460738 --- /dev/null +++ b/src/Sampler/RuleBased/Configuration/SamplingRuleSpanName.php @@ -0,0 +1,38 @@ +children() + ->scalarNode('pattern') + ->isRequired() + ->validate()->always(Validation::ensureRegexPattern())->end() + ->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Sampler/RuleBased/README.md b/src/Sampler/RuleBased/README.md new file mode 100644 index 00000000..7d285347 --- /dev/null +++ b/src/Sampler/RuleBased/README.md @@ -0,0 +1,87 @@ +# Contrib Sampler + +Provides additional samplers that are not part of the official specification. + +## Installation + +```shell +composer require tbachert/otel-sdk-contrib-sampler +``` + +## RuleBasedSampler + +Allows sampling based on a list of rule sets. The first matching rule set will decide the sampling result. + +```php +$sampler = new RuleBasedSampler( + [ + new RuleSet( + [ + new SpanKindRule(Kind::Server), + new AttributeRule('url.path', '~^/health$~'), + ], + new AlwaysOffSampler(), + ), + ], + new AlwaysOnSampler(), +); +``` + +### Configuration + +###### Example: drop spans for the /health endpoint + +```yaml +rule_based: + rule_sets: + - rules: + - span_kind: { kind: SERVER } + - attribute: { key: url.path, pattern: ~^/health$~ } + delegate: + always_off: {} + fallback: # ... +``` + +###### Example: sample spans with at least one sampled link + +```yaml +rule_based: + rule_sets: + - rules: [ link: { sampled: true } ] + delegate: + always_on: {} + fallback: # ... +``` + +###### Example: modeling parent based sampler as rule based sampler + +```yaml +rule_based: + rule_sets: + - rules: [ parent: { sampled: true, remote: true } ] + delegate: # remote_parent_sampled + - rules: [ parent: { sampled: false, remote: true } ] + delegate: # remote_parent_not_sampled + - rules: [ parent: { sampled: true, remote: false } ] + delegate: # local_parent_sampled + - rules: [ parent: { sampled: false, remote: false } ] + delegate: # local_parent_not_sampled + fallback: # root +``` + +## AlwaysRecordingSampler + +Records all spans to allow the usage of span processors that generate metrics from spans. + +```php +$sampler = new AlwaysRecordingSampler( + new ParentBasedSampler(new AlwaysOnSampler()), +); +``` + +### Configuration + +```yaml +always_recording: + sampler: # ... +``` diff --git a/src/Sampler/RuleBased/RuleBasedSampler.php b/src/Sampler/RuleBased/RuleBasedSampler.php new file mode 100644 index 00000000..43272730 --- /dev/null +++ b/src/Sampler/RuleBased/RuleBasedSampler.php @@ -0,0 +1,50 @@ + $ruleSets + */ + public function __construct( + private readonly array $ruleSets, + private readonly Sampler $fallback, + ) {} + + public function shouldSample( + ContextInterface $context, + string $traceId, + string $spanName, + Kind $spanKind, + Attributes $attributes, + array $links, + ): SamplingResult { + foreach ($this->ruleSets as $ruleSet) { + foreach ($ruleSet->samplingRules as $samplingRule) { + if (!$samplingRule->matches($context, $traceId, $spanName, $spanKind, $attributes, $links)) { + continue 2; + } + } + + return $ruleSet->delegate->shouldSample($context, $traceId, $spanName, $spanKind, $attributes, $links); + } + + return $this->fallback->shouldSample($context, $traceId, $spanName, $spanKind, $attributes, $links); + } + + public function __toString(): string { + return sprintf('RuleBasedSampler{rules=[%s],fallback=%s}', implode(',', $this->ruleSets), $this->fallback); + } +} diff --git a/src/Sampler/RuleBased/RuleSet.php b/src/Sampler/RuleBased/RuleSet.php new file mode 100644 index 00000000..58b2ce3f --- /dev/null +++ b/src/Sampler/RuleBased/RuleSet.php @@ -0,0 +1,21 @@ + $samplingRules + */ + public function __construct( + public readonly array $samplingRules, + public readonly Sampler $delegate, + ) {} + + public function __toString(): string { + return sprintf('RuleSet{rules=[%s],delegate=%s}', implode(',', $this->samplingRules), $this->delegate); + } +} diff --git a/src/Sampler/RuleBased/SamplingRule.php b/src/Sampler/RuleBased/SamplingRule.php new file mode 100644 index 00000000..b4d44a4c --- /dev/null +++ b/src/Sampler/RuleBased/SamplingRule.php @@ -0,0 +1,35 @@ + $links span links + * @return bool whether this rule matches the given data + * + * @see Sampler::shouldSample() + */ + public function matches( + ContextInterface $context, + string $traceId, + string $spanName, + Kind $spanKind, + Attributes $attributes, + array $links, + ): bool; + + public function __toString(): string; +} diff --git a/src/Sampler/RuleBased/SamplingRule/AttributeRule.php b/src/Sampler/RuleBased/SamplingRule/AttributeRule.php new file mode 100644 index 00000000..c4e1d142 --- /dev/null +++ b/src/Sampler/RuleBased/SamplingRule/AttributeRule.php @@ -0,0 +1,36 @@ +has($this->attributeKey) + && preg_match($this->pattern, (string) $attributes->get($this->attributeKey)); + } + + public function __toString(): string { + return sprintf('Attribute{key=%s,pattern=%s}', $this->attributeKey, $this->pattern); + } +} diff --git a/src/Sampler/RuleBased/SamplingRule/LinkRule.php b/src/Sampler/RuleBased/SamplingRule/LinkRule.php new file mode 100644 index 00000000..09b30b41 --- /dev/null +++ b/src/Sampler/RuleBased/SamplingRule/LinkRule.php @@ -0,0 +1,46 @@ +spanContext->isSampled() !== $this->sampled) { + continue; + } + if ($this->remote !== null && $link->spanContext->isRemote() !== $this->remote) { + continue; + } + + return true; + } + + return false; + } + + public function __toString(): string { + return sprintf('Link{sampled=%s,remote=%s}', var_export($this->sampled, true), var_export($this->remote, true)); + } +} diff --git a/src/Sampler/RuleBased/SamplingRule/ParentRule.php b/src/Sampler/RuleBased/SamplingRule/ParentRule.php new file mode 100644 index 00000000..60faeff3 --- /dev/null +++ b/src/Sampler/RuleBased/SamplingRule/ParentRule.php @@ -0,0 +1,40 @@ +getContext(); + + return $parent->isValid() + && $parent->isSampled() === $this->sampled + && ($this->remote === null || $parent->isRemote() === $this->remote); + } + + public function __toString(): string { + return sprintf('Parent{sampled=%s,remote=%s}', var_export($this->sampled, true), var_export($this->remote, true)); + } +} diff --git a/src/Sampler/RuleBased/SamplingRule/SpanKindRule.php b/src/Sampler/RuleBased/SamplingRule/SpanKindRule.php new file mode 100644 index 00000000..abc8b442 --- /dev/null +++ b/src/Sampler/RuleBased/SamplingRule/SpanKindRule.php @@ -0,0 +1,33 @@ +spanKind === $spanKind; + } + + public function __toString(): string { + return sprintf('SpanKind{kind=%s}', $this->spanKind->name); + } +} diff --git a/src/Sampler/RuleBased/SamplingRule/SpanNameRule.php b/src/Sampler/RuleBased/SamplingRule/SpanNameRule.php new file mode 100644 index 00000000..74a03000 --- /dev/null +++ b/src/Sampler/RuleBased/SamplingRule/SpanNameRule.php @@ -0,0 +1,31 @@ +pattern, $spanName); + } + + public function __toString(): string { + return sprintf('SpanName{pattern=%s}', $this->pattern); + } +} diff --git a/src/Sampler/RuleBased/composer.json b/src/Sampler/RuleBased/composer.json new file mode 100644 index 00000000..e1c0662c --- /dev/null +++ b/src/Sampler/RuleBased/composer.json @@ -0,0 +1,36 @@ +{ + "name": "open-telemetry/contrib-sampler-rule-based", + "description": "OpenTelemetry SDK contrib rule-based sampler", + "keywords": ["opentelemetry", "otel", "sdk", "tracing", "sampler"], + "license": "Apache-2.0", + "require": { + "php": "^8.1", + "open-telemetry/sdk": "dev-main as 1.1.0", + "open-telemetry/" + }, + "require-dev": { + "symfony/config": "^5.4 || ^6.4 || ^7.0", + "tbachert/otel-sdk-configuration": "^0.1" + }, + "autoload": { + "psr-4": { + "Nevay\\OTelSDK\\Contrib\\Sampler\\": "" + } + }, + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + }, + "spi": { + "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplerAlwaysRecording", + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplerRuleBased", + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleAttribute", + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleLink", + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleParent", + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleSpanKind", + "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleSpanName" + ] + } + } +} From 5543d3c28e588795639b9cb7c26435e4084dda8d Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 1 Jul 2024 18:23:44 +1000 Subject: [PATCH 02/13] move to src subdir --- src/Sampler/RuleBased/{ => src}/AlwaysRecordingSampler.php | 0 src/Sampler/RuleBased/{ => src}/AlwaysRecordingSamplingResult.php | 0 .../RuleBased/{ => src}/Configuration/SamplerAlwaysRecording.php | 0 .../RuleBased/{ => src}/Configuration/SamplerRuleBased.php | 0 .../RuleBased/{ => src}/Configuration/SamplingRuleAttribute.php | 0 .../RuleBased/{ => src}/Configuration/SamplingRuleLink.php | 0 .../RuleBased/{ => src}/Configuration/SamplingRuleParent.php | 0 .../RuleBased/{ => src}/Configuration/SamplingRuleSpanKind.php | 0 .../RuleBased/{ => src}/Configuration/SamplingRuleSpanName.php | 0 src/Sampler/RuleBased/{ => src}/RuleBasedSampler.php | 0 src/Sampler/RuleBased/{ => src}/RuleSet.php | 0 src/Sampler/RuleBased/{ => src}/SamplingRule.php | 0 src/Sampler/RuleBased/{ => src}/SamplingRule/AttributeRule.php | 0 src/Sampler/RuleBased/{ => src}/SamplingRule/LinkRule.php | 0 src/Sampler/RuleBased/{ => src}/SamplingRule/ParentRule.php | 0 src/Sampler/RuleBased/{ => src}/SamplingRule/SpanKindRule.php | 0 src/Sampler/RuleBased/{ => src}/SamplingRule/SpanNameRule.php | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename src/Sampler/RuleBased/{ => src}/AlwaysRecordingSampler.php (100%) rename src/Sampler/RuleBased/{ => src}/AlwaysRecordingSamplingResult.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplerAlwaysRecording.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplerRuleBased.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplingRuleAttribute.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplingRuleLink.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplingRuleParent.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplingRuleSpanKind.php (100%) rename src/Sampler/RuleBased/{ => src}/Configuration/SamplingRuleSpanName.php (100%) rename src/Sampler/RuleBased/{ => src}/RuleBasedSampler.php (100%) rename src/Sampler/RuleBased/{ => src}/RuleSet.php (100%) rename src/Sampler/RuleBased/{ => src}/SamplingRule.php (100%) rename src/Sampler/RuleBased/{ => src}/SamplingRule/AttributeRule.php (100%) rename src/Sampler/RuleBased/{ => src}/SamplingRule/LinkRule.php (100%) rename src/Sampler/RuleBased/{ => src}/SamplingRule/ParentRule.php (100%) rename src/Sampler/RuleBased/{ => src}/SamplingRule/SpanKindRule.php (100%) rename src/Sampler/RuleBased/{ => src}/SamplingRule/SpanNameRule.php (100%) diff --git a/src/Sampler/RuleBased/AlwaysRecordingSampler.php b/src/Sampler/RuleBased/src/AlwaysRecordingSampler.php similarity index 100% rename from src/Sampler/RuleBased/AlwaysRecordingSampler.php rename to src/Sampler/RuleBased/src/AlwaysRecordingSampler.php diff --git a/src/Sampler/RuleBased/AlwaysRecordingSamplingResult.php b/src/Sampler/RuleBased/src/AlwaysRecordingSamplingResult.php similarity index 100% rename from src/Sampler/RuleBased/AlwaysRecordingSamplingResult.php rename to src/Sampler/RuleBased/src/AlwaysRecordingSamplingResult.php diff --git a/src/Sampler/RuleBased/Configuration/SamplerAlwaysRecording.php b/src/Sampler/RuleBased/src/Configuration/SamplerAlwaysRecording.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplerAlwaysRecording.php rename to src/Sampler/RuleBased/src/Configuration/SamplerAlwaysRecording.php diff --git a/src/Sampler/RuleBased/Configuration/SamplerRuleBased.php b/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplerRuleBased.php rename to src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleAttribute.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplingRuleAttribute.php rename to src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleLink.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplingRuleLink.php rename to src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleParent.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplingRuleParent.php rename to src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleSpanKind.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplingRuleSpanKind.php rename to src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php diff --git a/src/Sampler/RuleBased/Configuration/SamplingRuleSpanName.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php similarity index 100% rename from src/Sampler/RuleBased/Configuration/SamplingRuleSpanName.php rename to src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php diff --git a/src/Sampler/RuleBased/RuleBasedSampler.php b/src/Sampler/RuleBased/src/RuleBasedSampler.php similarity index 100% rename from src/Sampler/RuleBased/RuleBasedSampler.php rename to src/Sampler/RuleBased/src/RuleBasedSampler.php diff --git a/src/Sampler/RuleBased/RuleSet.php b/src/Sampler/RuleBased/src/RuleSet.php similarity index 100% rename from src/Sampler/RuleBased/RuleSet.php rename to src/Sampler/RuleBased/src/RuleSet.php diff --git a/src/Sampler/RuleBased/SamplingRule.php b/src/Sampler/RuleBased/src/SamplingRule.php similarity index 100% rename from src/Sampler/RuleBased/SamplingRule.php rename to src/Sampler/RuleBased/src/SamplingRule.php diff --git a/src/Sampler/RuleBased/SamplingRule/AttributeRule.php b/src/Sampler/RuleBased/src/SamplingRule/AttributeRule.php similarity index 100% rename from src/Sampler/RuleBased/SamplingRule/AttributeRule.php rename to src/Sampler/RuleBased/src/SamplingRule/AttributeRule.php diff --git a/src/Sampler/RuleBased/SamplingRule/LinkRule.php b/src/Sampler/RuleBased/src/SamplingRule/LinkRule.php similarity index 100% rename from src/Sampler/RuleBased/SamplingRule/LinkRule.php rename to src/Sampler/RuleBased/src/SamplingRule/LinkRule.php diff --git a/src/Sampler/RuleBased/SamplingRule/ParentRule.php b/src/Sampler/RuleBased/src/SamplingRule/ParentRule.php similarity index 100% rename from src/Sampler/RuleBased/SamplingRule/ParentRule.php rename to src/Sampler/RuleBased/src/SamplingRule/ParentRule.php diff --git a/src/Sampler/RuleBased/SamplingRule/SpanKindRule.php b/src/Sampler/RuleBased/src/SamplingRule/SpanKindRule.php similarity index 100% rename from src/Sampler/RuleBased/SamplingRule/SpanKindRule.php rename to src/Sampler/RuleBased/src/SamplingRule/SpanKindRule.php diff --git a/src/Sampler/RuleBased/SamplingRule/SpanNameRule.php b/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php similarity index 100% rename from src/Sampler/RuleBased/SamplingRule/SpanNameRule.php rename to src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php From 95f3e3902e17189082a52b77ad02073e02bcfcbe Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 3 Jul 2024 17:24:57 +1000 Subject: [PATCH 03/13] update, tests --- src/Sampler/RuleBased/.gitignore | 1 + src/Sampler/RuleBased/.phan/config.php | 371 ++++++++++++++++++ src/Sampler/RuleBased/.php-cs-fixer.php | 43 ++ src/Sampler/RuleBased/composer.json | 40 +- src/Sampler/RuleBased/phpstan.neon.dist | 9 + src/Sampler/RuleBased/phpunit.xml.dist | 22 ++ src/Sampler/RuleBased/phpunit.xml.dist.bak | 47 +++ src/Sampler/RuleBased/psalm.xml.dist | 15 + .../RuleBased/src/AlwaysRecordingSampler.php | 39 -- .../src/AlwaysRecordingSamplingResult.php | 31 -- .../Configuration/SamplerAlwaysRecording.php | 35 -- .../src/Configuration/SamplerRuleBased.php | 43 +- .../Configuration/SamplingRuleAttribute.php | 28 +- .../src/Configuration/SamplingRuleLink.php | 26 +- .../src/Configuration/SamplingRuleParent.php | 26 +- .../Configuration/SamplingRuleSpanKind.php | 38 +- .../Configuration/SamplingRuleSpanName.php | 28 +- .../RuleBased/src/RuleBasedSampler.php | 49 ++- src/Sampler/RuleBased/src/RuleSet.php | 38 +- .../RuleBased/src/RuleSetInterface.php | 15 + src/Sampler/RuleBased/src/SamplingRule.php | 26 +- .../src/SamplingRule/AttributeRule.php | 25 +- .../RuleBased/src/SamplingRule/LinkRule.php | 30 +- .../RuleBased/src/SamplingRule/ParentRule.php | 25 +- .../src/SamplingRule/SpanKindRule.php | 29 +- .../src/SamplingRule/SpanNameRule.php | 25 +- .../Integration/RuleBasedSamplerTest.php | 26 ++ .../tests/Integration/config/sdk-config.yaml | 25 ++ .../tests/Unit/RuleBasedSamplerTest.php | 92 +++++ .../RuleBased/tests/Unit/RuleSetTest.php | 43 ++ .../Unit/SamplingRule/AttributeRuleTest.php | 48 +++ .../tests/Unit/SamplingRule/LinkRuleTest.php | 66 ++++ .../Unit/SamplingRule/ParentRuleTest.php | 70 ++++ .../Unit/SamplingRule/SpanKindRuleTest.php | 39 ++ .../Unit/SamplingRule/SpanNameRuleTest.php | 41 ++ 35 files changed, 1263 insertions(+), 291 deletions(-) create mode 100644 src/Sampler/RuleBased/.gitignore create mode 100644 src/Sampler/RuleBased/.phan/config.php create mode 100644 src/Sampler/RuleBased/.php-cs-fixer.php create mode 100644 src/Sampler/RuleBased/phpstan.neon.dist create mode 100644 src/Sampler/RuleBased/phpunit.xml.dist create mode 100644 src/Sampler/RuleBased/phpunit.xml.dist.bak create mode 100644 src/Sampler/RuleBased/psalm.xml.dist delete mode 100644 src/Sampler/RuleBased/src/AlwaysRecordingSampler.php delete mode 100644 src/Sampler/RuleBased/src/AlwaysRecordingSamplingResult.php delete mode 100644 src/Sampler/RuleBased/src/Configuration/SamplerAlwaysRecording.php create mode 100644 src/Sampler/RuleBased/src/RuleSetInterface.php create mode 100644 src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php create mode 100644 src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml create mode 100644 src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php create mode 100644 src/Sampler/RuleBased/tests/Unit/RuleSetTest.php create mode 100644 src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php create mode 100644 src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php create mode 100644 src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php create mode 100644 src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php create mode 100644 src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php diff --git a/src/Sampler/RuleBased/.gitignore b/src/Sampler/RuleBased/.gitignore new file mode 100644 index 00000000..723504e3 --- /dev/null +++ b/src/Sampler/RuleBased/.gitignore @@ -0,0 +1 @@ +.phpunit.cache diff --git a/src/Sampler/RuleBased/.phan/config.php b/src/Sampler/RuleBased/.phan/config.php new file mode 100644 index 00000000..6473a9aa --- /dev/null +++ b/src/Sampler/RuleBased/.phan/config.php @@ -0,0 +1,371 @@ + '8.1', + + // If enabled, missing properties will be created when + // they are first seen. If false, we'll report an + // error message if there is an attempt to write + // to a class property that wasn't explicitly + // defined. + 'allow_missing_properties' => false, + + // If enabled, null can be cast to any type and any + // type can be cast to null. Setting this to true + // will cut down on false positives. + 'null_casts_as_any_type' => false, + + // If enabled, allow null to be cast as any array-like type. + // + // This is an incremental step in migrating away from `null_casts_as_any_type`. + // If `null_casts_as_any_type` is true, this has no effect. + 'null_casts_as_array' => true, + + // If enabled, allow any array-like type to be cast to null. + // This is an incremental step in migrating away from `null_casts_as_any_type`. + // If `null_casts_as_any_type` is true, this has no effect. + 'array_casts_as_null' => true, + + // If enabled, scalars (int, float, bool, string, null) + // are treated as if they can cast to each other. + // This does not affect checks of array keys. See `scalar_array_key_cast`. + 'scalar_implicit_cast' => false, + + // If enabled, any scalar array keys (int, string) + // are treated as if they can cast to each other. + // E.g. `array` can cast to `array` and vice versa. + // Normally, a scalar type such as int could only cast to/from int and mixed. + 'scalar_array_key_cast' => true, + + // If this has entries, scalars (int, float, bool, string, null) + // are allowed to perform the casts listed. + // + // E.g. `['int' => ['float', 'string'], 'float' => ['int'], 'string' => ['int'], 'null' => ['string']]` + // allows casting null to a string, but not vice versa. + // (subset of `scalar_implicit_cast`) + 'scalar_implicit_partial' => [], + + // If enabled, Phan will warn if **any** type in a method invocation's object + // is definitely not an object, + // or if **any** type in an invoked expression is not a callable. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_method_checking' => false, + + // If enabled, Phan will warn if **any** type of the object expression for a property access + // does not contain that property. + 'strict_object_checking' => false, + + // If enabled, Phan will warn if **any** type in the argument's union type + // cannot be cast to a type in the parameter's expected union type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_param_checking' => false, + + // If enabled, Phan will warn if **any** type in a property assignment's union type + // cannot be cast to a type in the property's declared union type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_property_checking' => false, + + // If enabled, Phan will warn if **any** type in a returned value's union type + // cannot be cast to the declared return type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_return_checking' => false, + + // If true, seemingly undeclared variables in the global + // scope will be ignored. + // + // This is useful for projects with complicated cross-file + // globals that you have no hope of fixing. + 'ignore_undeclared_variables_in_global_scope' => true, + + // Set this to false to emit `PhanUndeclaredFunction` issues for internal functions that Phan has signatures for, + // but aren't available in the codebase, or from Reflection. + // (may lead to false positives if an extension isn't loaded) + // + // If this is true(default), then Phan will not warn. + // + // Even when this is false, Phan will still infer return values and check parameters of internal functions + // if Phan has the signatures. + 'ignore_undeclared_functions_with_known_signatures' => true, + + // Backwards Compatibility Checking. This is slow + // and expensive, but you should consider running + // it before upgrading your version of PHP to a + // new version that has backward compatibility + // breaks. + // + // If you are migrating from PHP 5 to PHP 7, + // you should also look into using + // [php7cc (no longer maintained)](https://github.com/sstalle/php7cc) + // and [php7mar](https://github.com/Alexia/php7mar), + // which have different backwards compatibility checks. + 'backward_compatibility_checks' => false, + + // If true, check to make sure the return type declared + // in the doc-block (if any) matches the return type + // declared in the method signature. + 'check_docblock_signature_return_type_match' => false, + + // If true, make narrowed types from phpdoc params override + // the real types from the signature, when real types exist. + // (E.g. allows specifying desired lists of subclasses, + // or to indicate a preference for non-nullable types over nullable types) + // + // Affects analysis of the body of the method and the param types passed in by callers. + // + // (*Requires `check_docblock_signature_param_type_match` to be true*) + 'prefer_narrowed_phpdoc_param_type' => true, + + // (*Requires `check_docblock_signature_return_type_match` to be true*) + // + // If true, make narrowed types from phpdoc returns override + // the real types from the signature, when real types exist. + // + // (E.g. allows specifying desired lists of subclasses, + // or to indicate a preference for non-nullable types over nullable types) + // + // This setting affects the analysis of return statements in the body of the method and the return types passed in by callers. + 'prefer_narrowed_phpdoc_return_type' => true, + + // If enabled, check all methods that override a + // parent method to make sure its signature is + // compatible with the parent's. + // + // This check can add quite a bit of time to the analysis. + // + // This will also check if final methods are overridden, etc. + 'analyze_signature_compatibility' => true, + + // This setting maps case-insensitive strings to union types. + // + // This is useful if a project uses phpdoc that differs from the phpdoc2 standard. + // + // If the corresponding value is the empty string, + // then Phan will ignore that union type (E.g. can ignore 'the' in `@return the value`) + // + // If the corresponding value is not empty, + // then Phan will act as though it saw the corresponding UnionTypes(s) + // when the keys show up in a UnionType of `@param`, `@return`, `@var`, `@property`, etc. + // + // This matches the **entire string**, not parts of the string. + // (E.g. `@return the|null` will still look for a class with the name `the`, but `@return the` will be ignored with the below setting) + // + // (These are not aliases, this setting is ignored outside of doc comments). + // (Phan does not check if classes with these names exist) + // + // Example setting: `['unknown' => '', 'number' => 'int|float', 'char' => 'string', 'long' => 'int', 'the' => '']` + 'phpdoc_type_mapping' => [], + + // Set to true in order to attempt to detect dead + // (unreferenced) code. Keep in mind that the + // results will only be a guess given that classes, + // properties, constants and methods can be referenced + // as variables (like `$class->$property` or + // `$class->$method()`) in ways that we're unable + // to make sense of. + 'dead_code_detection' => false, + + // Set to true in order to attempt to detect unused variables. + // `dead_code_detection` will also enable unused variable detection. + // + // This has a few known false positives, e.g. for loops or branches. + 'unused_variable_detection' => false, + + // Set to true in order to attempt to detect redundant and impossible conditions. + // + // This has some false positives involving loops, + // variables set in branches of loops, and global variables. + 'redundant_condition_detection' => false, + + // If enabled, Phan will act as though it's certain of real return types of a subset of internal functions, + // even if those return types aren't available in reflection (real types were taken from php 7.3 or 8.0-dev, depending on target_php_version). + // + // Note that with php 7 and earlier, php would return null or false for many internal functions if the argument types or counts were incorrect. + // As a result, enabling this setting with target_php_version 8.0 may result in false positives for `--redundant-condition-detection` when codebases also support php 7.x. + 'assume_real_types_for_internal_functions' => false, + + // If true, this runs a quick version of checks that takes less + // time at the cost of not running as thorough + // of an analysis. You should consider setting this + // to true only when you wish you had more **undiagnosed** issues + // to fix in your code base. + // + // In quick-mode the scanner doesn't rescan a function + // or a method's code block every time a call is seen. + // This means that the problem here won't be detected: + // + // ```php + // false, + + // Enable or disable support for generic templated + // class types. + 'generic_types_enabled' => true, + + // Override to hardcode existence and types of (non-builtin) globals in the global scope. + // Class names should be prefixed with `\`. + // + // (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`) + 'globals_type_map' => [], + + // The minimum severity level to report on. This can be + // set to `Issue::SEVERITY_LOW`, `Issue::SEVERITY_NORMAL` or + // `Issue::SEVERITY_CRITICAL`. Setting it to only + // critical issues is a good place to start on a big + // sloppy mature code base. + 'minimum_severity' => Issue::SEVERITY_LOW, + + // Add any issue types (such as `'PhanUndeclaredMethod'`) + // to this deny-list to inhibit them from being reported. + 'suppress_issue_types' => [], + + // A regular expression to match files to be excluded + // from parsing and analysis and will not be read at all. + // + // This is useful for excluding groups of test or example + // directories/files, unanalyzable files, or files that + // can't be removed for whatever reason. + // (e.g. `'@Test\.php$@'`, or `'@vendor/.*/(tests|Tests)/@'`) + 'exclude_file_regex' => '@^vendor/.*/(tests?|Tests?)/@', + + // A list of files that will be excluded from parsing and analysis + // and will not be read at all. + // + // This is useful for excluding hopelessly unanalyzable + // files that can't be removed for whatever reason. + 'exclude_file_list' => [ + 'vendor/composer/composer/src/Composer/InstalledVersions.php' + ], + + // A directory list that defines files that will be excluded + // from static analysis, but whose class and method + // information should be included. + // + // Generally, you'll want to include the directories for + // third-party code (such as "vendor/") in this list. + // + // n.b.: If you'd like to parse but not analyze 3rd + // party code, directories containing that code + // should be added to the `directory_list` as well as + // to `exclude_analysis_directory_list`. + 'exclude_analysis_directory_list' => [ + 'vendor/', + 'proto/', + 'thrift/' + ], + + // Enable this to enable checks of require/include statements referring to valid paths. + 'enable_include_path_checks' => true, + + // The number of processes to fork off during the analysis + // phase. + 'processes' => 1, + + // List of case-insensitive file extensions supported by Phan. + // (e.g. `['php', 'html', 'htm']`) + 'analyzed_file_extensions' => [ + 'php', + ], + + // You can put paths to stubs of internal extensions in this config option. + // If the corresponding extension is **not** loaded, then Phan will use the stubs instead. + // Phan will continue using its detailed type annotations, + // but load the constants, classes, functions, and classes (and their Reflection types) + // from these stub files (doubling as valid php files). + // Use a different extension from php to avoid accidentally loading these. + // The `tools/make_stubs` script can be used to generate your own stubs (compatible with php 7.0+ right now) + // + // (e.g. `['xdebug' => '.phan/internal_stubs/xdebug.phan_php']`) + 'autoload_internal_extension_signatures' => [], + + // A list of plugin files to execute. + // + // Plugins which are bundled with Phan can be added here by providing their name (e.g. `'AlwaysReturnPlugin'`) + // + // Documentation about available bundled plugins can be found [here](https://github.com/phan/phan/tree/master/.phan/plugins). + // + // Alternately, you can pass in the full path to a PHP file with the plugin's implementation (e.g. `'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'`) + 'plugins' => [ + 'AlwaysReturnPlugin', + 'PregRegexCheckerPlugin', + 'UnreachableCodePlugin', + ], + + // A list of directories that should be parsed for class and + // method information. After excluding the directories + // defined in `exclude_analysis_directory_list`, the remaining + // files will be statically analyzed for errors. + // + // Thus, both first-party and third-party code being used by + // your application should be included in this list. + 'directory_list' => [ + 'src', + 'vendor' + ], + + // A list of individual files to include in analysis + // with a path relative to the root directory of the + // project. + 'file_list' => [], +]; diff --git a/src/Sampler/RuleBased/.php-cs-fixer.php b/src/Sampler/RuleBased/.php-cs-fixer.php new file mode 100644 index 00000000..e35fa078 --- /dev/null +++ b/src/Sampler/RuleBased/.php-cs-fixer.php @@ -0,0 +1,43 @@ +exclude('vendor') + ->exclude('var/cache') + ->in(__DIR__); + +$config = new PhpCsFixer\Config(); +return $config->setRules([ + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => ['space' => 'none'], + 'is_null' => true, + 'modernize_types_casting' => true, + 'ordered_imports' => true, + 'php_unit_construct' => true, + 'single_line_comment_style' => true, + 'yoda_style' => false, + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => true, + 'cast_spaces' => true, + 'declare_strict_types' => true, + 'type_declaration_spaces' => true, + 'include' => true, + 'lowercase_cast' => true, + 'new_with_parentheses' => true, + 'no_extra_blank_lines' => true, + 'no_leading_import_slash' => true, + 'echo_tag_syntax' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_types' => true, + 'short_scalar_cast' => true, + 'blank_lines_before_namespace' => true, + 'single_quote' => true, + 'trailing_comma_in_multiline' => true, + ]) + ->setRiskyAllowed(true) + ->setFinder($finder); + diff --git a/src/Sampler/RuleBased/composer.json b/src/Sampler/RuleBased/composer.json index e1c0662c..72e70c5a 100644 --- a/src/Sampler/RuleBased/composer.json +++ b/src/Sampler/RuleBased/composer.json @@ -1,20 +1,28 @@ { - "name": "open-telemetry/contrib-sampler-rule-based", - "description": "OpenTelemetry SDK contrib rule-based sampler", + "name": "open-telemetry/sampler-rule-based", + "description": "OpenTelemetry SDK rule-based sampler", "keywords": ["opentelemetry", "otel", "sdk", "tracing", "sampler"], "license": "Apache-2.0", "require": { "php": "^8.1", + "open-telemetry/api": "dev-main as 1.1.0", "open-telemetry/sdk": "dev-main as 1.1.0", - "open-telemetry/" + "open-telemetry/sdk-configuration": "dev-main as 0.99" }, "require-dev": { "symfony/config": "^5.4 || ^6.4 || ^7.0", - "tbachert/otel-sdk-configuration": "^0.1" + "symfony/yaml": "^6 || ^7", + "friendsofphp/php-cs-fixer": "^3", + "phan/phan": "^5.0", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "psalm/plugin-phpunit": "^0.18.4", + "phpunit/phpunit": "^10 || ^11", + "vimeo/psalm": "^4|^5" }, "autoload": { "psr-4": { - "Nevay\\OTelSDK\\Contrib\\Sampler\\": "" + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\": "src/" } }, "extra": { @@ -22,15 +30,21 @@ "dev-main": "0.1.x-dev" }, "spi": { - "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplerAlwaysRecording", - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplerRuleBased", - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleAttribute", - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleLink", - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleParent", - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleSpanKind", - "Nevay\\OTelSDK\\Contrib\\Sampler\\Configuration\\SamplingRuleSpanName" + "OpenTelemetry\\Config\\SDK\\Configuration\\ComponentProvider": [ + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplerRuleBased", + + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleAttribute", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleLink", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleParent", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleSpanKind", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleSpanName" ] } + }, + "config": { + "allow-plugins": { + "php-http/discovery": false, + "tbachert/spi": true + } } } diff --git a/src/Sampler/RuleBased/phpstan.neon.dist b/src/Sampler/RuleBased/phpstan.neon.dist new file mode 100644 index 00000000..ed94c13d --- /dev/null +++ b/src/Sampler/RuleBased/phpstan.neon.dist @@ -0,0 +1,9 @@ +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + +parameters: + tmpDir: var/cache/phpstan + level: 5 + paths: + - src + - tests diff --git a/src/Sampler/RuleBased/phpunit.xml.dist b/src/Sampler/RuleBased/phpunit.xml.dist new file mode 100644 index 00000000..aebce8c3 --- /dev/null +++ b/src/Sampler/RuleBased/phpunit.xml.dist @@ -0,0 +1,22 @@ + + + + + + + + + + + tests/Unit + + + tests/Integration + + + + + src + + + diff --git a/src/Sampler/RuleBased/phpunit.xml.dist.bak b/src/Sampler/RuleBased/phpunit.xml.dist.bak new file mode 100644 index 00000000..d8548853 --- /dev/null +++ b/src/Sampler/RuleBased/phpunit.xml.dist.bak @@ -0,0 +1,47 @@ + + + + + + + src + + + + + + + + + + + + + tests/Unit + + + tests/Integration + + + + diff --git a/src/Sampler/RuleBased/psalm.xml.dist b/src/Sampler/RuleBased/psalm.xml.dist new file mode 100644 index 00000000..15571171 --- /dev/null +++ b/src/Sampler/RuleBased/psalm.xml.dist @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/src/Sampler/RuleBased/src/AlwaysRecordingSampler.php b/src/Sampler/RuleBased/src/AlwaysRecordingSampler.php deleted file mode 100644 index 74327fce..00000000 --- a/src/Sampler/RuleBased/src/AlwaysRecordingSampler.php +++ /dev/null @@ -1,39 +0,0 @@ -sampler->shouldSample($context, $traceId, $spanName, $spanKind, $attributes, $links); - if (!$result->shouldRecord()) { - $result = new AlwaysRecordingSamplingResult($result); - } - - return $result; - } - - public function __toString(): string { - return sprintf('AlwaysRecordingSampler{%s}', $this->sampler); - } -} diff --git a/src/Sampler/RuleBased/src/AlwaysRecordingSamplingResult.php b/src/Sampler/RuleBased/src/AlwaysRecordingSamplingResult.php deleted file mode 100644 index dfda9b94..00000000 --- a/src/Sampler/RuleBased/src/AlwaysRecordingSamplingResult.php +++ /dev/null @@ -1,31 +0,0 @@ -samplingResult->traceFlags(); - } - - public function traceState(): ?TraceStateInterface { - return $this->samplingResult->traceState(); - } - - public function additionalAttributes(): iterable { - return $this->samplingResult->additionalAttributes(); - } -} diff --git a/src/Sampler/RuleBased/src/Configuration/SamplerAlwaysRecording.php b/src/Sampler/RuleBased/src/Configuration/SamplerAlwaysRecording.php deleted file mode 100644 index c3e44226..00000000 --- a/src/Sampler/RuleBased/src/Configuration/SamplerAlwaysRecording.php +++ /dev/null @@ -1,35 +0,0 @@ - - * } $properties - */ - public function createPlugin(array $properties, Context $context): Sampler { - return new AlwaysRecordingSampler( - $properties['sampler']->create($context), - ); - } - - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('always_recording'); - $node - ->children() - ->append($registry->component('sampler', Sampler::class)->isRequired()) - ->end() - ; - - return $node; - } -} diff --git a/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php b/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php index 1559da79..c29a0dea 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php +++ b/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php @@ -1,28 +1,32 @@ ->, - * delegate: ComponentPlugin, + * delegate: ComponentPlugin, * }>, - * fallback: ComponentPlugin, + * fallback: ComponentPlugin, * } $properties */ - public function createPlugin(array $properties, Context $context): Sampler { + public function createPlugin(array $properties, Context $context): SamplerInterface + { $ruleSets = []; foreach ($properties['rule_sets'] as $ruleSet) { $samplingRules = []; @@ -42,7 +46,8 @@ public function createPlugin(array $properties, Context $context): Sampler { ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('rule_based'); $node ->children() @@ -50,11 +55,11 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->arrayPrototype() ->children() ->append($registry->componentList('rules', SamplingRule::class)->isRequired()->cannotBeEmpty()) - ->append($registry->component('delegate', Sampler::class)->isRequired()) + ->append($registry->component('delegate', SamplerInterface::class)->isRequired()) ->end() ->end() ->end() - ->append($registry->component('fallback', Sampler::class)->isRequired()) + ->append($registry->component('fallback', SamplerInterface::class)->isRequired()) ->end() ; diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php index 1635835f..367e1e76 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php +++ b/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php @@ -1,15 +1,19 @@ -children() diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php index a8104cb4..0781f526 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php +++ b/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php @@ -1,14 +1,18 @@ -children() diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php index 5f4a8eec..ab0f37f1 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php +++ b/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php @@ -1,14 +1,18 @@ -children() diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php index 8c8f7da4..b622bce3 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php +++ b/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php @@ -1,34 +1,40 @@ - Kind::Internal, - 'CLIENT' => Kind::Client, - 'SERVER' => Kind::Server, - 'PRODUCER' => Kind::Producer, - 'CONSUMER' => Kind::Consumer, + 'INTERNAL' => SpanKind::KIND_INTERNAL, + 'CLIENT' => SpanKind::KIND_CLIENT, + 'SERVER' => SpanKind::KIND_SERVER, + 'PRODUCER' => SpanKind::KIND_PRODUCER, + 'CONSUMER' => SpanKind::KIND_CONSUMER, }, ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('span_kind'); $node ->children() diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php b/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php index 9e460738..6c5b4195 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php +++ b/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php @@ -1,28 +1,34 @@ -children() diff --git a/src/Sampler/RuleBased/src/RuleBasedSampler.php b/src/Sampler/RuleBased/src/RuleBasedSampler.php index 43272730..b8bce6ab 100644 --- a/src/Sampler/RuleBased/src/RuleBasedSampler.php +++ b/src/Sampler/RuleBased/src/RuleBasedSampler.php @@ -1,50 +1,59 @@ - $ruleSets */ public function __construct( private readonly array $ruleSets, - private readonly Sampler $fallback, - ) {} + private readonly SamplerInterface $fallback, + ) { + } public function shouldSample( - ContextInterface $context, + ContextInterface $parentContext, string $traceId, string $spanName, - Kind $spanKind, - Attributes $attributes, + int $spanKind, + AttributesInterface $attributes, array $links, ): SamplingResult { foreach ($this->ruleSets as $ruleSet) { - foreach ($ruleSet->samplingRules as $samplingRule) { - if (!$samplingRule->matches($context, $traceId, $spanName, $spanKind, $attributes, $links)) { + foreach ($ruleSet->samplingRules() as $samplingRule) { + if (!$samplingRule->matches($parentContext, $traceId, $spanName, $spanKind, $attributes, $links)) { continue 2; } } - return $ruleSet->delegate->shouldSample($context, $traceId, $spanName, $spanKind, $attributes, $links); + return $ruleSet->delegate()->shouldSample($parentContext, $traceId, $spanName, $spanKind, $attributes, $links); } - return $this->fallback->shouldSample($context, $traceId, $spanName, $spanKind, $attributes, $links); + return $this->fallback->shouldSample($parentContext, $traceId, $spanName, $spanKind, $attributes, $links); + } + + public function __toString(): string + { + return sprintf('RuleBasedSampler{rules=[%s],fallback=%s}', implode(',', $this->ruleSets), $this->fallback->getDescription()); } - public function __toString(): string { - return sprintf('RuleBasedSampler{rules=[%s],fallback=%s}', implode(',', $this->ruleSets), $this->fallback); + public function getDescription(): string + { + return $this->__toString(); } } diff --git a/src/Sampler/RuleBased/src/RuleSet.php b/src/Sampler/RuleBased/src/RuleSet.php index 58b2ce3f..74f2ae18 100644 --- a/src/Sampler/RuleBased/src/RuleSet.php +++ b/src/Sampler/RuleBased/src/RuleSet.php @@ -1,21 +1,39 @@ - $samplingRules */ public function __construct( - public readonly array $samplingRules, - public readonly Sampler $delegate, - ) {} + private readonly array $samplingRules, + private readonly SamplerInterface $delegate, + ) { + } + + public function __toString(): string + { + return sprintf('RuleSet{rules=[%s],delegate=%s}', implode(',', $this->samplingRules), $this->delegate->getDescription()); + } + + /** + * @return list + */ + public function samplingRules(): array + { + return $this->samplingRules; + } - public function __toString(): string { - return sprintf('RuleSet{rules=[%s],delegate=%s}', implode(',', $this->samplingRules), $this->delegate); + public function delegate(): SamplerInterface + { + return $this->delegate; } } diff --git a/src/Sampler/RuleBased/src/RuleSetInterface.php b/src/Sampler/RuleBased/src/RuleSetInterface.php new file mode 100644 index 00000000..982aa99c --- /dev/null +++ b/src/Sampler/RuleBased/src/RuleSetInterface.php @@ -0,0 +1,15 @@ + + */ + public function samplingRules(): array; + public function delegate(): SamplerInterface; + public function __toString(); +} \ No newline at end of file diff --git a/src/Sampler/RuleBased/src/SamplingRule.php b/src/Sampler/RuleBased/src/SamplingRule.php index b4d44a4c..d4ad963e 100644 --- a/src/Sampler/RuleBased/src/SamplingRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule.php @@ -1,13 +1,15 @@ - $links span links + * @param int $spanKind span kind + * @param AttributesInterface $attributes span attributes + * @param list $links span links * @return bool whether this rule matches the given data * * @see Sampler::shouldSample() @@ -26,8 +28,8 @@ public function matches( ContextInterface $context, string $traceId, string $spanName, - Kind $spanKind, - Attributes $attributes, + int $spanKind, + AttributesInterface $attributes, array $links, ): bool; diff --git a/src/Sampler/RuleBased/src/SamplingRule/AttributeRule.php b/src/Sampler/RuleBased/src/SamplingRule/AttributeRule.php index c4e1d142..d712cfb2 100644 --- a/src/Sampler/RuleBased/src/SamplingRule/AttributeRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule/AttributeRule.php @@ -1,36 +1,41 @@ -has($this->attributeKey) && preg_match($this->pattern, (string) $attributes->get($this->attributeKey)); } - public function __toString(): string { + public function __toString(): string + { return sprintf('Attribute{key=%s,pattern=%s}', $this->attributeKey, $this->pattern); } } diff --git a/src/Sampler/RuleBased/src/SamplingRule/LinkRule.php b/src/Sampler/RuleBased/src/SamplingRule/LinkRule.php index 09b30b41..ed500b5d 100644 --- a/src/Sampler/RuleBased/src/SamplingRule/LinkRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule/LinkRule.php @@ -1,36 +1,41 @@ -spanContext->isSampled() !== $this->sampled) { + /* @var \OpenTelemetry\SDK\Trace\LinkInterface $link */ + if ($link->getSpanContext()->isSampled() !== $this->sampled) { continue; } - if ($this->remote !== null && $link->spanContext->isRemote() !== $this->remote) { + if ($this->remote !== null && $link->getSpanContext()->isRemote() !== $this->remote) { continue; } @@ -40,7 +45,8 @@ public function matches( return false; } - public function __toString(): string { + public function __toString(): string + { return sprintf('Link{sampled=%s,remote=%s}', var_export($this->sampled, true), var_export($this->remote, true)); } } diff --git a/src/Sampler/RuleBased/src/SamplingRule/ParentRule.php b/src/Sampler/RuleBased/src/SamplingRule/ParentRule.php index 60faeff3..e2521e80 100644 --- a/src/Sampler/RuleBased/src/SamplingRule/ParentRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule/ParentRule.php @@ -1,30 +1,34 @@ -getContext(); @@ -34,7 +38,8 @@ public function matches( && ($this->remote === null || $parent->isRemote() === $this->remote); } - public function __toString(): string { + public function __toString(): string + { return sprintf('Parent{sampled=%s,remote=%s}', var_export($this->sampled, true), var_export($this->remote, true)); } } diff --git a/src/Sampler/RuleBased/src/SamplingRule/SpanKindRule.php b/src/Sampler/RuleBased/src/SamplingRule/SpanKindRule.php index abc8b442..b3083e7c 100644 --- a/src/Sampler/RuleBased/src/SamplingRule/SpanKindRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule/SpanKindRule.php @@ -1,33 +1,38 @@ -spanKind === $spanKind; } - public function __toString(): string { - return sprintf('SpanKind{kind=%s}', $this->spanKind->name); + public function __toString(): string + { + return sprintf('SpanKind{kind=%s}', $this->spanKind); //@todo SpanKind enum? } } diff --git a/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php b/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php index 74a03000..43a32a75 100644 --- a/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php @@ -1,31 +1,36 @@ -pattern, $spanName); } - public function __toString(): string { + public function __toString(): string + { return sprintf('SpanName{pattern=%s}', $this->pattern); } } diff --git a/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php b/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php new file mode 100644 index 00000000..2bd4a211 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php @@ -0,0 +1,26 @@ +expectNotToPerformAssertions(); + Configuration::parseFile($file)->create(); + } + + public static function configFileProvider(): iterable + { + yield [__DIR__ . '/config/sdk-config.yaml']; + } +} diff --git a/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml b/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml new file mode 100644 index 00000000..725627fb --- /dev/null +++ b/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml @@ -0,0 +1,25 @@ +file_format: "0.1" + +tracer_provider: + sampler: + rule_based: + rule_sets: + - rules: + - attribute: {key: is.important, pattern: ~false~ } + delegate: + always_off: {} + - rules: + - link: { sampled: true } + delegate: + always_off: {} + - rules: + - span_name: { pattern: ~foobar~ } + delegate: + always_off: {} + - rules: + - span_kind: { kind: SERVER } + - attribute: { key: url.path, pattern: ~^/health$~ } + delegate: + always_off: {} + fallback: + always_on: {} \ No newline at end of file diff --git a/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php b/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php new file mode 100644 index 00000000..ea1e42d2 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php @@ -0,0 +1,92 @@ +context = $this->createMock(ContextInterface::class); + $this->traceId = 'some.trace.id'; + $this->spanName = 'my-span'; + $this->spanKind = SpanKind::KIND_SERVER; + $this->attributes = $this->createMock(AttributesInterface::class); + $this->links = []; + + $this->delegate = $this->createMock(SamplerInterface::class); + $this->rule = $this->createMock(SamplingRule::class); + $this->ruleSet = new RuleSet([$this->rule], $this->delegate); + + $this->fallback = $this->createMock(SamplerInterface::class); + $this->sampler = new RuleBasedSampler([$this->ruleSet], $this->fallback); + } + + public function test_delegates_on_ruleset_match(): void + { + $this->fallback + ->expects($this->never()) + ->method('shouldSample'); + $this->delegate + ->expects($this->once()) + ->method('shouldSample') + ->willReturn(new SamplingResult(SamplingResult::RECORD_AND_SAMPLE)); + $this->rule + ->expects($this->once()) + ->method('matches') + ->willReturn(true); + + $this->sampler->shouldSample($this->context, $this->traceId, $this->spanName, $this->spanKind, $this->attributes, $this->links); + } + + public function test_uses_fallback_when_no_match(): void + { + $this->fallback + ->expects($this->once()) + ->method('shouldSample') + ->willReturn(new SamplingResult(SamplingResult::RECORD_AND_SAMPLE)); + $this->delegate + ->expects($this->never()) + ->method('shouldSample'); + $this->rule + ->expects($this->once()) + ->method('matches') + ->willReturn(false); + + $this->sampler->shouldSample($this->context, $this->traceId, $this->spanName, $this->spanKind, $this->attributes, $this->links); + } + + public function test_get_description(): void + { + $this->rule->method('__toString')->willReturn('rule-one'); + $this->fallback->method('getDescription')->willReturn('fallback'); + $this->delegate->method('getDescription')->willReturn('delegate'); + + $this->assertSame('RuleBasedSampler{rules=[RuleSet{rules=[rule-one],delegate=delegate}],fallback=fallback}', $this->sampler->getDescription()); + } +} \ No newline at end of file diff --git a/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php b/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php new file mode 100644 index 00000000..bc687438 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php @@ -0,0 +1,43 @@ +delegate = $this->createMock(SamplerInterface::class); + $this->rule_one = $this->createMock(SamplingRule::class); + $this->rule_two = $this->createMock(SamplingRule::class); + } + + public function test_getters(): void + { + $rules = [$this->rule_one, $this->rule_two]; + $ruleSet = new RuleSet($rules, $this->delegate); + + $this->assertSame($rules, $ruleSet->samplingRules()); + $this->assertSame($this->delegate, $ruleSet->delegate()); + } + + public function test_to_string(): void + { + $this->rule_one->expects($this->once())->method('__toString')->willReturn('rule_one'); + $this->rule_two->expects($this->once())->method('__toString')->willReturn('rule_two'); + $this->delegate->expects($this->once())->method('getDescription')->willReturn('delegate'); + $ruleSet = new RuleSet([$this->rule_one, $this->rule_two], $this->delegate); + + $this->assertSame('RuleSet{rules=[rule_one,rule_two],delegate=delegate}', (string)$ruleSet); + } +} \ No newline at end of file diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php new file mode 100644 index 00000000..f4a70a61 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php @@ -0,0 +1,48 @@ +assertSame( + $expected, + $rule->matches( + $this->createMock(ContextInterface::class), + 'trace-id', + 'span-name', + SpanKind::KIND_SERVER, + $attributes, + [] + ) + ); + } + + public static function attributesProvider(): iterable + { + yield [Attributes::create(['foo' => 'foo']), true]; + yield [Attributes::create(['foo' => 'bar']), false]; + yield [Attributes::create(['bar' => 'foo']), false]; + } + + public function test_to_string(): void + { + $rule = new AttributeRule('foo', '~foo~'); + + $this->assertSame('Attribute{key=foo,pattern=~foo~}', (string) $rule); + } +} \ No newline at end of file diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php new file mode 100644 index 00000000..d685c478 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php @@ -0,0 +1,66 @@ +createMock(AttributesInterface::class) + ); + + $rule = new LinkRule($sampled, $remote); + $this->assertSame( + $expected, + $rule->matches( + $this->createMock(ContextInterface::class), + 'trace-id', + 'span-name', + SpanKind::KIND_SERVER, + $this->createMock(AttributesInterface::class), + [$link] + ) + ); + } + + public static function matchesProvider(): array + { + //isSampled, isRemote, sampled, remote, expected + return [ + 'is sampled, allow sampled' => [true, false, true, false, true], + 'is sampled, allow remote' => [true, false, false, true, false], + 'is remote, allow sampled' => [false, true, true, false, false], + 'is remote, allow remote' => [false, true, false, true, true], + 'is sampled+remote, allow only sampled' => [true, true, true, false, false], + 'is sampled+remote, allow only remote' => [true, true, false, true, false], + 'is sampled+remote, allow sampled+remote' => [true, true, true, true, true], + ]; + } + + public function test_to_string(): void + { + $rule = new LinkRule(true, false); + $this->assertSame('Link{sampled=true,remote=false}', (string)$rule); + } +} \ No newline at end of file diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php new file mode 100644 index 00000000..90448693 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php @@ -0,0 +1,70 @@ +createMock(SpanInterface::class); + $span->method('getContext')->willReturn($spanContext); + $context = $this->createMock(ContextInterface::class); + $context->method('get')->willReturn($span); + + $rule = new ParentRule($sampled, $remote); + $this->assertSame( + $expected, + $rule->matches( + $context, + 'trace-id', + 'span-name', + SpanKind::KIND_SERVER, + $this->createMock(AttributesInterface::class), + [] + ) + ); + } + + public static function matchesProvider(): array + { + //isSampled, isRemote, sampled, remote, expected + return [ + 'is sampled, allow sampled' => [true, false, true, false, true], + 'is sampled, allow remote' => [true, false, false, true, false], + 'is remote, allow sampled' => [false, true, true, false, false], + 'is remote, allow remote' => [false, true, false, true, true], + 'is sampled+remote, allow only sampled' => [true, true, true, false, false], + 'is sampled+remote, allow only remote' => [true, true, false, true, false], + 'is sampled+remote, allow sampled+remote' => [true, true, true, true, true], + ]; + } + + public function test_to_string(): void + { + $rule = new ParentRule(true, false); + $this->assertSame('Parent{sampled=true,remote=false}', (string)$rule); + } +} \ No newline at end of file diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php new file mode 100644 index 00000000..93561c08 --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php @@ -0,0 +1,39 @@ +assertSame($expected, $rule->matches(Context::getRoot(), 'trace-id', 'foo', $spanKind, Attributes::create([]), [])); + } + + public static function matchesProvider(): array + { + return [ + [SpanKind::KIND_INTERNAL, SpanKind::KIND_INTERNAL, true], + [SpanKind::KIND_INTERNAL, SpanKind::KIND_SERVER, false], + ]; + } + + public function test_to_string(): void + { + $rule = new SpanKindRule(SpanKind::KIND_SERVER); + + $this->assertSame('SpanKind{kind=2}', (string)$rule); + } +} diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php new file mode 100644 index 00000000..628fb4ab --- /dev/null +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php @@ -0,0 +1,41 @@ +assertSame($expected, $rule->matches(Context::getRoot(), 'trace-id', $spanName, SpanKind::KIND_INTERNAL, Attributes::create([]), [])); + } + + public static function matchesProvider(): array + { + return [ + ['~foo~', 'foo', true], + ['~bar~', 'foobarbaz', true], + ['~foo~', 'bar', false], + ['~^bar$~', 'Xbar', false], + ]; + } + + public function test_to_string(): void + { + $rule = new SpanNameRule('~foo~'); + + $this->assertSame('SpanName{pattern=~foo~}', (string) $rule); + } +} From 3c367addb62c5ab488095752091419d117db9bde Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 3 Jul 2024 17:28:54 +1000 Subject: [PATCH 04/13] rename dir --- src/Sampler/RuleBased/composer.json | 12 ++++++------ .../SamplerRuleBased.php | 2 +- .../SamplingRuleAttribute.php | 2 +- .../SamplingRuleLink.php | 2 +- .../SamplingRuleParent.php | 2 +- .../SamplingRuleSpanKind.php | 2 +- .../SamplingRuleSpanName.php | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) rename src/Sampler/RuleBased/src/{Configuration => ComponentProvider}/SamplerRuleBased.php (97%) rename src/Sampler/RuleBased/src/{Configuration => ComponentProvider}/SamplingRuleAttribute.php (95%) rename src/Sampler/RuleBased/src/{Configuration => ComponentProvider}/SamplingRuleLink.php (94%) rename src/Sampler/RuleBased/src/{Configuration => ComponentProvider}/SamplingRuleParent.php (94%) rename src/Sampler/RuleBased/src/{Configuration => ComponentProvider}/SamplingRuleSpanKind.php (96%) rename src/Sampler/RuleBased/src/{Configuration => ComponentProvider}/SamplingRuleSpanName.php (94%) diff --git a/src/Sampler/RuleBased/composer.json b/src/Sampler/RuleBased/composer.json index 72e70c5a..51060165 100644 --- a/src/Sampler/RuleBased/composer.json +++ b/src/Sampler/RuleBased/composer.json @@ -31,13 +31,13 @@ }, "spi": { "OpenTelemetry\\Config\\SDK\\Configuration\\ComponentProvider": [ - "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplerRuleBased", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\ComponentProvider\\SamplerRuleBased", - "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleAttribute", - "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleLink", - "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleParent", - "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleSpanKind", - "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\Configuration\\SamplingRuleSpanName" + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\ComponentProvider\\SamplingRuleAttribute", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\ComponentProvider\\SamplingRuleLink", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\ComponentProvider\\SamplingRuleParent", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\ComponentProvider\\SamplingRuleSpanKind", + "OpenTelemetry\\Contrib\\Sampler\\RuleBased\\ComponentProvider\\SamplingRuleSpanName" ] } }, diff --git a/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php similarity index 97% rename from src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php rename to src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php index c29a0dea..480604e4 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplerRuleBased.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Sampler\RuleBased\Configuration; +namespace OpenTelemetry\Contrib\Sampler\RuleBased\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php similarity index 95% rename from src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php rename to src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php index 367e1e76..315b81ad 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleAttribute.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Sampler\RuleBased\Configuration; +namespace OpenTelemetry\Contrib\Sampler\RuleBased\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php similarity index 94% rename from src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php rename to src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php index 0781f526..c10347e8 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleLink.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Sampler\RuleBased\Configuration; +namespace OpenTelemetry\Contrib\Sampler\RuleBased\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php similarity index 94% rename from src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php rename to src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php index ab0f37f1..15be0e50 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleParent.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Sampler\RuleBased\Configuration; +namespace OpenTelemetry\Contrib\Sampler\RuleBased\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php similarity index 96% rename from src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php rename to src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php index b622bce3..8e2b9f17 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanKind.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Sampler\RuleBased\Configuration; +namespace OpenTelemetry\Contrib\Sampler\RuleBased\ComponentProvider; use OpenTelemetry\API\Trace\SpanKind; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; diff --git a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php similarity index 94% rename from src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php rename to src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php index 6c5b4195..db06f443 100644 --- a/src/Sampler/RuleBased/src/Configuration/SamplingRuleSpanName.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Sampler\RuleBased\Configuration; +namespace OpenTelemetry\Contrib\Sampler\RuleBased\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; From 571a392733c46c235d144e66d0cd7c39f6c2a832 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 4 Jul 2024 14:56:48 +1000 Subject: [PATCH 05/13] rename dir, add tests, static analysis fixes --- src/Sampler/RuleBased/.phan/config.php | 3 +-- src/Sampler/RuleBased/phpstan.neon.dist | 5 +++++ src/Sampler/RuleBased/psalm.xml.dist | 19 +++++++++++++++++++ .../ComponentProvider/SamplerRuleBased.php | 3 +++ .../SamplingRuleAttribute.php | 4 ++++ .../ComponentProvider/SamplingRuleLink.php | 3 +++ .../ComponentProvider/SamplingRuleParent.php | 3 +++ .../SamplingRuleSpanKind.php | 3 +++ .../SamplingRuleSpanName.php | 4 ++++ .../RuleBased/src/RuleSetInterface.php | 4 +++- .../src/SamplingRule/AttributeRule.php | 5 ++++- .../RuleBased/src/SamplingRule/LinkRule.php | 2 +- .../src/SamplingRule/SpanNameRule.php | 4 +++- .../tests/Unit/RuleBasedSamplerTest.php | 11 +++++++++-- .../RuleBased/tests/Unit/RuleSetTest.php | 10 ++++++++-- .../Unit/SamplingRule/AttributeRuleTest.php | 4 +++- .../tests/Unit/SamplingRule/LinkRuleTest.php | 6 ++++-- .../Unit/SamplingRule/ParentRuleTest.php | 7 ++++--- .../Unit/SamplingRule/SpanKindRuleTest.php | 2 +- .../Unit/SamplingRule/SpanNameRuleTest.php | 3 +++ 20 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/Sampler/RuleBased/.phan/config.php b/src/Sampler/RuleBased/.phan/config.php index 6473a9aa..d3c9f491 100644 --- a/src/Sampler/RuleBased/.phan/config.php +++ b/src/Sampler/RuleBased/.phan/config.php @@ -311,8 +311,7 @@ // to `exclude_analysis_directory_list`. 'exclude_analysis_directory_list' => [ 'vendor/', - 'proto/', - 'thrift/' + 'src/ComponentProvider/', ], // Enable this to enable checks of require/include statements referring to valid paths. diff --git a/src/Sampler/RuleBased/phpstan.neon.dist b/src/Sampler/RuleBased/phpstan.neon.dist index ed94c13d..f9cb5fac 100644 --- a/src/Sampler/RuleBased/phpstan.neon.dist +++ b/src/Sampler/RuleBased/phpstan.neon.dist @@ -7,3 +7,8 @@ parameters: paths: - src - tests + ignoreErrors: + - + message: "#Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeParentInterface::.*#" + paths: + - src/ \ No newline at end of file diff --git a/src/Sampler/RuleBased/psalm.xml.dist b/src/Sampler/RuleBased/psalm.xml.dist index 15571171..995b2a65 100644 --- a/src/Sampler/RuleBased/psalm.xml.dist +++ b/src/Sampler/RuleBased/psalm.xml.dist @@ -2,6 +2,8 @@ @@ -12,4 +14,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php index 480604e4..a50a61da 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php @@ -14,6 +14,9 @@ use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplerRuleBased implements ComponentProvider { /** diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php index 315b81ad..6c67736b 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php @@ -12,6 +12,9 @@ use OpenTelemetry\Contrib\Sampler\RuleBased\SamplingRule\AttributeRule; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplingRuleAttribute implements ComponentProvider { @@ -20,6 +23,7 @@ final class SamplingRuleAttribute implements ComponentProvider * key: string, * pattern: string, * } $properties + * @psalm-suppress ArgumentTypeCoercion */ public function createPlugin(array $properties, Context $context): SamplingRule { diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php index c10347e8..17cc5511 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php @@ -11,6 +11,9 @@ use OpenTelemetry\Contrib\Sampler\RuleBased\SamplingRule\LinkRule; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplingRuleLink implements ComponentProvider { diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php index 15be0e50..af818520 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php @@ -11,6 +11,9 @@ use OpenTelemetry\Contrib\Sampler\RuleBased\SamplingRule\ParentRule; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplingRuleParent implements ComponentProvider { diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php index 8e2b9f17..429bcc21 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php @@ -12,6 +12,9 @@ use OpenTelemetry\Contrib\Sampler\RuleBased\SamplingRule\SpanKindRule; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplingRuleSpanKind implements ComponentProvider { diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php index db06f443..10c49633 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php @@ -12,6 +12,9 @@ use OpenTelemetry\Contrib\Sampler\RuleBased\SamplingRule\SpanNameRule; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplingRuleSpanName implements ComponentProvider { @@ -19,6 +22,7 @@ final class SamplingRuleSpanName implements ComponentProvider * @param array{ * pattern: string, * } $properties + * @psalm-suppress ArgumentTypeCoercion */ public function createPlugin(array $properties, Context $context): SamplingRule { diff --git a/src/Sampler/RuleBased/src/RuleSetInterface.php b/src/Sampler/RuleBased/src/RuleSetInterface.php index 982aa99c..d2d6997c 100644 --- a/src/Sampler/RuleBased/src/RuleSetInterface.php +++ b/src/Sampler/RuleBased/src/RuleSetInterface.php @@ -1,5 +1,7 @@ getSpanContext()->isSampled() !== $this->sampled) { continue; } diff --git a/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php b/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php index 43a32a75..5861f49a 100644 --- a/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule/SpanNameRule.php @@ -12,7 +12,9 @@ final class SpanNameRule implements SamplingRule { - + /** + * @param non-empty-string $pattern + */ public function __construct( private readonly string $pattern, ) { diff --git a/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php b/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php index ea1e42d2..d7ab145e 100644 --- a/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php +++ b/src/Sampler/RuleBased/tests/Unit/RuleBasedSamplerTest.php @@ -1,26 +1,32 @@ */ private array $links; public function setUp(): void @@ -89,4 +96,4 @@ public function test_get_description(): void $this->assertSame('RuleBasedSampler{rules=[RuleSet{rules=[rule-one],delegate=delegate}],fallback=fallback}', $this->sampler->getDescription()); } -} \ No newline at end of file +} diff --git a/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php b/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php index bc687438..03aadbaa 100644 --- a/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php +++ b/src/Sampler/RuleBased/tests/Unit/RuleSetTest.php @@ -1,18 +1,24 @@ delegate->expects($this->once())->method('getDescription')->willReturn('delegate'); $ruleSet = new RuleSet([$this->rule_one, $this->rule_two], $this->delegate); - $this->assertSame('RuleSet{rules=[rule_one,rule_two],delegate=delegate}', (string)$ruleSet); + $this->assertSame('RuleSet{rules=[rule_one,rule_two],delegate=delegate}', (string) $ruleSet); } -} \ No newline at end of file +} diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php index f4a70a61..b26ee377 100644 --- a/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/AttributeRuleTest.php @@ -1,5 +1,7 @@ assertSame('Attribute{key=foo,pattern=~foo~}', (string) $rule); } -} \ No newline at end of file +} diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php index d685c478..b54b1ada 100644 --- a/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/LinkRuleTest.php @@ -1,5 +1,7 @@ assertSame('Link{sampled=true,remote=false}', (string)$rule); + $this->assertSame('Link{sampled=true,remote=false}', (string) $rule); } -} \ No newline at end of file +} diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php index 90448693..3a375177 100644 --- a/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/ParentRuleTest.php @@ -1,5 +1,7 @@ assertSame('Parent{sampled=true,remote=false}', (string)$rule); + $this->assertSame('Parent{sampled=true,remote=false}', (string) $rule); } -} \ No newline at end of file +} diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php index 93561c08..8db7ed2b 100644 --- a/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanKindRuleTest.php @@ -34,6 +34,6 @@ public function test_to_string(): void { $rule = new SpanKindRule(SpanKind::KIND_SERVER); - $this->assertSame('SpanKind{kind=2}', (string)$rule); + $this->assertSame('SpanKind{kind=2}', (string) $rule); } } diff --git a/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php index 628fb4ab..75301553 100644 --- a/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php +++ b/src/Sampler/RuleBased/tests/Unit/SamplingRule/SpanNameRuleTest.php @@ -15,6 +15,9 @@ #[CoversClass(SpanNameRule::class)] class SpanNameRuleTest extends TestCase { + /** + * @param non-empty-string $pattern + */ #[DataProvider('matchesProvider')] public function test_matches(string $pattern, string $spanName, bool $expected): void { From bde4f556eb618c7fb5737ba89e11a12aee826e16 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 4 Jul 2024 21:24:59 +1000 Subject: [PATCH 06/13] update workflow and gitsplit --- .github/workflows/php.yml | 5 +++++ .gitsplit.yml | 2 ++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 44bd9635..c6a6c242 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -45,6 +45,7 @@ jobs: 'Propagation/TraceResponse', 'ResourceDetectors/Azure', 'ResourceDetectors/Container', + 'Sampler/RuleBased', 'Shims/OpenTracing', 'Symfony' ] @@ -101,6 +102,10 @@ jobs: php-version: 7.4 - project: 'ResourceDetectors/Container' php-version: 7.4 + - project: 'Sampler/RuleBased' + php-version: 7.4 + - project: 'Sampler/RuleBased' + php-version: 8.0 steps: - uses: actions/checkout@v4 diff --git a/.gitsplit.yml b/.gitsplit.yml index 1e9eac36..eea9a2fe 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -64,6 +64,8 @@ splits: target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-detector-azure.git" - prefix: "src/ResourceDetectors/Container" target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-detector-container.git" + - prefix: "src/Sampler/RuleBased" + target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-sampler-rulebased.git" - prefix: "src/Shims/OpenTracing" target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-shim-opentracing.git" # List of references to split (defined as regexp) From e312f0907829b921bbe85711b6f8d2b76478fe8a Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 17 Jul 2024 14:33:06 +1000 Subject: [PATCH 07/13] update readme --- src/Sampler/RuleBased/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sampler/RuleBased/README.md b/src/Sampler/RuleBased/README.md index 7d285347..63a75404 100644 --- a/src/Sampler/RuleBased/README.md +++ b/src/Sampler/RuleBased/README.md @@ -5,7 +5,7 @@ Provides additional samplers that are not part of the official specification. ## Installation ```shell -composer require tbachert/otel-sdk-contrib-sampler +composer require open-telemetry/sampler-rule-based ``` ## RuleBasedSampler From 8fb041450b74d3aa5e8f10d0a95332f70c5b04d4 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 18 Jul 2024 14:00:15 +1000 Subject: [PATCH 08/13] rename key to contrib_rule_based to avoid future collision with an official rule-based sampler, change the name to something less likely to conflict. --- src/Sampler/RuleBased/README.md | 4 ++-- .../RuleBased/src/ComponentProvider/SamplerRuleBased.php | 2 +- .../RuleBased/tests/Integration/config/sdk-config.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Sampler/RuleBased/README.md b/src/Sampler/RuleBased/README.md index 63a75404..ccde5d7b 100644 --- a/src/Sampler/RuleBased/README.md +++ b/src/Sampler/RuleBased/README.md @@ -32,7 +32,7 @@ $sampler = new RuleBasedSampler( ###### Example: drop spans for the /health endpoint ```yaml -rule_based: +contrib_rule_based: rule_sets: - rules: - span_kind: { kind: SERVER } @@ -45,7 +45,7 @@ rule_based: ###### Example: sample spans with at least one sampled link ```yaml -rule_based: +contrib_rule_based: rule_sets: - rules: [ link: { sampled: true } ] delegate: diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php index a50a61da..72df17f6 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php @@ -51,7 +51,7 @@ public function createPlugin(array $properties, Context $context): SamplerInterf public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('rule_based'); + $node = new ArrayNodeDefinition('contrib_rule_based'); $node ->children() ->arrayNode('rule_sets') diff --git a/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml b/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml index 725627fb..21859a7b 100644 --- a/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml +++ b/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml @@ -2,7 +2,7 @@ file_format: "0.1" tracer_provider: sampler: - rule_based: + contrib_rule_based: rule_sets: - rules: - attribute: {key: is.important, pattern: ~false~ } From b6fcb39447602eb5f7092471e39114a76e624e4a Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Fri, 30 Aug 2024 09:31:09 +1000 Subject: [PATCH 09/13] stringable, componentArrayList --- .../RuleBased/src/ComponentProvider/SamplerRuleBased.php | 2 +- src/Sampler/RuleBased/src/SamplingRule.php | 9 +++++---- .../RuleBased/tests/Integration/RuleBasedSamplerTest.php | 2 +- .../RuleBased/tests/Integration/config/sdk-config.yaml | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php index 72df17f6..0a714940 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php @@ -57,7 +57,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->arrayNode('rule_sets') ->arrayPrototype() ->children() - ->append($registry->componentList('rules', SamplingRule::class)->isRequired()->cannotBeEmpty()) + ->append($registry->componentArrayList('rules', SamplingRule::class)->isRequired()->cannotBeEmpty()) ->append($registry->component('delegate', SamplerInterface::class)->isRequired()) ->end() ->end() diff --git a/src/Sampler/RuleBased/src/SamplingRule.php b/src/Sampler/RuleBased/src/SamplingRule.php index d4ad963e..fbc81df6 100644 --- a/src/Sampler/RuleBased/src/SamplingRule.php +++ b/src/Sampler/RuleBased/src/SamplingRule.php @@ -7,10 +7,13 @@ use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Trace\LinkInterface; +use Stringable; -interface SamplingRule +/** + * @phan-suppress PhanRedefinedInheritedInterface + */ +interface SamplingRule extends Stringable { - /** * Returns whether this sampling rule matches the given data. * @@ -32,6 +35,4 @@ public function matches( AttributesInterface $attributes, array $links, ): bool; - - public function __toString(): string; } diff --git a/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php b/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php index 2bd4a211..420fc7e9 100644 --- a/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php +++ b/src/Sampler/RuleBased/tests/Integration/RuleBasedSamplerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OpenTelemetry\Contrib\Tests\Integration\Propagation\RuleBased; +namespace OpenTelemetry\Contrib\Tests\Integration\Sampler\RuleBased; use OpenTelemetry\Config\SDK\Configuration; use PHPUnit\Framework\Attributes\CoversNothing; diff --git a/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml b/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml index 21859a7b..c12a8859 100644 --- a/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml +++ b/src/Sampler/RuleBased/tests/Integration/config/sdk-config.yaml @@ -1,4 +1,4 @@ -file_format: "0.1" +file_format: "0.3" tracer_provider: sampler: From 35fb19a5e41ee4011bd41fd3e54daac1a34a0f05 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Fri, 30 Aug 2024 10:05:02 +1000 Subject: [PATCH 10/13] replace a toString --- src/Sampler/RuleBased/src/RuleBasedSampler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sampler/RuleBased/src/RuleBasedSampler.php b/src/Sampler/RuleBased/src/RuleBasedSampler.php index b8bce6ab..8b6019cd 100644 --- a/src/Sampler/RuleBased/src/RuleBasedSampler.php +++ b/src/Sampler/RuleBased/src/RuleBasedSampler.php @@ -54,6 +54,6 @@ public function __toString(): string public function getDescription(): string { - return $this->__toString(); + return (string) $this; } } From d603f07a84690ffbb1f5641cb5b2147b1c038004 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Sat, 7 Sep 2024 09:17:36 +1000 Subject: [PATCH 11/13] stringable --- src/Sampler/RuleBased/src/RuleSetInterface.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Sampler/RuleBased/src/RuleSetInterface.php b/src/Sampler/RuleBased/src/RuleSetInterface.php index d2d6997c..ca042c3a 100644 --- a/src/Sampler/RuleBased/src/RuleSetInterface.php +++ b/src/Sampler/RuleBased/src/RuleSetInterface.php @@ -5,13 +5,16 @@ namespace OpenTelemetry\Contrib\Sampler\RuleBased; use OpenTelemetry\SDK\Trace\SamplerInterface; +use Stringable; -interface RuleSetInterface +/** + * @phan-suppress PhanRedefinedInheritedInterface + */ +interface RuleSetInterface extends Stringable { /** * @return list */ public function samplingRules(): array; public function delegate(): SamplerInterface; - public function __toString(); } From 5183ac03f4b489549eb69e2d308140d6cd464717 Mon Sep 17 00:00:00 2001 From: Chris Lightfoot-Wild Date: Wed, 11 Sep 2024 21:37:44 +0100 Subject: [PATCH 12/13] Add .gitattributes to rulebased sampler --- src/Sampler/RuleBased/.gitattributes | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/Sampler/RuleBased/.gitattributes diff --git a/src/Sampler/RuleBased/.gitattributes b/src/Sampler/RuleBased/.gitattributes new file mode 100644 index 00000000..ac40e9f8 --- /dev/null +++ b/src/Sampler/RuleBased/.gitattributes @@ -0,0 +1,13 @@ +* text=auto + +*.md diff=markdown +*.php diff=php + +/.gitattributes export-ignore +/.gitignore export-ignore +/.phan export-ignore +/.php-cs-fixer.php export-ignore +/phpstan.neon.dist export-ignore +/phpunit.xml.dist export-ignore +/psalm.xml.dist export-ignore +/tests export-ignore From 53becd818400cf780c9fc2f194d819cd765eb7ae Mon Sep 17 00:00:00 2001 From: Chris Lightfoot-Wild Date: Wed, 11 Sep 2024 21:38:19 +0100 Subject: [PATCH 13/13] Remove phpunit.xml.dist.bak --- src/Sampler/RuleBased/phpunit.xml.dist.bak | 47 ---------------------- 1 file changed, 47 deletions(-) delete mode 100644 src/Sampler/RuleBased/phpunit.xml.dist.bak diff --git a/src/Sampler/RuleBased/phpunit.xml.dist.bak b/src/Sampler/RuleBased/phpunit.xml.dist.bak deleted file mode 100644 index d8548853..00000000 --- a/src/Sampler/RuleBased/phpunit.xml.dist.bak +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - src - - - - - - - - - - - - - tests/Unit - - - tests/Integration - - - -