From 52cd14a7b69b3dc4fa5dc6ebdc6e52ea0a117f10 Mon Sep 17 00:00:00 2001 From: Ruben Van Assche Date: Thu, 21 May 2026 11:48:58 +0200 Subject: [PATCH 1/2] Split sampling rules into typed subclasses --- composer.json | 2 +- phpstan-baseline.neon | 5 - .../PhpCommandAttributesProvider.php | 15 +++ .../PhpJobAttributesProvider.php | 15 +++ .../SymfonyInputCommandAttributesProvider.php | 3 +- src/Contracts/CommandAttributesProvider.php | 2 +- src/Contracts/JobAttributesProvider.php | 5 +- src/Contracts/QueuedJobAttributesProvider.php | 10 ++ src/Contracts/SamplingAttributesProvider.php | 16 +++ src/EntryPoint/EntryPoint.php | 22 ++++ .../CommandRecorder/CommandRecorder.php | 11 +- src/Recorders/JobRecorder/JobRecorder.php | 9 +- src/Recorders/QueueRecorder/QueueRecorder.php | 4 +- .../RoutingRecorder/RoutingRecorder.php | 19 +-- src/Recorders/SpansRecorder.php | 16 ++- src/Sampling/DeferrableSampler.php | 2 +- src/Sampling/DeferredSamplerRule.php | 7 ++ src/Sampling/DynamicSampler.php | 32 +++-- src/Sampling/Rules/ClosureSamplingRule.php | 26 ++++ src/Sampling/Rules/CommandSamplingRule.php | 32 +++++ .../Rules/DeferredClosureSamplingRule.php | 27 ++++ src/Sampling/Rules/JobSamplingRule.php | 31 +++++ src/Sampling/Rules/PathSamplingRule.php | 36 ++++++ src/Sampling/Rules/RouteSamplingRule.php | 36 ++++++ src/Sampling/Rules/UrlSamplingRule.php | 34 +++++ src/Sampling/SamplingRule.php | 116 +++++------------- src/Sampling/SamplingRuleType.php | 26 ---- src/Tracer.php | 2 +- tests/Integration/IntegrationTest.php | 4 +- .../RoutingRecorder/RoutingRecorderTest.php | 35 ++++++ tests/Sampling/DynamicSamplerTest.php | 66 ++++------ tests/Sampling/SamplingRuleTest.php | 68 ++-------- tests/TracerTest.php | 20 +-- 33 files changed, 462 insertions(+), 292 deletions(-) create mode 100644 src/Contracts/QueuedJobAttributesProvider.php create mode 100644 src/Contracts/SamplingAttributesProvider.php create mode 100644 src/Sampling/DeferredSamplerRule.php create mode 100644 src/Sampling/Rules/ClosureSamplingRule.php create mode 100644 src/Sampling/Rules/CommandSamplingRule.php create mode 100644 src/Sampling/Rules/DeferredClosureSamplingRule.php create mode 100644 src/Sampling/Rules/JobSamplingRule.php create mode 100644 src/Sampling/Rules/PathSamplingRule.php create mode 100644 src/Sampling/Rules/RouteSamplingRule.php create mode 100644 src/Sampling/Rules/UrlSamplingRule.php delete mode 100644 src/Sampling/SamplingRuleType.php diff --git a/composer.json b/composer.json index b344c95..b05c6bb 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "1.3.x-dev" + "dev-main": "3.x-dev" } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index b9b0160..fecb4fa 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -95,11 +95,6 @@ parameters: count: 1 path: src/Recorders/SpanEventsRecorder.php - - - message: "#^Unsafe usage of new static\\(\\)\\.$#" - count: 8 - path: src/Sampling/SamplingRule.php - - message: "#^Instanceof between \\*NEVER\\* and Spatie\\\\FlareClient\\\\Spans\\\\SpanEvent will always evaluate to false\\.$#" count: 1 diff --git a/src/AttributesProviders/PhpCommandAttributesProvider.php b/src/AttributesProviders/PhpCommandAttributesProvider.php index c16bc57..821f6e5 100644 --- a/src/AttributesProviders/PhpCommandAttributesProvider.php +++ b/src/AttributesProviders/PhpCommandAttributesProvider.php @@ -30,4 +30,19 @@ public function commandClass(): ?string { return $this->commandClass; } + + public function entryPointHandlerIdentifier(): ?string + { + return $this->command; + } + + public function entryPointHandlerName(): ?string + { + return $this->commandClass; + } + + public function entryPointHandlerType(): ?string + { + return 'php_command'; + } } diff --git a/src/AttributesProviders/PhpJobAttributesProvider.php b/src/AttributesProviders/PhpJobAttributesProvider.php index bd3f8e8..84c4987 100644 --- a/src/AttributesProviders/PhpJobAttributesProvider.php +++ b/src/AttributesProviders/PhpJobAttributesProvider.php @@ -26,4 +26,19 @@ public function jobClass(): ?string { return $this->jobClass; } + + public function entryPointHandlerIdentifier(): ?string + { + return $this->jobName; + } + + public function entryPointHandlerName(): ?string + { + return $this->jobClass; + } + + public function entryPointHandlerType(): ?string + { + return 'php_job'; + } } diff --git a/src/AttributesProviders/SymfonyInputCommandAttributesProvider.php b/src/AttributesProviders/SymfonyInputCommandAttributesProvider.php index 5478c47..c5001f8 100644 --- a/src/AttributesProviders/SymfonyInputCommandAttributesProvider.php +++ b/src/AttributesProviders/SymfonyInputCommandAttributesProvider.php @@ -3,10 +3,9 @@ namespace Spatie\FlareClient\AttributesProviders; use Spatie\FlareClient\Contracts\CommandAttributesProvider; -use Spatie\FlareClient\Contracts\EntryPointHandlerProvider; use Symfony\Component\Console\Input\InputInterface; -class SymfonyInputCommandAttributesProvider implements CommandAttributesProvider, EntryPointHandlerProvider +class SymfonyInputCommandAttributesProvider implements CommandAttributesProvider { public function __construct( protected InputInterface $input, diff --git a/src/Contracts/CommandAttributesProvider.php b/src/Contracts/CommandAttributesProvider.php index 42966ab..9a8fa6f 100644 --- a/src/Contracts/CommandAttributesProvider.php +++ b/src/Contracts/CommandAttributesProvider.php @@ -2,7 +2,7 @@ namespace Spatie\FlareClient\Contracts; -interface CommandAttributesProvider extends AttributesProvider +interface CommandAttributesProvider extends AttributesProvider, EntryPointHandlerProvider { public function command(): string; diff --git a/src/Contracts/JobAttributesProvider.php b/src/Contracts/JobAttributesProvider.php index 2e27d4e..a785bc5 100644 --- a/src/Contracts/JobAttributesProvider.php +++ b/src/Contracts/JobAttributesProvider.php @@ -2,9 +2,6 @@ namespace Spatie\FlareClient\Contracts; -interface JobAttributesProvider extends AttributesProvider +interface JobAttributesProvider extends QueuedJobAttributesProvider, EntryPointHandlerProvider { - public function jobName(): string; - - public function jobClass(): ?string; } diff --git a/src/Contracts/QueuedJobAttributesProvider.php b/src/Contracts/QueuedJobAttributesProvider.php new file mode 100644 index 0000000..3b988bc --- /dev/null +++ b/src/Contracts/QueuedJobAttributesProvider.php @@ -0,0 +1,10 @@ + */ + public function samplingAttributes(): array; +} diff --git a/src/EntryPoint/EntryPoint.php b/src/EntryPoint/EntryPoint.php index 3793dc2..9ec5b92 100644 --- a/src/EntryPoint/EntryPoint.php +++ b/src/EntryPoint/EntryPoint.php @@ -2,6 +2,9 @@ namespace Spatie\FlareClient\EntryPoint; +use Spatie\FlareClient\Contracts\AttributesProvider; +use Spatie\FlareClient\Contracts\EntryPointHandlerProvider; +use Spatie\FlareClient\Contracts\SamplingAttributesProvider; use Spatie\FlareClient\Enums\EntryPointType; class EntryPoint @@ -14,6 +17,9 @@ class EntryPoint public ?string $handlerType; + /** @var array */ + public array $samplingAttributes = []; + public function __construct( public EntryPointType $type, public string $value, @@ -25,17 +31,33 @@ public function updateValue(string $value): void $this->value = $value; } + /** @param array $samplingAttributes */ public function setHandler( string $handlerIdentifier, ?string $handlerName, ?string $handlerType, + array $samplingAttributes = [], ): void { $this->handlerIdentifier = $handlerIdentifier; $this->handlerName = $handlerName; $this->handlerType = $handlerType; + $this->samplingAttributes = $samplingAttributes; $this->handlerResolved = true; } + public function setHandlerFromAttributesProvider( + AttributesProvider&EntryPointHandlerProvider $provider, + ): void { + $this->setHandler( + handlerIdentifier: $provider->entryPointHandlerIdentifier() ?? 'unknown', + handlerName: $provider->entryPointHandlerName(), + handlerType: $provider->entryPointHandlerType() ?? 'unknown', + samplingAttributes: $provider instanceof SamplingAttributesProvider + ? $provider->samplingAttributes() + : [], + ); + } + /** @return array */ public function toAttributes(): array { diff --git a/src/Recorders/CommandRecorder/CommandRecorder.php b/src/Recorders/CommandRecorder/CommandRecorder.php index 3a32c32..2d3ead3 100644 --- a/src/Recorders/CommandRecorder/CommandRecorder.php +++ b/src/Recorders/CommandRecorder/CommandRecorder.php @@ -5,7 +5,6 @@ use Spatie\FlareClient\AttributesProviders\PhpCommandAttributesProvider; use Spatie\FlareClient\AttributesProviders\SymfonyInputCommandAttributesProvider; use Spatie\FlareClient\Contracts\CommandAttributesProvider; -use Spatie\FlareClient\Contracts\EntryPointHandlerProvider; use Spatie\FlareClient\EntryPoint\EntryPointResolver; use Spatie\FlareClient\Enums\RecorderType; use Spatie\FlareClient\Enums\SpanType; @@ -54,15 +53,7 @@ public function recordStart( $entryPoint = $this->entryPointResolver->get(); if (! $entryPoint->handlerResolved) { - $entryPointProvider = $commandAttributesProvider instanceof EntryPointHandlerProvider - ? $commandAttributesProvider - : null; - - $entryPoint->setHandler( - handlerIdentifier: $entryPointProvider?->entryPointHandlerIdentifier() ?? $command, - handlerName: $entryPointProvider?->entryPointHandlerName() ?? $commandClass, - handlerType: $entryPointProvider?->entryPointHandlerType() ?? 'php_command', - ); + $entryPoint->setHandlerFromAttributesProvider($commandAttributesProvider); } $this->tracer->reevaluateSampling(); diff --git a/src/Recorders/JobRecorder/JobRecorder.php b/src/Recorders/JobRecorder/JobRecorder.php index 0aeee28..89d4348 100644 --- a/src/Recorders/JobRecorder/JobRecorder.php +++ b/src/Recorders/JobRecorder/JobRecorder.php @@ -3,7 +3,6 @@ namespace Spatie\FlareClient\Recorders\JobRecorder; use Spatie\FlareClient\AttributesProviders\PhpJobAttributesProvider; -use Spatie\FlareClient\Contracts\EntryPointHandlerProvider; use Spatie\FlareClient\Contracts\JobAttributesProvider; use Spatie\FlareClient\EntryPoint\EntryPoint; use Spatie\FlareClient\EntryPoint\EntryPointResolver; @@ -82,13 +81,7 @@ public function recordStart( value: $jobClass ?? $jobName, ); - $entryPointProvider = $jobAttributesProvider instanceof EntryPointHandlerProvider ? $jobAttributesProvider : null; - - $entryPoint->setHandler( - handlerIdentifier: $entryPointProvider?->entryPointHandlerIdentifier() ?? $jobName, - handlerName: $entryPointProvider?->entryPointHandlerName() ?? $jobClass, - handlerType: $entryPointProvider?->entryPointHandlerType() ?? 'php_job', - ); + $entryPoint->setHandlerFromAttributesProvider($jobAttributesProvider); if ($this->lifecycle->usesSubtasks) { $this->entryPointResolver->set($entryPoint); diff --git a/src/Recorders/QueueRecorder/QueueRecorder.php b/src/Recorders/QueueRecorder/QueueRecorder.php index 29dec71..9c131b1 100644 --- a/src/Recorders/QueueRecorder/QueueRecorder.php +++ b/src/Recorders/QueueRecorder/QueueRecorder.php @@ -3,7 +3,7 @@ namespace Spatie\FlareClient\Recorders\QueueRecorder; use Spatie\FlareClient\AttributesProviders\PhpJobAttributesProvider; -use Spatie\FlareClient\Contracts\JobAttributesProvider; +use Spatie\FlareClient\Contracts\QueuedJobAttributesProvider; use Spatie\FlareClient\Enums\RecorderType; use Spatie\FlareClient\Enums\SpanType; use Spatie\FlareClient\Recorders\SpansRecorder; @@ -36,7 +36,7 @@ protected function configure(array $config): void } public function recordStart( - JobAttributesProvider $provider, + QueuedJobAttributesProvider $provider, array $attributes = [], ): ?Span { $jobName = $provider->jobName(); diff --git a/src/Recorders/RoutingRecorder/RoutingRecorder.php b/src/Recorders/RoutingRecorder/RoutingRecorder.php index 1ef1d3c..fd86d1b 100644 --- a/src/Recorders/RoutingRecorder/RoutingRecorder.php +++ b/src/Recorders/RoutingRecorder/RoutingRecorder.php @@ -143,15 +143,15 @@ public function recordRoutingEnd( $entryPoint = $this->entryPointResolver->get(); - if (! $entryPoint->handlerResolved) { - $entryPointProvider = $routeAttributesProvider instanceof EntryPointHandlerProvider - ? $routeAttributesProvider - : null; + if (! $entryPoint->handlerResolved && $routeAttributesProvider instanceof EntryPointHandlerProvider) { + $entryPoint->setHandlerFromAttributesProvider($routeAttributesProvider); + } + if (! $entryPoint->handlerResolved) { $entryPoint->setHandler( - handlerIdentifier: $entryPointProvider?->entryPointHandlerIdentifier() ?? 'unknown', - handlerName: $entryPointProvider?->entryPointHandlerName(), - handlerType: $entryPointProvider?->entryPointHandlerType() ?? 'php_request', + handlerIdentifier: 'unknown', + handlerName: null, + handlerType: 'php_request', ); } @@ -167,7 +167,10 @@ public function recordRoutingEnd( return $this->endSpan( time: $time, - additionalAttributes: $attributes, + additionalAttributes: fn () => [ + ...$routeAttributesProvider->toArray(), + ...$attributes, + ], ); } diff --git a/src/Recorders/SpansRecorder.php b/src/Recorders/SpansRecorder.php index a19caf0..d35157a 100644 --- a/src/Recorders/SpansRecorder.php +++ b/src/Recorders/SpansRecorder.php @@ -146,6 +146,14 @@ final protected function endSpan( $spanCallback($span); } + $shouldTrace = $this->withTraces + && $this->tracer->sampling + && ! $this->tracer->disabled; + + if (! $shouldTrace && ! $this->shouldReport()) { + return $span; + } + if (is_callable($additionalAttributes)) { $additionalAttributes = $additionalAttributes(); } @@ -154,14 +162,10 @@ final protected function endSpan( $span->addAttributes($additionalAttributes); } - if ($this->withTraces === false - || $this->tracer->sampling === false - || $this->tracer->disabled === true) { - return $span; + if ($shouldTrace) { + $this->tracer->endSpan($span, includeMemoryUsage: $includeMemoryUsage); } - $this->tracer->endSpan($span, includeMemoryUsage: $includeMemoryUsage); - return $span; } diff --git a/src/Sampling/DeferrableSampler.php b/src/Sampling/DeferrableSampler.php index 6307139..3f60aef 100644 --- a/src/Sampling/DeferrableSampler.php +++ b/src/Sampling/DeferrableSampler.php @@ -6,7 +6,7 @@ interface DeferrableSampler extends Sampler { - public function isPending(): bool; + public function isDeferred(): bool; public function reevaluate(EntryPoint $entryPoint): bool; diff --git a/src/Sampling/DeferredSamplerRule.php b/src/Sampling/DeferredSamplerRule.php new file mode 100644 index 0000000..e1fcfe2 --- /dev/null +++ b/src/Sampling/DeferredSamplerRule.php @@ -0,0 +1,7 @@ + */ protected array $rules; - protected bool $pending = false; + protected bool $deferred = false; protected ?bool $parentSampled = null; + /** @param array{base_rate?: float|null, rules?: array} $config */ public function __construct(array $config) { parent::__construct(['rate' => $config['base_rate'] ?? null]); - $this->rules = array_map( - fn (SamplingRule|array $rule) => $rule instanceof SamplingRule - ? $rule - : SamplingRule::fromArray($rule), - $config['rules'] ?? [], - ); + $this->rules = $config['rules'] ?? []; } public function shouldSample(EntryPoint $entryPoint, ?bool $parentSampled = null): bool { - $this->pending = false; + $this->deferred = false; $this->parentSampled = $parentSampled; foreach ($this->rules as $rule) { - if (! $rule->type()->appliesTo($entryPoint->type)) { + if (! $rule->appliesTo($entryPoint->type)) { continue; } - if (! $rule->canRun($entryPoint)) { - $this->pending = true; + if ($rule instanceof DeferredSamplerRule && ! $entryPoint->handlerResolved) { + $this->deferred = true; break; } @@ -48,28 +44,28 @@ public function shouldSample(EntryPoint $entryPoint, ?bool $parentSampled = null } } - if ($this->pending) { + if ($this->deferred) { return true; } return $parentSampled ?? parent::shouldSample($entryPoint, null); } - public function isPending(): bool + public function isDeferred(): bool { - return $this->pending; + return $this->deferred; } public function reevaluate(EntryPoint $entryPoint): bool { - $this->pending = false; + $this->deferred = false; foreach ($this->rules as $rule) { - if (! $rule->type()->appliesTo($entryPoint->type)) { + if (! $rule->appliesTo($entryPoint->type)) { continue; } - if (! $rule->canRun($entryPoint)) { + if ($rule instanceof DeferredSamplerRule && ! $entryPoint->handlerResolved) { continue; } @@ -85,7 +81,7 @@ public function reevaluate(EntryPoint $entryPoint): bool public function reset(): void { - $this->pending = false; + $this->deferred = false; $this->parentSampled = null; } } diff --git a/src/Sampling/Rules/ClosureSamplingRule.php b/src/Sampling/Rules/ClosureSamplingRule.php new file mode 100644 index 0000000..4fc8bdd --- /dev/null +++ b/src/Sampling/Rules/ClosureSamplingRule.php @@ -0,0 +1,26 @@ +closure)($entryPoint); + } +} diff --git a/src/Sampling/Rules/CommandSamplingRule.php b/src/Sampling/Rules/CommandSamplingRule.php new file mode 100644 index 0000000..8426ba9 --- /dev/null +++ b/src/Sampling/Rules/CommandSamplingRule.php @@ -0,0 +1,32 @@ + 1) { + throw new InvalidArgumentException('Sampling rate must be between 0 and 1.'); + } + } + + public function appliesTo(EntryPointType $entryPointType): bool + { + return $entryPointType === EntryPointType::Cli; + } + + public function getMatchedRate(EntryPoint $entryPoint): ?float + { + return PatternMatcher::matches($entryPoint->handlerIdentifier, $this->pattern) ? $this->rate : null; + } +} diff --git a/src/Sampling/Rules/DeferredClosureSamplingRule.php b/src/Sampling/Rules/DeferredClosureSamplingRule.php new file mode 100644 index 0000000..4b3eb5e --- /dev/null +++ b/src/Sampling/Rules/DeferredClosureSamplingRule.php @@ -0,0 +1,27 @@ +closure)($entryPoint); + } +} diff --git a/src/Sampling/Rules/JobSamplingRule.php b/src/Sampling/Rules/JobSamplingRule.php new file mode 100644 index 0000000..d35fd30 --- /dev/null +++ b/src/Sampling/Rules/JobSamplingRule.php @@ -0,0 +1,31 @@ + 1) { + throw new InvalidArgumentException('Sampling rate must be between 0 and 1.'); + } + } + + public function appliesTo(EntryPointType $entryPointType): bool + { + return $entryPointType === EntryPointType::Queue; + } + + public function getMatchedRate(EntryPoint $entryPoint): ?float + { + return PatternMatcher::matches($entryPoint->handlerIdentifier, $this->pattern) ? $this->rate : null; + } +} diff --git a/src/Sampling/Rules/PathSamplingRule.php b/src/Sampling/Rules/PathSamplingRule.php new file mode 100644 index 0000000..640c36f --- /dev/null +++ b/src/Sampling/Rules/PathSamplingRule.php @@ -0,0 +1,36 @@ + 1) { + throw new InvalidArgumentException('Sampling rate must be between 0 and 1.'); + } + } + + public function appliesTo(EntryPointType $entryPointType): bool + { + return $entryPointType === EntryPointType::Web; + } + + public function getMatchedRate(EntryPoint $entryPoint): ?float + { + $path = parse_url($entryPoint->value, PHP_URL_PATH) ?: '/'; + + $value = rtrim($path, '/') ?: '/'; + $pattern = rtrim($this->pattern, '/') ?: '/'; + + return PatternMatcher::matches($value, $pattern) ? $this->rate : null; + } +} diff --git a/src/Sampling/Rules/RouteSamplingRule.php b/src/Sampling/Rules/RouteSamplingRule.php new file mode 100644 index 0000000..1f73092 --- /dev/null +++ b/src/Sampling/Rules/RouteSamplingRule.php @@ -0,0 +1,36 @@ + 1) { + throw new InvalidArgumentException('Sampling rate must be between 0 and 1.'); + } + } + + public function appliesTo(EntryPointType $entryPointType): bool + { + return $entryPointType === EntryPointType::Web; + } + + public function getMatchedRate(EntryPoint $entryPoint): ?float + { + $value = str_contains($entryPoint->handlerIdentifier, ' ') + ? explode(' ', $entryPoint->handlerIdentifier, 2)[1] + : $entryPoint->handlerIdentifier; + + return PatternMatcher::matches($value, $this->pattern) ? $this->rate : null; + } +} diff --git a/src/Sampling/Rules/UrlSamplingRule.php b/src/Sampling/Rules/UrlSamplingRule.php new file mode 100644 index 0000000..3304dd9 --- /dev/null +++ b/src/Sampling/Rules/UrlSamplingRule.php @@ -0,0 +1,34 @@ + 1) { + throw new InvalidArgumentException('Sampling rate must be between 0 and 1.'); + } + } + + public function appliesTo(EntryPointType $entryPointType): bool + { + return $entryPointType === EntryPointType::Web; + } + + public function getMatchedRate(EntryPoint $entryPoint): ?float + { + $value = rtrim($entryPoint->value, '/') ?: '/'; + $pattern = rtrim($this->pattern, '/') ?: '/'; + + return PatternMatcher::matches($value, $pattern) ? $this->rate : null; + } +} diff --git a/src/Sampling/SamplingRule.php b/src/Sampling/SamplingRule.php index 8bbe637..96d9db0 100644 --- a/src/Sampling/SamplingRule.php +++ b/src/Sampling/SamplingRule.php @@ -3,116 +3,56 @@ namespace Spatie\FlareClient\Sampling; use Closure; -use InvalidArgumentException; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; -use Spatie\FlareClient\Support\PatternMatcher; - -class SamplingRule +use Spatie\FlareClient\Sampling\Rules\ClosureSamplingRule; +use Spatie\FlareClient\Sampling\Rules\CommandSamplingRule; +use Spatie\FlareClient\Sampling\Rules\DeferredClosureSamplingRule; +use Spatie\FlareClient\Sampling\Rules\JobSamplingRule; +use Spatie\FlareClient\Sampling\Rules\PathSamplingRule; +use Spatie\FlareClient\Sampling\Rules\RouteSamplingRule; +use Spatie\FlareClient\Sampling\Rules\UrlSamplingRule; + +abstract class SamplingRule { - protected function __construct( - protected SamplingRuleType $type, - protected ?string $pattern, - protected ?float $rate, - protected ?Closure $closure = null, - ) { - if ($rate !== null && ($rate < 0 || $rate > 1)) { - throw new InvalidArgumentException('Sampling rate must be between 0 and 1.'); - } - } - - public static function forUrl(string $pattern, float $rate): static + public static function forUrl(string $pattern, float $rate): UrlSamplingRule { - return new static(SamplingRuleType::Url, $pattern, $rate); + return new UrlSamplingRule($pattern, $rate); } - public static function forPath(string $pattern, float $rate): static + public static function forPath(string $pattern, float $rate): PathSamplingRule { - return new static(SamplingRuleType::Path, $pattern, $rate); + return new PathSamplingRule($pattern, $rate); } - public static function forRoute(string $pattern, float $rate): static + public static function forRoute(string $pattern, float $rate): RouteSamplingRule { - return new static(SamplingRuleType::Route, $pattern, $rate); + return new RouteSamplingRule($pattern, $rate); } - public static function forCommand(string $pattern, float $rate): static + public static function forCommand(string $pattern, float $rate): CommandSamplingRule { - return new static(SamplingRuleType::Command, $pattern, $rate); + return new CommandSamplingRule($pattern, $rate); } - public static function forJob(string $pattern, float $rate): static + public static function forJob(string $pattern, float $rate): JobSamplingRule { - return new static(SamplingRuleType::Job, $pattern, $rate); + return new JobSamplingRule($pattern, $rate); } - /** @param $closure Closure(EntryPoint):?float */ - public static function using(Closure $closure): static + /** @param Closure(EntryPoint):?float $closure */ + public static function using(Closure $closure): ClosureSamplingRule { - return new static(SamplingRuleType::Closure, null, null, $closure); + return new ClosureSamplingRule($closure); } - /** @param $closure Closure(EntryPoint):?float */ - public static function usingEarly(Closure $closure): static + /** @param Closure(EntryPoint):?float $closure */ + public static function usingDeferred(Closure $closure): DeferredClosureSamplingRule { - return new static(SamplingRuleType::EarlyClosure, null, null, $closure); + return new DeferredClosureSamplingRule($closure); } - public static function fromArray(array $data): static - { - if (! isset($data['type']) || ! isset($data['rate']) || ! isset($data['pattern'])) { - throw new InvalidArgumentException('Sampling rule array must contain "type", "pattern" and "rate" keys.'); - } - - if (! $data['type'] instanceof SamplingRuleType) { - throw new InvalidArgumentException('Sampling rule "type" must be a SamplingRuleType enum.'); - } - - if ($data['type'] === SamplingRuleType::Closure || $data['type'] === SamplingRuleType::EarlyClosure) { - throw new InvalidArgumentException('Closure sampling rules cannot be created from arrays.'); - } - - return new static($data['type'], $data['pattern'], $data['rate']); - } - - public function type(): SamplingRuleType - { - return $this->type; - } + abstract public function appliesTo(EntryPointType $entryPointType): bool; - public function canRun(EntryPoint $entryPoint): bool - { - return match ($this->type) { - SamplingRuleType::Url, SamplingRuleType::Path, SamplingRuleType::Job, SamplingRuleType::EarlyClosure => true, - SamplingRuleType::Route, SamplingRuleType::Command, SamplingRuleType::Closure => $entryPoint->handlerResolved, - }; - } - - public function getMatchedRate(EntryPoint $entryPoint): ?float - { - if ($this->type === SamplingRuleType::Closure || $this->type === SamplingRuleType::EarlyClosure) { - /** @var Closure $closure */ - $closure = $this->closure; - - return $closure($entryPoint); - } - - /** @var string $pattern */ - $pattern = $this->pattern; - - $value = match ($this->type) { - SamplingRuleType::Url => $entryPoint->value, - SamplingRuleType::Path => parse_url($entryPoint->value, PHP_URL_PATH) ?: '/', - SamplingRuleType::Route => str_contains($entryPoint->handlerIdentifier, ' ') - ? explode(' ', $entryPoint->handlerIdentifier, 2)[1] - : $entryPoint->handlerIdentifier, - default => $entryPoint->handlerIdentifier, - }; - - if ($this->type === SamplingRuleType::Path || $this->type === SamplingRuleType::Url) { - $value = rtrim($value, '/') ?: '/'; - $pattern = rtrim($pattern, '/') ?: '/'; - } - - return PatternMatcher::matches($value, $pattern) ? $this->rate : null; - } + abstract public function getMatchedRate(EntryPoint $entryPoint): ?float; } diff --git a/src/Sampling/SamplingRuleType.php b/src/Sampling/SamplingRuleType.php deleted file mode 100644 index 738158e..0000000 --- a/src/Sampling/SamplingRuleType.php +++ /dev/null @@ -1,26 +0,0 @@ - $entryPointType === EntryPointType::Web, - self::Command => $entryPointType === EntryPointType::Cli, - self::Job => $entryPointType === EntryPointType::Queue, - self::Closure, self::EarlyClosure => true, - }; - } -} diff --git a/src/Tracer.php b/src/Tracer.php index 96c945d..8e5227b 100644 --- a/src/Tracer.php +++ b/src/Tracer.php @@ -151,7 +151,7 @@ public function endTrace(): void public function reevaluateSampling(): void { - if (! $this->sampler instanceof DeferrableSampler || ! $this->sampler->isPending()) { + if (! $this->sampler instanceof DeferrableSampler || ! $this->sampler->isDeferred()) { return; } diff --git a/tests/Integration/IntegrationTest.php b/tests/Integration/IntegrationTest.php index 7d00715..f94e0c5 100644 --- a/tests/Integration/IntegrationTest.php +++ b/tests/Integration/IntegrationTest.php @@ -40,7 +40,7 @@ $flare->request()->recordStartFromGlobals(); expect($flare->tracer->isSampling())->toBeTrue(); - expect($flare->tracer->sampler->isPending())->toBeTrue(); + expect($flare->tracer->sampler->isDeferred())->toBeTrue(); $flare->routing()->recordRoutingStart(); $flare->routing()->recordRoutingEndFromDefined( @@ -49,7 +49,7 @@ handlerName: 'AdminController@index', ); - expect($flare->tracer->sampler->isPending())->toBeFalse(); + expect($flare->tracer->sampler->isDeferred())->toBeFalse(); $flare->query()->record( diff --git a/tests/Recorders/RoutingRecorder/RoutingRecorderTest.php b/tests/Recorders/RoutingRecorder/RoutingRecorderTest.php index c0ea1ac..a12af97 100644 --- a/tests/Recorders/RoutingRecorder/RoutingRecorderTest.php +++ b/tests/Recorders/RoutingRecorder/RoutingRecorderTest.php @@ -2,6 +2,7 @@ namespace Spatie\FlareClient\Tests\Shared\Recorders\RoutingRecorder; +use Spatie\FlareClient\Contracts\RouteAttributesProvider; use Spatie\FlareClient\EntryPoint\EntryPoint; use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Enums\SpanType; @@ -200,6 +201,40 @@ expect($flare->tracer->isSampling())->toBeTrue(); }); +it('forwards route attributes provider data onto the routing span', function () { + $provider = new class implements RouteAttributesProvider { + public function toArray(): array + { + return [ + 'http.route' => '/admin/users', + 'custom.route.attribute' => 'extra-value', + ]; + } + + public function route(): ?string + { + return '/admin/users'; + } + + public function method(): string + { + return 'GET'; + } + }; + + $flare = setupFlare(fn (FlareConfig $config) => $config->collectRequests(), alwaysSampleTraces: true); + + $flare->tracer->startTrace(); + $flare->routing()->recordRoutingStart(); + $flare->routing()->recordRoutingEnd($provider); + $flare->tracer->endTrace(); + + $routingSpan = FakeApi::lastTrace()->expectSpan(SpanType::Routing); + + expect($routingSpan->attributes())->toHaveKey('http.route', '/admin/users'); + expect($routingSpan->attributes())->toHaveKey('custom.route.attribute', 'extra-value'); +}); + it('unsamples a trace when an ignored route is matched', function () { $flare = setupFlare( fn (FlareConfig $config) => $config->collectRequests(ignoredRoutes: ['/api/health']), diff --git a/tests/Sampling/DynamicSamplerTest.php b/tests/Sampling/DynamicSamplerTest.php index 196627b..25786f7 100644 --- a/tests/Sampling/DynamicSamplerTest.php +++ b/tests/Sampling/DynamicSamplerTest.php @@ -4,14 +4,13 @@ use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\DynamicSampler; use Spatie\FlareClient\Sampling\SamplingRule; -use Spatie\FlareClient\Sampling\SamplingRuleType; it('behaves like rate sampler with no rules', function () { $sampler = new DynamicSampler(['base_rate' => 0]); $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/test'); expect($sampler->shouldSample($entryPoint))->toBeFalse(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); it('behaves like rate sampler with no rules and rate 1', function () { @@ -19,7 +18,7 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/test'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); it('skips all rules when entry point type does not match any rule', function () { @@ -34,10 +33,10 @@ $entryPoint = new EntryPoint(EntryPointType::Cli, 'artisan migrate'); expect($sampler->shouldSample($entryPoint))->toBeFalse(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); -it('evaluates url rule immediately with no pending state', function () { +it('evaluates url rule immediately with no deferred state', function () { $sampler = new DynamicSampler([ 'base_rate' => 0, 'rules' => [ @@ -48,7 +47,7 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/admin/users'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); @@ -63,10 +62,10 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/public/page'); expect($sampler->shouldSample($entryPoint))->toBeFalse(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); -it('sets pending when a derrable rule cannot be evaluated', function () { +it('sets deferred when a deferrable rule cannot be evaluated', function () { $sampler = new DynamicSampler([ 'base_rate' => 0, 'rules' => [ @@ -77,7 +76,7 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/admin/users'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeTrue(); + expect($sampler->isDeferred())->toBeTrue(); }); it('reevaluates when handler becomes available and rule matches', function () { @@ -95,7 +94,7 @@ $entryPoint->setHandler('GET /admin/users', 'AdminController', 'php_request'); expect($sampler->reevaluate($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); it('reevaluates to false when route rule has rate 0', function () { @@ -109,7 +108,7 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/api/health'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeTrue(); + expect($sampler->isDeferred())->toBeTrue(); $entryPoint->setHandler('GET /api/health', 'HealthController', 'php_request'); @@ -159,7 +158,7 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/api/health'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeTrue(); + expect($sampler->isDeferred())->toBeTrue(); }); it('reevaluates correctly after breaking on deferred rule', function () { @@ -180,7 +179,7 @@ expect($sampler->reevaluate($entryPoint))->toBeFalse(); }); -it('command rule sets pending when handler not resolved', function () { +it('command rule sets deferred when handler not resolved', function () { $sampler = new DynamicSampler([ 'base_rate' => 0, 'rules' => [ @@ -191,7 +190,7 @@ $entryPoint = new EntryPoint(EntryPointType::Cli, 'artisan schedule:run'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeTrue(); + expect($sampler->isDeferred())->toBeTrue(); }); it('job rule evaluates immediately', function () { @@ -206,10 +205,10 @@ $entryPoint->setHandler('App\\Jobs\\ProcessPodcast', 'App\\Jobs\\ProcessPodcast', 'php_job'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); -it('reset clears pending state', function () { +it('reset clears deferred state', function () { $sampler = new DynamicSampler([ 'base_rate' => 0, 'rules' => [ @@ -221,57 +220,44 @@ $sampler->shouldSample($entryPoint); - expect($sampler->isPending())->toBeTrue(); + expect($sampler->isDeferred())->toBeTrue(); $sampler->reset(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); -it('accepts array-defined rules in config', function () { +it('defers a deferred closure rule until the handler is resolved', function () { $sampler = new DynamicSampler([ 'base_rate' => 0, 'rules' => [ - ['type' => SamplingRuleType::Path, 'pattern' => '/admin/*', 'rate' => 1.0], + SamplingRule::usingDeferred(fn (EntryPoint $ep) => str_contains($ep->handlerIdentifier, 'admin') ? 1.0 : null), ], ]); $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/admin/users'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); -}); - -it('defers a closure rule until the handler is resolved', function () { - $sampler = new DynamicSampler([ - 'base_rate' => 0, - 'rules' => [ - SamplingRule::using(fn (EntryPoint $ep) => str_contains($ep->handlerIdentifier, 'admin') ? 1.0 : null), - ], - ]); - - $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/admin/users'); - - expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeTrue(); + expect($sampler->isDeferred())->toBeTrue(); $entryPoint->setHandler('GET /admin/users', 'AdminController', 'php_request'); expect($sampler->reevaluate($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); -it('runs an early closure without waiting for the handler', function () { +it('runs an immediate closure without waiting for the handler', function () { $sampler = new DynamicSampler([ 'base_rate' => 0, 'rules' => [ - SamplingRule::usingEarly(fn (EntryPoint $ep) => $ep->type === EntryPointType::Web ? 1.0 : null), + SamplingRule::using(fn (EntryPoint $ep) => $ep->type === EntryPointType::Web ? 1.0 : null), ], ]); $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/whatever'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); it('lets a non-deferrable rule before a deferrable one decide immediately', function () { @@ -286,10 +272,10 @@ $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/api/health'); expect($sampler->shouldSample($entryPoint))->toBeTrue(); - expect($sampler->isPending())->toBeFalse(); + expect($sampler->isDeferred())->toBeFalse(); }); -it('reevaluates to the base rate when called without prior pending state', function () { +it('reevaluates to the base rate when called without prior deferred state', function () { $sampler = new DynamicSampler([ 'base_rate' => 1, 'rules' => [ diff --git a/tests/Sampling/SamplingRuleTest.php b/tests/Sampling/SamplingRuleTest.php index dbbe867..605d461 100644 --- a/tests/Sampling/SamplingRuleTest.php +++ b/tests/Sampling/SamplingRuleTest.php @@ -2,34 +2,8 @@ use Spatie\FlareClient\EntryPoint\EntryPoint; use Spatie\FlareClient\Enums\EntryPointType; +use Spatie\FlareClient\Sampling\DeferredSamplerRule; use Spatie\FlareClient\Sampling\SamplingRule; -use Spatie\FlareClient\Sampling\SamplingRuleType; - -it('throws when creating a rule from an invalid array', function (array $data, string $message) { - expect(fn () => SamplingRule::fromArray($data)) - ->toThrow(InvalidArgumentException::class, $message); -})->with([ - 'non-enum type' => [ - ['type' => 'route', 'pattern' => 'GET /api/*', 'rate' => 0.5], - 'Sampling rule "type" must be a SamplingRuleType enum.', - ], - 'closure type' => [ - ['type' => SamplingRuleType::Closure, 'pattern' => 'anything', 'rate' => 1.0], - 'Closure sampling rules cannot be created from arrays.', - ], - 'missing keys' => [ - ['rate' => 1.0], - 'Sampling rule array must contain "type", "pattern" and "rate" keys.', - ], - 'rate above 1' => [ - ['type' => SamplingRuleType::Url, 'pattern' => '/api/*', 'rate' => 1.5], - 'Sampling rate must be between 0 and 1.', - ], - 'rate below 0' => [ - ['type' => SamplingRuleType::Url, 'pattern' => '/api/*', 'rate' => -0.1], - 'Sampling rate must be between 0 and 1.', - ], -]); it('throws when constructing a static rule with an out-of-range rate', function (Closure $factory) { expect(fn () => $factory())->toThrow(InvalidArgumentException::class, 'Sampling rate must be between 0 and 1.'); @@ -41,29 +15,21 @@ 'forJob below 0' => [fn () => SamplingRule::forJob('App\\Jobs\\*', -0.01)], ]); -it('always allows url, job, and early closure rules to run', function (SamplingRule $rule) { - $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/test'); - - expect($rule->canRun($entryPoint))->toBeTrue(); +it('does not mark url, path, job, or immediate closure rules as deferred', function (SamplingRule $rule) { + expect($rule)->not->toBeInstanceOf(DeferredSamplerRule::class); })->with([ 'url' => fn () => SamplingRule::forUrl('https://example.com/*', 1.0), 'path' => fn () => SamplingRule::forPath('/admin/*', 1.0), 'job' => fn () => SamplingRule::forJob('App\\Jobs\\*', 0.5), - 'early closure' => fn () => SamplingRule::usingEarly(fn () => 1.0), + 'closure' => fn () => SamplingRule::using(fn () => 1.0), ]); -it('only allows route, command, and closure rules to run when the handler is resolved', function (SamplingRule $rule) { - $entryPoint = new EntryPoint(EntryPointType::Web, 'https://example.com/test'); - - expect($rule->canRun($entryPoint))->toBeFalse(); - - $entryPoint->setHandler('GET /test', 'TestController', 'php_request'); - - expect($rule->canRun($entryPoint))->toBeTrue(); +it('marks route, command, and deferred closure rules as deferred', function (SamplingRule $rule) { + expect($rule)->toBeInstanceOf(DeferredSamplerRule::class); })->with([ 'route' => fn () => SamplingRule::forRoute('/api/*', 0.5), 'command' => fn () => SamplingRule::forCommand('migrate', 0), - 'closure' => fn () => SamplingRule::using(fn () => 1.0), + 'deferred closure' => fn () => SamplingRule::usingDeferred(fn () => 1.0), ]); it('returns the matched rate when the entry point matches', function (SamplingRule $rule, EntryPoint $entryPoint, ?float $expected) { @@ -145,8 +111,8 @@ return [SamplingRule::using(fn (EntryPoint $ep) => null), $entryPoint, null]; }, - 'early closure receives entry point without handler' => fn () => [ - SamplingRule::usingEarly(fn (EntryPoint $ep) => $ep->type === EntryPointType::Web ? 0.5 : null), + 'closure receives entry point without handler' => fn () => [ + SamplingRule::using(fn (EntryPoint $ep) => $ep->type === EntryPointType::Web ? 0.5 : null), new EntryPoint(EntryPointType::Web, 'https://example.com/page'), 0.5, ], @@ -173,19 +139,3 @@ return [SamplingRule::forRoute('users.index', 0.33), $entryPoint, 0.33]; }, ]); - -it('builds an equivalent rule from an array', function () { - $rule = SamplingRule::fromArray([ - 'type' => SamplingRuleType::Path, - 'pattern' => '/admin/*', - 'rate' => 0.5, - ]); - - expect($rule->type())->toBe(SamplingRuleType::Path); - - $matching = new EntryPoint(EntryPointType::Web, 'https://example.com/admin/users'); - $other = new EntryPoint(EntryPointType::Web, 'https://example.com/public/page'); - - expect($rule->getMatchedRate($matching))->toBe(0.5); - expect($rule->getMatchedRate($other))->toBeNull(); -}); diff --git a/tests/TracerTest.php b/tests/TracerTest.php index da163fb..b286534 100644 --- a/tests/TracerTest.php +++ b/tests/TracerTest.php @@ -620,7 +620,7 @@ $flare->tracer->startTrace(); expect($flare->tracer->isSampling())->toBeTrue(); - expect($flare->tracer->sampler->isPending())->toBeTrue(); + expect($flare->tracer->sampler->isDeferred())->toBeTrue(); $flare->tracer->startSpan('Request Span'); @@ -629,7 +629,7 @@ $flare->tracer->reevaluateSampling(); expect($flare->tracer->isSampling())->toBeFalse(); - expect($flare->tracer->sampler->isPending())->toBeFalse(); + expect($flare->tracer->sampler->isDeferred())->toBeFalse(); expect($flare->tracer->currentTrace())->toHaveCount(0); }); @@ -645,7 +645,7 @@ $flare->tracer->startTrace(); expect($flare->tracer->isSampling())->toBeTrue(); - expect($flare->tracer->sampler->isPending())->toBeTrue(); + expect($flare->tracer->sampler->isDeferred())->toBeTrue(); $flare->tracer->startSpan('Request Span'); @@ -654,11 +654,11 @@ $flare->tracer->reevaluateSampling(); expect($flare->tracer->isSampling())->toBeTrue(); - expect($flare->tracer->sampler->isPending())->toBeFalse(); + expect($flare->tracer->sampler->isDeferred())->toBeFalse(); expect($flare->tracer->currentTrace())->toHaveCount(1); }); -it('clears pending sampling state when the trace ends', function () { +it('clears deferred sampling state when the trace ends', function () { $flare = setupFlare( fn (FlareConfig $config) => $config->sampleTracesDynamic( baseRate: 0, @@ -669,14 +669,14 @@ $flare->tracer->startTrace(); - expect($flare->tracer->sampler->isPending())->toBeTrue(); + expect($flare->tracer->sampler->isDeferred())->toBeTrue(); $entryPoint->setHandler('GET /admin/users', 'AdminController', 'php_request'); $flare->tracer->reevaluateSampling(); $flare->tracer->endTrace(); - expect($flare->tracer->sampler->isPending())->toBeFalse(); + expect($flare->tracer->sampler->isDeferred())->toBeFalse(); }); it('force-closes all open spans up the parent chain via gracefullyEndSpans', function () { @@ -709,7 +709,7 @@ expect($stayOpen->end)->toBeNull(); }); -it('clears pending sampling state when unsampled', function () { +it('clears deferred sampling state when unsampled', function () { $flare = setupFlare( fn (FlareConfig $config) => $config->sampleTracesDynamic( baseRate: 0, @@ -720,9 +720,9 @@ $flare->tracer->startTrace(); - expect($flare->tracer->sampler->isPending())->toBeTrue(); + expect($flare->tracer->sampler->isDeferred())->toBeTrue(); $flare->tracer->unsample(); - expect($flare->tracer->sampler->isPending())->toBeFalse(); + expect($flare->tracer->sampler->isDeferred())->toBeFalse(); }); From 82ad8396f699c5c6ffc4d04c50e811cb5e8b5ed7 Mon Sep 17 00:00:00 2001 From: rubenvanassche Date: Thu, 21 May 2026 09:49:22 +0000 Subject: [PATCH 2/2] Fix styling --- src/Sampling/Rules/ClosureSamplingRule.php | 2 +- src/Sampling/Rules/CommandSamplingRule.php | 2 +- src/Sampling/Rules/DeferredClosureSamplingRule.php | 2 +- src/Sampling/Rules/JobSamplingRule.php | 2 +- src/Sampling/Rules/PathSamplingRule.php | 2 +- src/Sampling/Rules/RouteSamplingRule.php | 2 +- src/Sampling/Rules/UrlSamplingRule.php | 2 +- src/Sampling/SamplingRule.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Sampling/Rules/ClosureSamplingRule.php b/src/Sampling/Rules/ClosureSamplingRule.php index 4fc8bdd..9f1cc79 100644 --- a/src/Sampling/Rules/ClosureSamplingRule.php +++ b/src/Sampling/Rules/ClosureSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use Closure; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\SamplingRule; class ClosureSamplingRule extends SamplingRule diff --git a/src/Sampling/Rules/CommandSamplingRule.php b/src/Sampling/Rules/CommandSamplingRule.php index 8426ba9..db5b449 100644 --- a/src/Sampling/Rules/CommandSamplingRule.php +++ b/src/Sampling/Rules/CommandSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use InvalidArgumentException; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\DeferredSamplerRule; use Spatie\FlareClient\Sampling\SamplingRule; use Spatie\FlareClient\Support\PatternMatcher; diff --git a/src/Sampling/Rules/DeferredClosureSamplingRule.php b/src/Sampling/Rules/DeferredClosureSamplingRule.php index 4b3eb5e..87b925b 100644 --- a/src/Sampling/Rules/DeferredClosureSamplingRule.php +++ b/src/Sampling/Rules/DeferredClosureSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use Closure; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\DeferredSamplerRule; use Spatie\FlareClient\Sampling\SamplingRule; diff --git a/src/Sampling/Rules/JobSamplingRule.php b/src/Sampling/Rules/JobSamplingRule.php index d35fd30..4765567 100644 --- a/src/Sampling/Rules/JobSamplingRule.php +++ b/src/Sampling/Rules/JobSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use InvalidArgumentException; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\SamplingRule; use Spatie\FlareClient\Support\PatternMatcher; diff --git a/src/Sampling/Rules/PathSamplingRule.php b/src/Sampling/Rules/PathSamplingRule.php index 640c36f..f7172f8 100644 --- a/src/Sampling/Rules/PathSamplingRule.php +++ b/src/Sampling/Rules/PathSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use InvalidArgumentException; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\SamplingRule; use Spatie\FlareClient\Support\PatternMatcher; diff --git a/src/Sampling/Rules/RouteSamplingRule.php b/src/Sampling/Rules/RouteSamplingRule.php index 1f73092..d76733e 100644 --- a/src/Sampling/Rules/RouteSamplingRule.php +++ b/src/Sampling/Rules/RouteSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use InvalidArgumentException; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\DeferredSamplerRule; use Spatie\FlareClient\Sampling\SamplingRule; use Spatie\FlareClient\Support\PatternMatcher; diff --git a/src/Sampling/Rules/UrlSamplingRule.php b/src/Sampling/Rules/UrlSamplingRule.php index 3304dd9..104c372 100644 --- a/src/Sampling/Rules/UrlSamplingRule.php +++ b/src/Sampling/Rules/UrlSamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling\Rules; use InvalidArgumentException; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\SamplingRule; use Spatie\FlareClient\Support\PatternMatcher; diff --git a/src/Sampling/SamplingRule.php b/src/Sampling/SamplingRule.php index 96d9db0..88b7c6e 100644 --- a/src/Sampling/SamplingRule.php +++ b/src/Sampling/SamplingRule.php @@ -3,8 +3,8 @@ namespace Spatie\FlareClient\Sampling; use Closure; -use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\EntryPoint\EntryPoint; +use Spatie\FlareClient\Enums\EntryPointType; use Spatie\FlareClient\Sampling\Rules\ClosureSamplingRule; use Spatie\FlareClient\Sampling\Rules\CommandSamplingRule; use Spatie\FlareClient\Sampling\Rules\DeferredClosureSamplingRule;