From d03caa9cba540ebd4df1573eded10743c6a92366 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Tue, 22 Oct 2024 21:11:06 +0300 Subject: [PATCH 01/48] Updated otel initialisation --- .../CloudResourceDetector.php | 41 --------- .../PostFilterBatchSpanProcessor.php | 27 ++++++ .../SprykerInstrumentationBootstrap.php | 92 ++++++++++++++++++- .../SpanFilter/SamplerSpanFilter.php | 20 ---- .../Zed/Opentelemetry/OpentelemetryConfig.php | 68 +++++++++++++- 5 files changed, 179 insertions(+), 69 deletions(-) delete mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/ResourceDetector/CloudResourceDetector.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/ResourceDetector/CloudResourceDetector.php b/src/Spryker/Service/Opentelemetry/Instrumentation/ResourceDetector/CloudResourceDetector.php deleted file mode 100644 index dabe3da..0000000 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/ResourceDetector/CloudResourceDetector.php +++ /dev/null @@ -1,41 +0,0 @@ - gethostname(), - ]; - - return ResourceInfo::create(Attributes::create($attributes), ResourceAttributes::SCHEMA_URL); - } -} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php new file mode 100644 index 0000000..8cf003d --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -0,0 +1,27 @@ +getDuration() < OpentelemetryConfig::getSamplerThresholdNano() + && $span->toSpanData()->getParentSpanId() + && $span->toSpanData()->getStatus()->getCode() === StatusCode::STATUS_OK + ) { + return; + } + parent::onEnd($span); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 24b6340..d4f867c 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -7,8 +7,28 @@ namespace Spryker\Service\Opentelemetry\Instrumentation; +use OpenTelemetry\API\Common\Time\Clock; +use OpenTelemetry\API\Signals; +use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; +use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; +use OpenTelemetry\Contrib\Otlp\OtlpUtil; +use OpenTelemetry\Contrib\Otlp\SpanExporter; +use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Metrics\MeterProviderFactory; use OpenTelemetry\SDK\Registry; +use OpenTelemetry\SDK\Resource\ResourceInfo; +use OpenTelemetry\SDK\Resource\ResourceInfoFactory; +use OpenTelemetry\SDK\Sdk; +use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler; +use OpenTelemetry\SDK\Trace\Sampler\ParentBased; +use OpenTelemetry\SDK\Trace\TracerProvider; +use OpenTelemetry\SDK\Trace\TracerProviderInterface; +use OpenTelemetry\SemConv\ResourceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\ResourceDetector\CloudResourceDetector; +use Spryker\Service\Opentelemetry\Instrumentation\ResourceDetector\NameResourceDetector; +use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; +use Spryker\Shared\Opentelemetry\Request\RequestProcessor; +use Spryker\Zed\Opentelemetry\OpentelemetryConfig; /** * @method \Spryker\Service\Opentelemetry\OpentelemetryServiceFactory getFactory() @@ -25,14 +45,80 @@ class SprykerInstrumentationBootstrap */ protected const INSTANCE_ID = 'instance.id'; + /** + * @var string + */ + protected const INSTRUMENTATION_VERSION = '0.1'; + /** * @return void */ public static function register(): void { - Registry::registerResourceDetector( - static::INSTANCE_ID, - new CloudResourceDetector(), + $resource = ResourceInfoFactory::defaultResource()->merge(ResourceInfo::create(Attributes::create([ + ResourceAttributes::SERVICE_NAMESPACE => OpentelemetryConfig::getServiceNamespace(), + ResourceAttributes::SERVICE_VERSION => static::INSTRUMENTATION_VERSION, + ResourceAttributes::SERVICE_NAME => static::resolveServiceName(), + ]))); + + $meterProvider = (new MeterProviderFactory())->create($resource); + + Sdk::builder() + ->setTracerProvider(static::createTracerProvider($resource)) + ->setMeterProvider($meterProvider) + ->setPropagator(TraceContextPropagator::getInstance()) + ->setAutoShutdown(true) + ->buildAndRegisterGlobal(); + } + + /** + * @param $resource + * + * @return \OpenTelemetry\SDK\Trace\TracerProviderInterface + */ + protected static function createTracerProvider($resource): TracerProviderInterface + { + $spanExporter = new SpanExporter( + (new GrpcTransportFactory())->create(OpentelemetryConfig::getExporterEndpoint() . OtlpUtil::method(Signals::TRACE)) ); + + return TracerProvider::builder() + ->addSpanProcessor( + new PostFilterBatchSpanProcessor( + $spanExporter, + Clock::getDefault(), + ), + ) + ->setResource($resource) + ->setSampler(new ParentBased(new AlwaysOnSampler())) + ->build(); + } + + /** + * @return string + */ + protected static function resolveServiceName(): string + { + $request = (new RequestProcessor())->getRequest(); + + $cli = $request->server->get('argv'); + if ($cli) { + [$vendor, $bin, $application] = explode('/', $cli[0]); + + if ($application === 'console') { + return 'CLI ZED'; + } + return 'CLI ' . $application; + } + + $mapping = OpentelemetryConfig::getServiceNameMapping(); + + foreach ($mapping as $pattern => $serviceName) { + if (preg_match($pattern, $request->getHost())) { + return $serviceName; + } + } + + return 'Undefined service'; } } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php index 0ef0e03..bf1ed1a 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php @@ -23,26 +23,6 @@ class SamplerSpanFilter implements SpanFilterInterface */ public static function filter(SpanInterface $span, bool $forceToShow = false): SpanInterface { - if (!$span instanceof ReadableSpanInterface) { - return $span; - } - - $contextToChange = $span->getContext(); - $isSampled = $contextToChange->isSampled(); - $thresholdNanos = OpentelemetryConfig::getSamplerThresholdNano(); - $reflectionProperty = new ReflectionProperty($contextToChange, 'isSampled'); - $shouldBeSampled = $forceToShow || - ( - $isSampled - && - !( - $span->getDuration() < $thresholdNanos - && $span->toSpanData()->getParentSpanId() - && $span->toSpanData()->getStatus()->getCode() === StatusCode::STATUS_OK - ) - ); - $reflectionProperty->setValue($contextToChange, $shouldBeSampled); - return $span; } } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 3247eac..05fe27e 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -69,11 +69,11 @@ public function getExcludedDirs(): array public function getPathPatterns(): array { return [ - '#^vendor/spryker/[^/]+/.*/.*/(Zed|Shared)/.*/(?!Persistence|Presentation)[^/]+/.*#', - '#^vendor/spryker/[^/]+/Glue.*#', - '#^vendor/spryker(?:/spryker)?-shop/[^/]+/.*#', - '#^vendor/spryker-eco/[^/]+/.*#', - '#^src/Pyz/.*#', + '#/vendor/spryker/[//]+/.*/.*/(Zed|Shared)/.*/(?!Persistence|Presentation)[//]+/.*#', + '#/vendor/spryker/[//]+/Glue.*#', + '#/vendor/spryker(?:/spryker)?-shop/[//]+/.*#', + '#/vendor/spryker-eco/[//]+/.*#', + '#/src/Pyz/.*#', ]; } @@ -124,4 +124,62 @@ public static function getSamplerThresholdNano(): int return $multiplicator * static::THRESHOLD_NANOS; } + + /** + * @api + * + * @return string + */ + public static function getServiceNamespace(): string + { + return getenv('OTEL_SERVICE_NAMESPACE') ?: 'spryker'; + } + + /** + * @api + * + * @return string + */ + public static function getServiceName(): string + { + return getenv('OTEL_SERVICE_NAME') ?: 'Test'; + } + + /** + * @api + * + * @return string + */ + public static function getExporterEndpoint(): string + { + return getenv('OTEL_EXPORTER_OTLP_ENDPOINT') ?: 'http://collector:4317'; + } + + /** + * @return array + */ + public static function getExcludedURLs(): array + { + $urls = getenv('OTEL_PHP_EXCLUDED_URLS') ?: []; + + return explode(',', $urls); + } + + public static function getServiceNameMapping(): array + { + $mapping = getenv('OTEL_SERVICE_NAME_MAPPING') ?: '{}'; + $mapping = json_decode($mapping, true); + + if ($mapping === []) { + return [ + '/(?:https?:\/\/)?(yves)\./' => 'Yves', + '/(?:https?:\/\/)?(backoffice)\./' => 'Backoffice', + '/(?:https?:\/\/)?(glue)\./' => 'Legacy Glue', + '/(?:https?:\/\/)?(merchant)\./' => 'Merchant Portal', + '/(?:https?:\/\/)?(backend-gateway)\./' => 'Backend Gateway', + '/(?:https?:\/\/)?(glue-storefront)\./' => 'Glue Storefront', + '/(?:https?:\/\/)?(glue-backend)\./' => 'Glue Backend', + ]; + } + } } From 3e2ffd29aae675002c7a87e6e1018e4b6bf10667 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Wed, 23 Oct 2024 12:56:30 +0300 Subject: [PATCH 02/48] Disabled instrumentation on env value provided --- _register.php | 4 ++++ .../SprykerInstrumentationBootstrap.php | 10 +--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/_register.php b/_register.php index bfd776b..0eb360c 100644 --- a/_register.php +++ b/_register.php @@ -13,4 +13,8 @@ return; } +if (getenv('OTEL_SDK_DISABLED')) { + return; +} + SprykerInstrumentationBootstrap::register(); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index d4f867c..b7f46b3 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -15,7 +15,6 @@ use OpenTelemetry\Contrib\Otlp\SpanExporter; use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Metrics\MeterProviderFactory; -use OpenTelemetry\SDK\Registry; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; @@ -24,8 +23,6 @@ use OpenTelemetry\SDK\Trace\TracerProvider; use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SemConv\ResourceAttributes; -use Spryker\Service\Opentelemetry\Instrumentation\ResourceDetector\CloudResourceDetector; -use Spryker\Service\Opentelemetry\Instrumentation\ResourceDetector\NameResourceDetector; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; @@ -40,11 +37,6 @@ class SprykerInstrumentationBootstrap */ public const NAME = 'spryker'; - /** - * @var string - */ - protected const INSTANCE_ID = 'instance.id'; - /** * @var string */ @@ -118,7 +110,7 @@ protected static function resolveServiceName(): string return $serviceName; } } - + return 'Undefined service'; } } From 74fbcaf85a6f45dbc0f50dcdb3d8cb84bb78ac06 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Wed, 23 Oct 2024 18:37:11 +0300 Subject: [PATCH 03/48] Fixed generation --- src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 05fe27e..8785d9b 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -69,11 +69,11 @@ public function getExcludedDirs(): array public function getPathPatterns(): array { return [ - '#/vendor/spryker/[//]+/.*/.*/(Zed|Shared)/.*/(?!Persistence|Presentation)[//]+/.*#', - '#/vendor/spryker/[//]+/Glue.*#', - '#/vendor/spryker(?:/spryker)?-shop/[//]+/.*#', - '#/vendor/spryker-eco/[//]+/.*#', - '#/src/Pyz/.*#', + '#^vendor/spryker/[^/]+/.*/.*/(Zed|Shared)/.*/(?!Persistence|Presentation)[^/]+/.*#', + '#^vendor/spryker/[^/]+/Glue.*#', + '#^vendor/spryker(?:/spryker)?-shop/[^/]+/.*#', + '#^vendor/spryker-eco/[^/]+/.*#', + '#^src/Pyz/.*#', ]; } From 0ea4cd039e466999640caa85814965a36dbe6204 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Wed, 23 Oct 2024 20:17:50 +0300 Subject: [PATCH 04/48] Updated instrumentation enabling condition --- _register.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_register.php b/_register.php index 0eb360c..06d619e 100644 --- a/_register.php +++ b/_register.php @@ -13,7 +13,7 @@ return; } -if (getenv('OTEL_SDK_DISABLED')) { +if (getenv('OTEL_SDK_DISABLED') === true || getenv('OTEL_SDK_DISABLED') === 'true') { return; } From ee208c92eb39af62b84a6b8edea09c5610af8844 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 24 Oct 2024 10:57:04 +0300 Subject: [PATCH 05/48] Updated instrumentation sampling --- .../SprykerInstrumentationBootstrap.php | 5 +++-- src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index b7f46b3..472d5f5 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -18,8 +18,8 @@ use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; -use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler; use OpenTelemetry\SDK\Trace\Sampler\ParentBased; +use OpenTelemetry\SDK\Trace\Sampler\TraceIdRatioBasedSampler; use OpenTelemetry\SDK\Trace\TracerProvider; use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SemConv\ResourceAttributes; @@ -82,7 +82,7 @@ protected static function createTracerProvider($resource): TracerProviderInterfa ), ) ->setResource($resource) - ->setSampler(new ParentBased(new AlwaysOnSampler())) + ->setSampler(new ParentBased(new TraceIdRatioBasedSampler(OpentelemetryConfig::getSamplerProbability()))) ->build(); } @@ -100,6 +100,7 @@ protected static function resolveServiceName(): string if ($application === 'console') { return 'CLI ZED'; } + return 'CLI ' . $application; } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 8785d9b..973b595 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -182,4 +182,14 @@ public static function getServiceNameMapping(): array ]; } } + + /** + * @return float + */ + public static function getSamplerProbability(): float + { + $probability = getenv('OTEL_TRACES_SAMPLER_ARG') ?: 1.0; + + return (float)$probability; + } } From 03dfc3c28d5fcd98b23e2e627df54004322b9993 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 24 Oct 2024 17:35:56 +0300 Subject: [PATCH 06/48] Added filter for instrumentation only for public methods --- .../Generator/Collector/ClassCollector.php | 24 +++++++++++++++++++ .../Zed/Opentelemetry/OpentelemetryConfig.php | 9 +++++++ 2 files changed, 33 insertions(+) diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php index 7da082e..8fed8ac 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php @@ -199,6 +199,9 @@ protected function parseMethods(array $tokens): array for ($i = 0; $i < $tokensCount; $i++) { if ($tokens[$i][0] === T_FUNCTION) { + if (!$this->isMethodAllowed($tokens, $i)) { + break; + } $isAnonymousFunction = false; for ($j = $i + 1; $j < $tokensCount; $j++) { if ($tokens[$j] === '(') { @@ -238,6 +241,27 @@ protected function parseMethods(array $tokens): array return $methods; } + protected function isMethodAllowed(array $tokens, int $functionIndex): bool + { + if (!$this->config->areOnlyPublicMethodsInstrumented()) { + return true; + } + + if (isset($tokens[$functionIndex - 2][0]) && in_array($tokens[$functionIndex - 2][0], [T_PROTECTED, T_PRIVATE], true)) { + return false; + } + + if (isset($tokens[$functionIndex - 2][0]) + && $tokens[$functionIndex - 2][0] === T_STATIC + && isset($tokens[$functionIndex - 3][0]) + && in_array($tokens[$functionIndex - 3][0], [T_PROTECTED, T_PRIVATE], true) + ) { + return false; + } + + return true; + } + /** * @return array */ diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 973b595..f75026d 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -36,6 +36,7 @@ public function getExcludedDirs(): array { return [ 'Opentelemetry', + 'OpenTelemetry', 'Container', 'Transfer', 'Kernel', @@ -110,6 +111,14 @@ public function getOtelEnvVars(): array ]; } + /** + * @return bool + */ + public function areOnlyPublicMethodsInstrumented(): bool + { + return true; + } + /** * Specification: * - The threshold in nanoseconds for the span to be sampled. From 47184cc51ff0ab2a4dc8c539e8b300394e8dc975 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Mon, 28 Oct 2024 15:50:53 +0200 Subject: [PATCH 07/48] Reworked instrumentation initialisation --- .../CriticalSpanTraceIdRatioSampler.php | 85 ++++++++ .../Instrumentation/Span/SpanBuilder.php | 189 ++++++++++++++++++ .../SprykerInstrumentationBootstrap.php | 7 +- .../Instrumentation/Tracer/Tracer.php | 100 +++++++++ .../Instrumentation/Tracer/TracerProvider.php | 154 ++++++++++++++ .../Tracer/TracerProviderBuilder.php | 93 +++++++++ .../Zed/Opentelemetry/OpentelemetryConfig.php | 2 + 7 files changed, 626 insertions(+), 4 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php new file mode 100644 index 0000000..efa0d5a --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -0,0 +1,85 @@ + 1.0) { + throw new InvalidArgumentException('probability should be be between 0.0 and 1.0.'); + } + $this->probability = $probability; + } + + /** + * Returns `SamplingResult` based on probability. Respects the parent `SampleFlag` + * {@inheritdoc} + */ + public function shouldSample( + ContextInterface $parentContext, + string $traceId, + string $spanName, + int $spanKind, + AttributesInterface $attributes, + array $links, + ): SamplingResult { + $parentSpan = $this->parentSpan ?: Span::fromContext($parentContext); + $parentSpanContext = $parentSpan->getContext(); + $traceState = $parentSpanContext->getTraceState(); + + if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { + return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $traceState); + } + + /** + * Since php can only store up to 63 bit positive integers + */ + $traceIdLimit = (1 << 60) - 1; + $lowerOrderBytes = hexdec(substr($traceId, strlen($traceId) - 15, 15)); + $traceIdCondition = $lowerOrderBytes < round($this->probability * $traceIdLimit); + $decision = $traceIdCondition ? SamplingResult::RECORD_AND_SAMPLE : SamplingResult::DROP; + + return new SamplingResult($decision, [], $traceState); + } + + public function addParentSpan(SpanInterface $span): void + { + $this->parentSpan = $span; + } + + /** + * @return string + */ + public function getDescription(): string + { + return sprintf('%s{%.6F}', 'CriticalSpanTraceIdRatioSampler', $this->probability); + } + +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php new file mode 100644 index 0000000..c6ce443 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -0,0 +1,189 @@ + */ + private array $links = []; + + private AttributesBuilderInterface $attributesBuilder; + private int $totalNumberOfLinksAdded = 0; + private int $startEpochNanos = 0; + + /** @param non-empty-string $spanName */ + public function __construct( + private readonly string $spanName, + private readonly InstrumentationScopeInterface $instrumentationScope, + private readonly TracerSharedState $tracerSharedState, + ) { + $this->attributesBuilder = $this->tracerSharedState->getSpanLimits()->getAttributesFactory()->builder(); + } + + /** @inheritDoc */ + public function setParent(ContextInterface|false|null $context): SpanBuilderInterface + { + $this->parentContext = $context; + + return $this; + } + + /** + * @param \OpenTelemetry\API\Trace\SpanContextInterface $context + * @param iterable $attributes + * + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface + */ + public function addLink(SpanContextInterface $context, iterable $attributes = []): SpanBuilderInterface + { + if (!$context->isValid()) { + return $this; + } + + $this->totalNumberOfLinksAdded++; + + if (count($this->links) === $this->tracerSharedState->getSpanLimits()->getLinkCountLimit()) { + return $this; + } + + $this->links[] = new Link( + $context, + $this->tracerSharedState + ->getSpanLimits() + ->getLinkAttributesFactory() + ->builder($attributes) + ->build(), + ); + + return $this; + } + + /** @inheritDoc */ + public function setAttribute(string $key, mixed $value): SpanBuilderInterface + { + $this->attributesBuilder[$key] = $value; + + return $this; + } + + /** @inheritDoc */ + public function setAttributes(iterable $attributes): SpanBuilderInterface + { + foreach ($attributes as $key => $value) { + $this->attributesBuilder[$key] = $value; + } + + return $this; + } + + /** + * @inheritDoc + * + * @psalm-param SpanKind::KIND_* $spanKind + */ + public function setSpanKind(int $spanKind): SpanBuilderInterface + { + $this->spanKind = $spanKind; + + return $this; + } + + /** @inheritDoc */ + public function setStartTimestamp(int $timestampNanos): SpanBuilderInterface + { + if (0 > $timestampNanos) { + return $this; + } + + $this->startEpochNanos = $timestampNanos; + + return $this; + } + + /** @inheritDoc */ + public function startSpan(): \OpenTelemetry\API\Trace\SpanInterface + { + $parentContext = Context::resolve($this->parentContext); + $parentSpan = Span::fromContext($parentContext); + $parentSpanContext = $parentSpan->getContext(); + + $spanId = $this->tracerSharedState->getIdGenerator()->generateSpanId(); + + if (!$parentSpanContext->isValid()) { + $traceId = $this->tracerSharedState->getIdGenerator()->generateTraceId(); + } else { + $traceId = $parentSpanContext->getTraceId(); + } + + $sampler = $this + ->tracerSharedState + ->getSampler(); + $sampler->addParentSpan($parentSpan); + $samplingResult = $sampler + ->shouldSample( + $parentContext, + $traceId, + $this->spanName, + $this->spanKind, + $this->attributesBuilder->build(), + $this->links, + $parentSpan, + ); + $samplingDecision = $samplingResult->getDecision(); + $samplingResultTraceState = $samplingResult->getTraceState(); + + $spanContext = SpanContext::create( + $traceId, + $spanId, + SamplingResult::RECORD_AND_SAMPLE === $samplingDecision ? TraceFlags::SAMPLED : TraceFlags::DEFAULT, + $samplingResultTraceState, + ); + + if (!in_array($samplingDecision, [SamplingResult::RECORD_AND_SAMPLE, SamplingResult::RECORD_ONLY], true)) { + return Span::wrap($spanContext); + } + + $attributesBuilder = clone $this->attributesBuilder; + foreach ($samplingResult->getAttributes() as $key => $value) { + $attributesBuilder[$key] = $value; + } + + return Span::startSpan( + $this->spanName, + $spanContext, + $this->instrumentationScope, + $this->spanKind, + $parentSpan, + $parentContext, + $this->tracerSharedState->getSpanLimits(), + $this->tracerSharedState->getSpanProcessor(), + $this->tracerSharedState->getResource(), + $attributesBuilder, + $this->links, + $this->totalNumberOfLinksAdded, + $this->startEpochNanos, + ); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 472d5f5..780af22 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -18,12 +18,11 @@ use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; -use OpenTelemetry\SDK\Trace\Sampler\ParentBased; -use OpenTelemetry\SDK\Trace\Sampler\TraceIdRatioBasedSampler; -use OpenTelemetry\SDK\Trace\TracerProvider; use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SemConv\ResourceAttributes; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; +use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; @@ -82,7 +81,7 @@ protected static function createTracerProvider($resource): TracerProviderInterfa ), ) ->setResource($resource) - ->setSampler(new ParentBased(new TraceIdRatioBasedSampler(OpentelemetryConfig::getSamplerProbability()))) + ->setSampler(new CriticalSpanTraceIdRatioSampler(OpentelemetryConfig::getSamplerProbability())) ->build(); } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php new file mode 100644 index 0000000..17837c3 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php @@ -0,0 +1,100 @@ +tracerSharedState = $tracerSharedState; + $this->instrumentationScope = $instrumentationScope; + $this->config = $configurator ? $configurator->resolve($this->instrumentationScope) : TracerConfig::default(); + } + + /** + * @param string $spanName + * + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface + */ + public function spanBuilder(string $spanName): SpanBuilderInterface + { + if (ctype_space($spanName)) { + $spanName = static::FALLBACK_SPAN_NAME; + } + // If a Tracer is disabled, it MUST behave equivalently to No-op Tracer + if (!$this->config->isEnabled() || $this->tracerSharedState->hasShutdown()) { + return new NoopSpanBuilder(Context::storage()); + } + + return new SpanBuilder( + $spanName, + $this->instrumentationScope, + $this->tracerSharedState, + ); + } + + /** + * @return \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface + */ + public function getInstrumentationScope(): InstrumentationScopeInterface + { + return $this->instrumentationScope; + } + + /** + * @return bool + */ + public function isEnabled(): bool + { + return $this->config->isEnabled(); + } + + /** + * @param \OpenTelemetry\SDK\Common\InstrumentationScope\Configurator $configurator + * + * @return void + */ + public function updateConfig(Configurator $configurator): void + { + $this->config = $configurator->resolve($this->instrumentationScope); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php new file mode 100644 index 0000000..cbaf801 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php @@ -0,0 +1,154 @@ +build(); + + $this->tracerSharedState = new TracerSharedState( + $idGenerator, + $resource, + $spanLimits, + $sampler, + [$spanProcessor], + ); + $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); + $this->tracers = new WeakMap(); + } + + /** + * @param \OpenTelemetry\SDK\Common\Future\CancellationInterface|null $cancellation + * + * @return bool + */ + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return $this->tracerSharedState->getSpanProcessor()->forceFlush($cancellation); + } + + /** + * @param string $name + * @param string|null $version + * @param string|null $schemaUrl + * @param iterable $attributes + * + * @return \OpenTelemetry\API\Trace\TracerInterface + */ + public function getTracer( + string $name, + ?string $version = null, + ?string $schemaUrl = null, + iterable $attributes = [], + ): API\TracerInterface { + if ($this->tracerSharedState->hasShutdown()) { + return NoopTracer::getInstance(); + } + + $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); + $tracer = new Tracer( + $this->tracerSharedState, + $scope, + $this->configurator, + ); + $this->tracers->offsetSet($tracer, null); + + return $tracer; + } + + /** + * @return \OpenTelemetry\SDK\Trace\SamplerInterface + */ + public function getSampler(): SamplerInterface + { + return $this->tracerSharedState->getSampler(); + } + + /** + * @param \OpenTelemetry\SDK\Common\Future\CancellationInterface|null $cancellation + * + * @return bool + */ + public function shutdown(?CancellationInterface $cancellation = null): bool + { + if ($this->tracerSharedState->hasShutdown()) { + return true; + } + + return $this->tracerSharedState->shutdown($cancellation); + } + + /** + * @return \Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProviderBuilder + */ + public static function builder(): TracerProviderBuilder + { + return new TracerProviderBuilder(); + } + + /** + * @param \OpenTelemetry\SDK\Common\InstrumentationScope\Configurator $configurator + * + * @return void + */ + public function updateConfigurator(Configurator $configurator): void + { + $this->configurator = $configurator; + + foreach ($this->tracers as $tracer => $unused) { + $tracer->updateConfig($configurator); + } + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php new file mode 100644 index 0000000..857cec2 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php @@ -0,0 +1,93 @@ +spanProcessor = $spanProcessor; + + return $this; + } + + /** + * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource + * + * @return $this + */ + public function setResource(ResourceInfo $resource) + { + $this->resource = $resource; + + return $this; + } + + /** + * @param \OpenTelemetry\SDK\Trace\SamplerInterface $sampler + * + * @return $this + */ + public function setSampler(SamplerInterface $sampler) + { + $this->sampler = $sampler; + + return $this; + } + + /** + * @param \OpenTelemetry\SDK\Common\InstrumentationScope\Configurator $configurator + * + * @return $this + */ + public function setConfigurator(Configurator $configurator) + { + $this->configurator = $configurator; + + return $this; + } + + /** + * @return \OpenTelemetry\SDK\Trace\TracerProviderInterface + */ + public function build(): TracerProviderInterface + { + return new TracerProvider( + $this->spanProcessor, + $this->sampler, + $this->resource, + configurator: $this->configurator ?? Configurator::tracer(), + ); + } +} diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index f75026d..e74c0f8 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -190,6 +190,8 @@ public static function getServiceNameMapping(): array '/(?:https?:\/\/)?(glue-backend)\./' => 'Glue Backend', ]; } + + return $mapping; } /** From f17caead74591164e72452a565c557e9ea85156b Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Tue, 29 Oct 2024 17:01:16 +0200 Subject: [PATCH 08/48] Filtered covered code --- .../Opentelemetry/Instrumentation/Span/SpanBuilder.php | 1 - .../Generator/ContentCreator/HookContentCreator.php | 8 +++----- src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php | 3 +++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index c6ce443..c282058 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -149,7 +149,6 @@ public function startSpan(): \OpenTelemetry\API\Trace\SpanInterface $this->spanKind, $this->attributesBuilder->build(), $this->links, - $parentSpan, ); $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index 800b3af..ecfddbb 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -98,7 +98,7 @@ function: \'%s\', ->setAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::CODE_LINENO, $lineno) ->startSpan(); - \\OpenTelemetry\\Context\\Context::storage()->attach($span->storeInContext(\\OpenTelemetry\\Context\\Context::getCurrent())); + \\OpenTelemetry\\Context\\Context::storage()->attach($span->storeInContext($context)); }, post: static function ($instance, array $params, $returnValue, ?\Throwable $exception) { @@ -121,14 +121,12 @@ function: \'%s\', if (isset($exception)) { $span->recordException($exception); + $span->setAttribute(\'error_message\', isset($exception) ? $exception->getMessage() : \'\'); + $span->setAttribute(\'error_code\', isset($exception) ? $exception->getCode() : \'\'); } - $span->setAttribute(\'error_message\', isset($exception) ? $exception->getMessage() : \'\'); - $span->setAttribute(\'error_code\', isset($exception) ? $exception->getCode() : \'\'); $span->setStatus(isset($exception) ? \\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_ERROR : \\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_OK); - $span = \\Spryker\\Zed\\Opentelemetry\\Business\\Generator\\SpanFilter\\SamplerSpanFilter::filter($span); - $span->end(); } );', diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index e74c0f8..0ed3096 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -37,6 +37,9 @@ public function getExcludedDirs(): array return [ 'Opentelemetry', 'OpenTelemetry', + 'Dependency', + 'Acl', + 'AclEntity', 'Container', 'Transfer', 'Kernel', From 3a47f423af1b7439c2ce8ea0ec80cf61b913eecc Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Wed, 30 Oct 2024 10:49:13 +0200 Subject: [PATCH 09/48] Added metric exporter otlp factory registration to make sure that it exists on instrumentation boot --- .../Instrumentation/SprykerInstrumentationBootstrap.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 780af22..6b0af6f 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -11,10 +11,12 @@ use OpenTelemetry\API\Signals; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; +use OpenTelemetry\Contrib\Otlp\MetricExporterFactory; use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\Contrib\Otlp\SpanExporter; use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Metrics\MeterProviderFactory; +use OpenTelemetry\SDK\Registry; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; @@ -52,6 +54,7 @@ public static function register(): void ResourceAttributes::SERVICE_NAME => static::resolveServiceName(), ]))); + Registry::registerMetricExporterFactory('otlp', MetricExporterFactory::class); $meterProvider = (new MeterProviderFactory())->create($resource); Sdk::builder() From df5ca743a84806ef748b45f573cf30f1f1ab8c84 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 31 Oct 2024 11:34:28 +0200 Subject: [PATCH 10/48] Updated attributes setting --- .../Instrumentation/Span/Attributes.php | 64 ++++++++ .../Span/AttributesBuilder.php | 106 +++++++++++++ .../Span/AttributesFactory.php | 34 ++++ .../Instrumentation/Span/SpanBuilder.php | 18 +-- .../Instrumentation/Span/SpanLimitBuilder.php | 146 ++++++++++++++++++ 5 files changed, 359 insertions(+), 9 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php new file mode 100644 index 0000000..fe90aec --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php @@ -0,0 +1,64 @@ +builder($attributes)->build(); + } + + public static function factory(?int $attributeCountLimit = null, ?int $attributeValueLengthLimit = null): AttributesFactoryInterface + { + return new AttributesFactory($attributeCountLimit, $attributeValueLengthLimit); + } + + public function has(string $name): bool + { + return array_key_exists($name, $this->attributes); + } + + public function get(string $name) + { + return $this->attributes[$name] ?? null; + } + + /** @psalm-mutation-free */ + public function count(): int + { + return count($this->attributes); + } + + public function getIterator(): Traversable + { + foreach ($this->attributes as $key => $value) { + yield (string) $key => $value; + } + } + + public function toArray(): array + { + return $this->attributes; + } + + public function getDroppedAttributesCount(): int + { + return $this->droppedAttributesCount; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php new file mode 100644 index 0000000..9f2cd2e --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php @@ -0,0 +1,106 @@ +attributes, $this->droppedAttributesCount); + } + + public function merge(AttributesInterface $old, AttributesInterface $updating): AttributesInterface + { + $new = $old->toArray(); + $dropped = $old->getDroppedAttributesCount() + $updating->getDroppedAttributesCount(); + foreach ($updating->toArray() as $key => $value) { + if (count($new) === $this->attributeCountLimit && !array_key_exists($key, $new)) { + $dropped++; + } else { + $new[$key] = $value; + } + } + + return new Attributes($new, $dropped); + } + + public function offsetExists($offset): bool + { + return array_key_exists($offset, $this->attributes); + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + public function offsetGet($offset): mixed + { + return $this->attributes[$offset] ?? null; + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + public function offsetSet($offset, $value): void + { + if ($offset === null) { + return; + } + if ($value === null) { + unset($this->attributes[$offset]); + + return; + } + if (!in_array($offset, $this->getSafeAttributes()) && !$this->attributeValidator->validate($value)) { + $this->droppedAttributesCount++; + + return; + } + if (count($this->attributes) === $this->attributeCountLimit && !array_key_exists($offset, $this->attributes)) { + $this->droppedAttributesCount++; + + return; + } + + $this->attributes[$offset] = $value; + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + public function offsetUnset($offset): void + { + unset($this->attributes[$offset]); + } + + /** + * @return array + */ + protected function getSafeAttributes(): array + { + return [ + TraceAttributes::CODE_NAMESPACE, + TraceAttributes::CODE_FILEPATH, + TraceAttributes::CODE_LINENO, + TraceAttributes::CODE_FUNCTION, + TraceAttributes::URL_QUERY, + 'query', + TraceAttributes::HTTP_REQUEST_METHOD, + 'queue.name', + 'queryTime', + 'search.index', + 'search.query', + 'root.url', + TraceAttributes::URL_DOMAIN, + ]; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php new file mode 100644 index 0000000..a1eb0b8 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php @@ -0,0 +1,34 @@ +attributeCountLimit, + $this->attributeValueLengthLimit, + 0, + $attributeValidator ?? new AttributeValidator(), + ); + foreach ($attributes as $key => $value) { + $builder[$key] = $value; + } + + return $builder; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index c282058..a22b81e 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -19,25 +19,25 @@ class SpanBuilder implements SpanBuilderInterface { - private ContextInterface|false|null $parentContext = null; + protected ContextInterface|false|null $parentContext = null; /** * @psalm-var SpanKind::KIND_* */ - private int $spanKind = SpanKind::KIND_INTERNAL; + protected int $spanKind = SpanKind::KIND_INTERNAL; /** @var list */ - private array $links = []; + protected array $links = []; - private AttributesBuilderInterface $attributesBuilder; - private int $totalNumberOfLinksAdded = 0; - private int $startEpochNanos = 0; + protected AttributesBuilderInterface $attributesBuilder; + protected int $totalNumberOfLinksAdded = 0; + protected int $startEpochNanos = 0; /** @param non-empty-string $spanName */ public function __construct( - private readonly string $spanName, - private readonly InstrumentationScopeInterface $instrumentationScope, - private readonly TracerSharedState $tracerSharedState, + protected readonly string $spanName, + protected readonly InstrumentationScopeInterface $instrumentationScope, + protected readonly TracerSharedState $tracerSharedState, ) { $this->attributesBuilder = $this->tracerSharedState->getSpanLimits()->getAttributesFactory()->builder(); } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php new file mode 100644 index 0000000..c32d9b0 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php @@ -0,0 +1,146 @@ +attributeCountLimit = $attributeCountLimit; + + return $this; + } + + /** + * @param int $attributeValueLengthLimit Maximum allowed attribute value length + */ + public function setAttributeValueLengthLimit(int $attributeValueLengthLimit): SpanLimitsBuilder + { + $this->attributeValueLengthLimit = $attributeValueLengthLimit; + + return $this; + } + + /** + * @param int $eventCountLimit Maximum allowed span event count + */ + public function setEventCountLimit(int $eventCountLimit): SpanLimitsBuilder + { + $this->eventCountLimit = $eventCountLimit; + + return $this; + } + + /** + * @param int $linkCountLimit Maximum allowed span link count + */ + public function setLinkCountLimit(int $linkCountLimit): SpanLimitsBuilder + { + $this->linkCountLimit = $linkCountLimit; + + return $this; + } + + /** + * @param int $attributePerEventCountLimit Maximum allowed attribute per span event count + */ + public function setAttributePerEventCountLimit(int $attributePerEventCountLimit): SpanLimitsBuilder + { + $this->attributePerEventCountLimit = $attributePerEventCountLimit; + + return $this; + } + + /** + * @param int $attributePerLinkCountLimit Maximum allowed attribute per span link count + */ + public function setAttributePerLinkCountLimit(int $attributePerLinkCountLimit): SpanLimitsBuilder + { + $this->attributePerLinkCountLimit = $attributePerLinkCountLimit; + + return $this; + } + + /** + * @param bool $retain whether general identity attributes should be retained + * + * @see https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attributes.md#general-identity-attributes + */ + public function retainGeneralIdentityAttributes(bool $retain = true): SpanLimitsBuilder + { + $this->retainGeneralIdentityAttributes = $retain; + + return $this; + } + + /** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#span-limits + * @phan-suppress PhanDeprecatedClassConstant + */ + public function build(): SpanLimits + { + $attributeCountLimit = $this->attributeCountLimit + ?: Configuration::getInt(Env::OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_ATTRIBUTE_COUNT_LIMIT); + $attributeValueLengthLimit = $this->attributeValueLengthLimit + ?: Configuration::getInt(Env::OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, SpanLimits::DEFAULT_SPAN_ATTRIBUTE_LENGTH_LIMIT); + $eventCountLimit = $this->eventCountLimit + ?: Configuration::getInt(Env::OTEL_SPAN_EVENT_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_EVENT_COUNT_LIMIT); + $linkCountLimit = $this->linkCountLimit + ?: Configuration::getInt(Env::OTEL_SPAN_LINK_COUNT_LIMIT, SpanLimits::DEFAULT_SPAN_LINK_COUNT_LIMIT); + $attributePerEventCountLimit = $this->attributePerEventCountLimit + ?: Configuration::getInt(Env::OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_EVENT_ATTRIBUTE_COUNT_LIMIT); + $attributePerLinkCountLimit = $this->attributePerLinkCountLimit + ?: Configuration::getInt(Env::OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, SpanLimits::DEFAULT_LINK_ATTRIBUTE_COUNT_LIMIT); + + if ($attributeValueLengthLimit === PHP_INT_MAX) { + $attributeValueLengthLimit = null; + } + + $spanAttributesFactory = Attributes::factory($attributeCountLimit, $attributeValueLengthLimit); + + if (!$this->retainGeneralIdentityAttributes) { + $spanAttributesFactory = new FilteredAttributesFactory($spanAttributesFactory, [ + TraceAttributes::USER_ID, + TraceAttributes::USER_ROLES, + ]); + } + + return new SpanLimits( + $spanAttributesFactory, + Attributes::factory($attributePerEventCountLimit, $attributeValueLengthLimit), + Attributes::factory($attributePerLinkCountLimit, $attributeValueLengthLimit), + $eventCountLimit, + $linkCountLimit, + ); + } +} From f0c4443ba5c7db332952017e94baae3a19441345 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 31 Oct 2024 11:44:13 +0200 Subject: [PATCH 11/48] Updated attributes setting --- .../Service/Opentelemetry/Instrumentation/Span/Attributes.php | 1 - .../Opentelemetry/Instrumentation/Span/AttributesFactory.php | 1 - .../Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php | 1 - .../Opentelemetry/Instrumentation/Tracer/TracerProvider.php | 4 ++-- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php index fe90aec..6f15325 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php @@ -3,7 +3,6 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Span; use IteratorAggregate; -use OpenTelemetry\SDK\Common\Attribute\AttributesFactory; use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use Traversable; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php index a1eb0b8..f74b69b 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php @@ -2,7 +2,6 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Span; -use OpenTelemetry\SDK\Common\Attribute\AttributesBuilder; use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface; use OpenTelemetry\SDK\Common\Attribute\AttributeValidator; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php index c32d9b0..22e2c4b 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php @@ -2,7 +2,6 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Span; -use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Attribute\FilteredAttributesFactory; use OpenTelemetry\SDK\Common\Configuration\Configuration; use OpenTelemetry\SDK\Common\Configuration\Variables as Env; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php index cbaf801..63f55ba 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php @@ -6,7 +6,6 @@ use OpenTelemetry\SDK\Trace\RandomIdGenerator; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SpanLimits; -use OpenTelemetry\SDK\Trace\SpanLimitsBuilder; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SDK\Trace\TracerSharedState; @@ -18,6 +17,7 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Resource\ResourceInfo; +use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanLimitBuilder; use WeakMap; class TracerProvider implements TracerProviderInterface @@ -56,7 +56,7 @@ public function __construct( protected ?Configurator $configurator = null, ) { $idGenerator ??= new RandomIdGenerator(); - $spanLimits ??= (new SpanLimitsBuilder())->build(); + $spanLimits ??= (new SpanLimitBuilder())->build(); $this->tracerSharedState = new TracerSharedState( $idGenerator, From 5ff2f6eb063bf3d5850fb92b5b007075ed05b0e6 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Fri, 1 Nov 2024 17:41:06 +0200 Subject: [PATCH 12/48] Updated code readability and also cached tracer --- .../CriticalSpanTraceIdRatioSampler.php | 27 +++- .../ParentSpanAwareSamplerInterface.php | 20 +++ .../Span/AttributesBuilder.php | 46 +++++- .../Span/AttributesFactory.php | 21 ++- .../Instrumentation/Span/SpanBuilder.php | 137 ++++++++++++------ .../Instrumentation/Span/SpanLimitBuilder.php | 87 ++++++----- .../PostFilterBatchSpanProcessor.php | 8 +- .../SprykerInstrumentationBootstrap.php | 89 ++++++++---- .../Instrumentation/Tracer/Tracer.php | 5 + .../Instrumentation/Tracer/TracerProvider.php | 47 +++--- .../Tracer/TracerProviderBuilder.php | 5 + .../Generator/Collector/ClassCollector.php | 37 +++++ .../Zed/Opentelemetry/OpentelemetryConfig.php | 45 +++--- 13 files changed, 416 insertions(+), 158 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index efa0d5a..b7c1b16 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -1,5 +1,10 @@ probability * $traceIdLimit); @@ -69,6 +77,11 @@ public function shouldSample( return new SamplingResult($decision, [], $traceState); } + /** + * @param \OpenTelemetry\API\Trace\SpanInterface $span + * + * @return void + */ public function addParentSpan(SpanInterface $span): void { $this->parentSpan = $span; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php new file mode 100644 index 0000000..f60064e --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php @@ -0,0 +1,20 @@ +attributes, $this->droppedAttributesCount); } + /** + * @param \OpenTelemetry\SDK\Common\Attribute\AttributesInterface $old + * @param \OpenTelemetry\SDK\Common\Attribute\AttributesInterface $updating + * + * @return \OpenTelemetry\SDK\Common\Attribute\AttributesInterface + */ public function merge(AttributesInterface $old, AttributesInterface $updating): AttributesInterface { $new = $old->toArray(); @@ -34,21 +52,31 @@ public function merge(AttributesInterface $old, AttributesInterface $updating): return new Attributes($new, $dropped); } + /** + * @param mixed $offset + * + * @return bool + */ public function offsetExists($offset): bool { return array_key_exists($offset, $this->attributes); } /** - * @phan-suppress PhanUndeclaredClassAttribute + * @param mixed $offset + * + * @return mixed */ - public function offsetGet($offset): mixed + public function offsetGet($offset) { return $this->attributes[$offset] ?? null; } /** - * @phan-suppress PhanUndeclaredClassAttribute + * @param mixed $offset + * @param mixed $value + * + * @return void */ public function offsetSet($offset, $value): void { @@ -75,7 +103,9 @@ public function offsetSet($offset, $value): void } /** - * @phan-suppress PhanUndeclaredClassAttribute + * @param mixed $offset + * + * @return void */ public function offsetUnset($offset): void { @@ -83,7 +113,7 @@ public function offsetUnset($offset): void } /** - * @return array + * @return array */ protected function getSafeAttributes(): array { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php index f74b69b..d212b8b 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesFactory.php @@ -1,5 +1,10 @@ */ + /** + * @var array<\OpenTelemetry\SDK\Trace\LinkInterface> + */ protected array $links = []; + /** + * @var \OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface + */ protected AttributesBuilderInterface $attributesBuilder; + + /** + * @var int + */ protected int $totalNumberOfLinksAdded = 0; + + /** + * @var int + */ protected int $startEpochNanos = 0; - /** @param non-empty-string $spanName */ + /** + * @param string $spanName + * @param \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface $instrumentationScope + * @param \OpenTelemetry\SDK\Trace\TracerSharedState $tracerSharedState + */ public function __construct( - protected readonly string $spanName, - protected readonly InstrumentationScopeInterface $instrumentationScope, - protected readonly TracerSharedState $tracerSharedState, + protected string $spanName, + protected InstrumentationScopeInterface $instrumentationScope, + protected TracerSharedState $tracerSharedState, ) { $this->attributesBuilder = $this->tracerSharedState->getSpanLimits()->getAttributesFactory()->builder(); } - /** @inheritDoc */ + /** + * @param \OpenTelemetry\Context\ContextInterface|false|null $context + * + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface + */ public function setParent(ContextInterface|false|null $context): SpanBuilderInterface { $this->parentContext = $context; @@ -80,15 +110,24 @@ public function addLink(SpanContextInterface $context, iterable $attributes = [] return $this; } - /** @inheritDoc */ - public function setAttribute(string $key, mixed $value): SpanBuilderInterface + /** + * @param string $key + * @param mixed $value + * + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface + */ + public function setAttribute(string $key, $value): SpanBuilderInterface { $this->attributesBuilder[$key] = $value; return $this; } - /** @inheritDoc */ + /** + * @param iterable $attributes + * + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface + */ public function setAttributes(iterable $attributes): SpanBuilderInterface { foreach ($attributes as $key => $value) { @@ -99,9 +138,9 @@ public function setAttributes(iterable $attributes): SpanBuilderInterface } /** - * @inheritDoc + * @param int $spanKind * - * @psalm-param SpanKind::KIND_* $spanKind + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface */ public function setSpanKind(int $spanKind): SpanBuilderInterface { @@ -110,10 +149,14 @@ public function setSpanKind(int $spanKind): SpanBuilderInterface return $this; } - /** @inheritDoc */ + /** + * @param int $timestampNanos + * + * @return \OpenTelemetry\API\Trace\SpanBuilderInterface + */ public function setStartTimestamp(int $timestampNanos): SpanBuilderInterface { - if (0 > $timestampNanos) { + if ($timestampNanos < 0) { return $this; } @@ -122,41 +165,26 @@ public function setStartTimestamp(int $timestampNanos): SpanBuilderInterface return $this; } - /** @inheritDoc */ - public function startSpan(): \OpenTelemetry\API\Trace\SpanInterface + /** + * @return \OpenTelemetry\API\Trace\SpanInterface + */ + public function startSpan(): SpanInterface { $parentContext = Context::resolve($this->parentContext); $parentSpan = Span::fromContext($parentContext); $parentSpanContext = $parentSpan->getContext(); $spanId = $this->tracerSharedState->getIdGenerator()->generateSpanId(); + $traceId = $parentSpanContext->isValid() ? $parentSpanContext->getTraceId() : $this->tracerSharedState->getIdGenerator()->generateTraceId(); - if (!$parentSpanContext->isValid()) { - $traceId = $this->tracerSharedState->getIdGenerator()->generateTraceId(); - } else { - $traceId = $parentSpanContext->getTraceId(); - } - - $sampler = $this - ->tracerSharedState - ->getSampler(); - $sampler->addParentSpan($parentSpan); - $samplingResult = $sampler - ->shouldSample( - $parentContext, - $traceId, - $this->spanName, - $this->spanKind, - $this->attributesBuilder->build(), - $this->links, - ); + $samplingResult = $this->getSamplingResult($parentSpan, $parentContext, $traceId); $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); $spanContext = SpanContext::create( $traceId, $spanId, - SamplingResult::RECORD_AND_SAMPLE === $samplingDecision ? TraceFlags::SAMPLED : TraceFlags::DEFAULT, + $samplingDecision === SamplingResult::RECORD_AND_SAMPLE ? TraceFlags::SAMPLED : TraceFlags::DEFAULT, $samplingResultTraceState, ); @@ -164,11 +192,6 @@ public function startSpan(): \OpenTelemetry\API\Trace\SpanInterface return Span::wrap($spanContext); } - $attributesBuilder = clone $this->attributesBuilder; - foreach ($samplingResult->getAttributes() as $key => $value) { - $attributesBuilder[$key] = $value; - } - return Span::startSpan( $this->spanName, $spanContext, @@ -179,10 +202,38 @@ public function startSpan(): \OpenTelemetry\API\Trace\SpanInterface $this->tracerSharedState->getSpanLimits(), $this->tracerSharedState->getSpanProcessor(), $this->tracerSharedState->getResource(), - $attributesBuilder, + $this->attributesBuilder, $this->links, $this->totalNumberOfLinksAdded, $this->startEpochNanos, ); } + + /** + * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan + * @param \OpenTelemetry\Context\ContextInterface $parentContext + * @param string $traceId + * + * @return \OpenTelemetry\SDK\Trace\SamplingResult + */ + protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface $parentContext, string $traceId): SamplingResult + { + $sampler = $this + ->tracerSharedState + ->getSampler(); + + if ($sampler instanceof ParentSpanAwareSamplerInterface) { + $sampler->addParentSpan($parentSpan); + } + + return $sampler + ->shouldSample( + $parentContext, + $traceId, + $this->spanName, + $this->spanKind, + $this->attributesBuilder->build(), + $this->links, + ); + } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php index 22e2c4b..66eda06 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanLimitBuilder.php @@ -1,5 +1,10 @@ attributeCountLimit = $attributeCountLimit; @@ -41,9 +58,11 @@ public function setAttributeCountLimit(int $attributeCountLimit): SpanLimitsBuil } /** - * @param int $attributeValueLengthLimit Maximum allowed attribute value length + * @param int $attributeValueLengthLimit + * + * @return $this */ - public function setAttributeValueLengthLimit(int $attributeValueLengthLimit): SpanLimitsBuilder + public function setAttributeValueLengthLimit(int $attributeValueLengthLimit) { $this->attributeValueLengthLimit = $attributeValueLengthLimit; @@ -51,9 +70,11 @@ public function setAttributeValueLengthLimit(int $attributeValueLengthLimit): Sp } /** - * @param int $eventCountLimit Maximum allowed span event count + * @param int $eventCountLimit + * + * @return $this */ - public function setEventCountLimit(int $eventCountLimit): SpanLimitsBuilder + public function setEventCountLimit(int $eventCountLimit) { $this->eventCountLimit = $eventCountLimit; @@ -61,9 +82,11 @@ public function setEventCountLimit(int $eventCountLimit): SpanLimitsBuilder } /** - * @param int $linkCountLimit Maximum allowed span link count + * @param int $linkCountLimit + * + * @return $this */ - public function setLinkCountLimit(int $linkCountLimit): SpanLimitsBuilder + public function setLinkCountLimit(int $linkCountLimit) { $this->linkCountLimit = $linkCountLimit; @@ -71,9 +94,10 @@ public function setLinkCountLimit(int $linkCountLimit): SpanLimitsBuilder } /** - * @param int $attributePerEventCountLimit Maximum allowed attribute per span event count + * @param int $attributePerEventCountLimit + * @return $this */ - public function setAttributePerEventCountLimit(int $attributePerEventCountLimit): SpanLimitsBuilder + public function setAttributePerEventCountLimit(int $attributePerEventCountLimit) { $this->attributePerEventCountLimit = $attributePerEventCountLimit; @@ -81,9 +105,11 @@ public function setAttributePerEventCountLimit(int $attributePerEventCountLimit) } /** - * @param int $attributePerLinkCountLimit Maximum allowed attribute per span link count + * @param int $attributePerLinkCountLimit + * + * @return $this */ - public function setAttributePerLinkCountLimit(int $attributePerLinkCountLimit): SpanLimitsBuilder + public function setAttributePerLinkCountLimit(int $attributePerLinkCountLimit) { $this->attributePerLinkCountLimit = $attributePerLinkCountLimit; @@ -91,11 +117,11 @@ public function setAttributePerLinkCountLimit(int $attributePerLinkCountLimit): } /** - * @param bool $retain whether general identity attributes should be retained + * @param bool $retain * - * @see https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attributes.md#general-identity-attributes + * @return $this */ - public function retainGeneralIdentityAttributes(bool $retain = true): SpanLimitsBuilder + public function retainGeneralIdentityAttributes(bool $retain = true) { $this->retainGeneralIdentityAttributes = $retain; @@ -103,8 +129,7 @@ public function retainGeneralIdentityAttributes(bool $retain = true): SpanLimits } /** - * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#span-limits - * @phan-suppress PhanDeprecatedClassConstant + * @return \OpenTelemetry\SDK\Trace\SpanLimits */ public function build(): SpanLimits { @@ -125,14 +150,10 @@ public function build(): SpanLimits $attributeValueLengthLimit = null; } - $spanAttributesFactory = Attributes::factory($attributeCountLimit, $attributeValueLengthLimit); - - if (!$this->retainGeneralIdentityAttributes) { - $spanAttributesFactory = new FilteredAttributesFactory($spanAttributesFactory, [ - TraceAttributes::USER_ID, - TraceAttributes::USER_ROLES, - ]); - } + $spanAttributesFactory = new FilteredAttributesFactory(Attributes::factory($attributeCountLimit, $attributeValueLengthLimit), [ + TraceAttributes::USER_ID, + TraceAttributes::USER_ROLES, + ]); return new SpanLimits( $spanAttributesFactory, diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 8cf003d..cf22b5e 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -1,5 +1,10 @@ getDuration() < OpentelemetryConfig::getSamplerThresholdNano() + if ( + $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() && $span->toSpanData()->getParentSpanId() && $span->toSpanData()->getStatus()->getCode() === StatusCode::STATUS_OK ) { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 6b0af6f..4523c4b 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -11,15 +11,17 @@ use OpenTelemetry\API\Signals; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; -use OpenTelemetry\Contrib\Otlp\MetricExporterFactory; use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\Contrib\Otlp\SpanExporter; use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Metrics\MeterProviderFactory; -use OpenTelemetry\SDK\Registry; +use OpenTelemetry\SDK\Metrics\MeterProviderInterface; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; +use OpenTelemetry\SDK\Trace\SamplerInterface; +use OpenTelemetry\SDK\Trace\SpanExporterInterface; +use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SemConv\ResourceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; @@ -48,46 +50,81 @@ class SprykerInstrumentationBootstrap */ public static function register(): void { - $resource = ResourceInfoFactory::defaultResource()->merge(ResourceInfo::create(Attributes::create([ - ResourceAttributes::SERVICE_NAMESPACE => OpentelemetryConfig::getServiceNamespace(), - ResourceAttributes::SERVICE_VERSION => static::INSTRUMENTATION_VERSION, - ResourceAttributes::SERVICE_NAME => static::resolveServiceName(), - ]))); - - Registry::registerMetricExporterFactory('otlp', MetricExporterFactory::class); - $meterProvider = (new MeterProviderFactory())->create($resource); + $resource = static::createResource(); Sdk::builder() ->setTracerProvider(static::createTracerProvider($resource)) - ->setMeterProvider($meterProvider) + ->setMeterProvider(static::createMeterProvider($resource)) ->setPropagator(TraceContextPropagator::getInstance()) ->setAutoShutdown(true) ->buildAndRegisterGlobal(); } /** - * @param $resource + * @return \OpenTelemetry\SDK\Resource\ResourceInfo + */ + protected static function createResource(): ResourceInfo + { + return ResourceInfoFactory::defaultResource()->merge(ResourceInfo::create(Attributes::create([ + ResourceAttributes::SERVICE_NAMESPACE => OpentelemetryConfig::getServiceNamespace(), + ResourceAttributes::SERVICE_VERSION => static::INSTRUMENTATION_VERSION, + ResourceAttributes::SERVICE_NAME => static::resolveServiceName(), + ]))); + } + + /** + * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource * - * @return \OpenTelemetry\SDK\Trace\TracerProviderInterface + * @return \OpenTelemetry\SDK\Metrics\MeterProviderInterface */ - protected static function createTracerProvider($resource): TracerProviderInterface + protected static function createMeterProvider(ResourceInfo $resource): MeterProviderInterface { - $spanExporter = new SpanExporter( - (new GrpcTransportFactory())->create(OpentelemetryConfig::getExporterEndpoint() . OtlpUtil::method(Signals::TRACE)) - ); + return (new MeterProviderFactory())->create($resource); + } + /** + * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource + * + * @return \OpenTelemetry\SDK\Trace\TracerProviderInterface + */ + protected static function createTracerProvider(ResourceInfo $resource): TracerProviderInterface + { return TracerProvider::builder() - ->addSpanProcessor( - new PostFilterBatchSpanProcessor( - $spanExporter, - Clock::getDefault(), - ), - ) + ->addSpanProcessor(static::createSpanProcessor()) ->setResource($resource) - ->setSampler(new CriticalSpanTraceIdRatioSampler(OpentelemetryConfig::getSamplerProbability())) + ->setSampler(static::createSampler()) ->build(); } + /** + * @return \OpenTelemetry\SDK\Trace\SpanExporterInterface + */ + protected static function createSpanExporter(): SpanExporterInterface + { + return new SpanExporter( + (new GrpcTransportFactory())->create(OpentelemetryConfig::getExporterEndpoint() . OtlpUtil::method(Signals::TRACE)), + ); + } + + /** + * @return \OpenTelemetry\SDK\Trace\SpanProcessorInterface + */ + protected static function createSpanProcessor(): SpanProcessorInterface + { + return new PostFilterBatchSpanProcessor( + static::createSpanExporter(), + Clock::getDefault(), + ); + } + + /** + * @return \OpenTelemetry\API\Trace\SamplerInterface + */ + protected static function createSampler(): SamplerInterface + { + return new CriticalSpanTraceIdRatioSampler(OpentelemetryConfig::getSamplerProbability()); + } + /** * @return string */ @@ -103,7 +140,7 @@ protected static function resolveServiceName(): string return 'CLI ZED'; } - return 'CLI ' . $application; + return sprintf('CLI %s', strtoupper($application)); } $mapping = OpentelemetryConfig::getServiceNameMapping(); @@ -114,6 +151,6 @@ protected static function resolveServiceName(): string } } - return 'Undefined service'; + return OpentelemetryConfig::getDefaultServiceName(); } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php index 17837c3..141f751 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php @@ -1,5 +1,10 @@ build(); + $idGenerator = new RandomIdGenerator(); + $spanLimits = (new SpanLimitBuilder())->build(); $this->tracerSharedState = new TracerSharedState( $idGenerator, @@ -65,7 +70,7 @@ public function __construct( $sampler, [$spanProcessor], ); - $this->instrumentationScopeFactory = $instrumentationScopeFactory ?? new InstrumentationScopeFactory(Attributes::factory()); + $this->instrumentationScopeFactory = new InstrumentationScopeFactory(Attributes::factory()); $this->tracers = new WeakMap(); } @@ -83,7 +88,7 @@ public function forceFlush(?CancellationInterface $cancellation = null): bool * @param string $name * @param string|null $version * @param string|null $schemaUrl - * @param iterable $attributes + * @param iterable|array $attributes * * @return \OpenTelemetry\API\Trace\TracerInterface */ @@ -92,11 +97,15 @@ public function getTracer( ?string $version = null, ?string $schemaUrl = null, iterable $attributes = [], - ): API\TracerInterface { + ): TracerInterface { if ($this->tracerSharedState->hasShutdown()) { return NoopTracer::getInstance(); } + if (static::$tracer) { + return static::$tracer; + } + $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); $tracer = new Tracer( $this->tracerSharedState, @@ -105,7 +114,9 @@ public function getTracer( ); $this->tracers->offsetSet($tracer, null); - return $tracer; + static::$tracer = $tracer; + + return static::$tracer; } /** diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php index 857cec2..b963c3e 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProviderBuilder.php @@ -1,5 +1,10 @@ checkForPublicMethods($tokens, $functionIndex) && $this->checkForSimpleMethods($tokens, $functionIndex); + } + + /** + * @param array $tokens + * @param int $functionIndex + * + * @return bool + */ + protected function checkForPublicMethods(array $tokens, int $functionIndex): bool { if (!$this->config->areOnlyPublicMethodsInstrumented()) { return true; @@ -262,6 +273,32 @@ protected function isMethodAllowed(array $tokens, int $functionIndex): bool return true; } + /** + * @param array $tokens + * @param int $functionIndex + * + * @return bool + */ + protected function checkForSimpleMethods(array $tokens, int $functionIndex): bool + { + for ($i = $functionIndex + 1; $i < count($tokens); $i++) { + if ($tokens[$i] === '{') { + $count = 0; + for ($j = $i + 1; $j < count($tokens); $j++) { + $count++; + if ($count < 3 && $tokens[$j][0] === T_RETURN && in_array($tokens[$j + 2][0], [T_STRING, T_ARRAY, T_NEW, ], true)) { + return false; + } + if ($tokens[$j] === '}') { + return true; + } + } + } + } + + return true; + } + /** * @return array */ diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 0ed3096..c7bdd7e 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -13,16 +13,9 @@ class OpentelemetryConfig extends AbstractBundleConfig { /** - * Specification: - * - The threshold in nanoseconds for the span to be sampled. - * - * @api - * - * @deprecated Will be removed as a public API. Please use getSamplerThresholdNano() instead. - * * @var int */ - public const THRESHOLD_NANOS = 1000000; + protected const THRESHOLD_NANOS = 1000000; /** * Specification: @@ -115,6 +108,11 @@ public function getOtelEnvVars(): array } /** + * Specification: + * - Set to false if you want to instrument all methods, including private and protected ones. + * + * @api + * * @return bool */ public function areOnlyPublicMethodsInstrumented(): bool @@ -147,16 +145,6 @@ public static function getServiceNamespace(): string return getenv('OTEL_SERVICE_NAMESPACE') ?: 'spryker'; } - /** - * @api - * - * @return string - */ - public static function getServiceName(): string - { - return getenv('OTEL_SERVICE_NAME') ?: 'Test'; - } - /** * @api * @@ -168,7 +156,9 @@ public static function getExporterEndpoint(): string } /** - * @return array + * @api + * + * @return array */ public static function getExcludedURLs(): array { @@ -177,6 +167,11 @@ public static function getExcludedURLs(): array return explode(',', $urls); } + /** + * @api + * + * @return array + */ public static function getServiceNameMapping(): array { $mapping = getenv('OTEL_SERVICE_NAME_MAPPING') ?: '{}'; @@ -198,6 +193,18 @@ public static function getServiceNameMapping(): array } /** + * @api + * + * @return string + */ + public static function getDefaultServiceName(): string + { + return getenv('OTEL_DEFAULT_SERVICE_NAME') ?: 'Default Service'; + } + + /** + * @api + * * @return float */ public static function getSamplerProbability(): float From b9cf95f7c9bdfd5194943178bfe0d08fcebb089d Mon Sep 17 00:00:00 2001 From: Anton Smarovydlo Date: Fri, 8 Nov 2024 11:51:45 +0100 Subject: [PATCH 13/48] Disable modules instrumentation if opentelemetry instrumentation is disabled. --- _register.php | 4 ++++ composer.json | 1 + 2 files changed, 5 insertions(+) diff --git a/_register.php b/_register.php index 06d619e..b18d9a1 100644 --- a/_register.php +++ b/_register.php @@ -5,6 +5,10 @@ use OpenTelemetry\SDK\Sdk; use Spryker\Service\Opentelemetry\Instrumentation\SprykerInstrumentationBootstrap; +if (Sdk::isDisabled()) { + return; +} + if (class_exists(Sdk::class) && Sdk::isInstrumentationDisabled(SprykerInstrumentationBootstrap::NAME) === true) { return; } diff --git a/composer.json b/composer.json index 611d6d9..823235f 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "require": { "open-telemetry/api": "^1.0", "open-telemetry/sdk": "^1.0", + "open-telemetry/sdk": "^1.0", "open-telemetry/sem-conv": "^1.0", "php": ">=8.1", "spryker/kernel": "^3.30.0", From 0ee71853efeffe2a1d4b290fadf723b8d6563cf6 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 14 Nov 2024 14:36:06 +0200 Subject: [PATCH 14/48] Added and fixed a root span --- _register.php | 2 +- otel-autoload-example.php | 4 +- .../SprykerInstrumentationBootstrap.php | 74 +++++++++++++++++-- .../Zed/Opentelemetry/OpentelemetryConfig.php | 1 + 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/_register.php b/_register.php index 06d619e..bf9c4db 100644 --- a/_register.php +++ b/_register.php @@ -13,7 +13,7 @@ return; } -if (getenv('OTEL_SDK_DISABLED') === true || getenv('OTEL_SDK_DISABLED') === 'true') { +if (Sdk::isDisabled()) { return; } diff --git a/otel-autoload-example.php b/otel-autoload-example.php index 943179b..8ac77f9 100644 --- a/otel-autoload-example.php +++ b/otel-autoload-example.php @@ -3,12 +3,14 @@ * This file should be copied to the root of Spryker application and enabled in `autoload.files` section of composer.json file. */ +use OpenTelemetry\SDK\Sdk; + $autoload = function (string $class) { $convertedClassName = str_replace('\\', '-', $class); $hookFilePath = __DIR__.'/src/Generated/OpenTelemetry/Hooks/' . $convertedClassName . 'Hook.php'; - if (getenv('OTEL_SDK_DISABLED') !== true && file_exists($hookFilePath)) { + if (!Sdk::isDisabled() && file_exists($hookFilePath)) { include_once $hookFilePath; } }; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 4523c4b..dca42ea 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -10,10 +10,15 @@ use OpenTelemetry\API\Common\Time\Clock; use OpenTelemetry\API\Signals; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; +use OpenTelemetry\API\Trace\Span; +use OpenTelemetry\API\Trace\SpanInterface; +use OpenTelemetry\API\Trace\SpanKind; +use OpenTelemetry\Context\Context; use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\Contrib\Otlp\SpanExporter; use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\Util\ShutdownHandler; use OpenTelemetry\SDK\Metrics\MeterProviderFactory; use OpenTelemetry\SDK\Metrics\MeterProviderInterface; use OpenTelemetry\SDK\Resource\ResourceInfo; @@ -24,9 +29,12 @@ use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SemConv\ResourceAttributes; +use OpenTelemetry\SemConv\TraceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; +use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; +use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; @@ -45,30 +53,45 @@ class SprykerInstrumentationBootstrap */ protected const INSTRUMENTATION_VERSION = '0.1'; + /** + * @var \OpenTelemetry\API\Trace\SpanInterface|null + */ + protected static ?SpanInterface $rootSpan = null; + /** * @return void */ public static function register(): void { - $resource = static::createResource(); + $serviceName = static::resolveServiceName(); + $resource = static::createResource($serviceName); + + $tracerProvider = static::createTracerProvider($resource); + $meterProvider = static::createMeterProvider($resource); Sdk::builder() - ->setTracerProvider(static::createTracerProvider($resource)) - ->setMeterProvider(static::createMeterProvider($resource)) + ->setTracerProvider($tracerProvider) + ->setMeterProvider($meterProvider) ->setPropagator(TraceContextPropagator::getInstance()) - ->setAutoShutdown(true) ->buildAndRegisterGlobal(); + + static::registerRootSpan($serviceName); + + ShutdownHandler::register($tracerProvider->shutdown(...)); + ShutdownHandler::register($meterProvider->shutdown(...)); } /** + * @param string $serviceName + * * @return \OpenTelemetry\SDK\Resource\ResourceInfo */ - protected static function createResource(): ResourceInfo + protected static function createResource(string $serviceName): ResourceInfo { return ResourceInfoFactory::defaultResource()->merge(ResourceInfo::create(Attributes::create([ ResourceAttributes::SERVICE_NAMESPACE => OpentelemetryConfig::getServiceNamespace(), ResourceAttributes::SERVICE_VERSION => static::INSTRUMENTATION_VERSION, - ResourceAttributes::SERVICE_NAME => static::resolveServiceName(), + ResourceAttributes::SERVICE_NAME => $serviceName, ]))); } @@ -153,4 +176,43 @@ protected static function resolveServiceName(): string return OpentelemetryConfig::getDefaultServiceName(); } + + /** + * @param string $servicedName + * @return void + */ + protected static function registerRootSpan(string $servicedName): void + { + $request = (new RequestProcessor())->getRequest(); + + $instrumentation = CachedInstrumentation::getCachedInstrumentation(); + $parent = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder($servicedName . ' root') + ->setParent($parent) + ->setSpanKind(SpanKind::KIND_SERVER) + ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) + ->setAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE, true) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($parent)); + + register_shutdown_function([static::class, 'shutdownHandler']); + } + + /** + * @return void + */ + public static function shutdownHandler(): void + { + $scope = Context::storage()->scope(); + if (!$scope) { + return; + } + $scope->detach(); + $span = Span::fromContext($scope->context()); + $customParamsStorage = CustomParameterStorage::getInstance(); + $span->setAttributes($customParamsStorage->getAttributes()); + $span->end(); + } } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index c7bdd7e..3f1d302 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -28,6 +28,7 @@ class OpentelemetryConfig extends AbstractBundleConfig public function getExcludedDirs(): array { return [ + 'Monitoring', 'Opentelemetry', 'OpenTelemetry', 'Dependency', From bfcbbcb25ce3085db90cabe92715ee34121a3be4 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 14 Nov 2024 15:22:19 +0200 Subject: [PATCH 15/48] test for generator --- _register.php | 8 +--- composer.json | 3 +- .../ContentCreator/HookContentCreator.php | 4 +- .../Business/Generator/HookGenerator.php | 38 +++++++++++++++++-- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/_register.php b/_register.php index 05e125f..f16bdbe 100644 --- a/_register.php +++ b/_register.php @@ -5,11 +5,11 @@ use OpenTelemetry\SDK\Sdk; use Spryker\Service\Opentelemetry\Instrumentation\SprykerInstrumentationBootstrap; -if (Sdk::isDisabled()) { +if (!class_exists(Sdk::class)) { return; } -if (class_exists(Sdk::class) && Sdk::isInstrumentationDisabled(SprykerInstrumentationBootstrap::NAME) === true) { +if (Sdk::isDisabled()) { return; } @@ -17,8 +17,4 @@ return; } -if (Sdk::isDisabled()) { - return; -} - SprykerInstrumentationBootstrap::register(); diff --git a/composer.json b/composer.json index 823235f..74f2984 100644 --- a/composer.json +++ b/composer.json @@ -6,9 +6,8 @@ "require": { "open-telemetry/api": "^1.0", "open-telemetry/sdk": "^1.0", - "open-telemetry/sdk": "^1.0", "open-telemetry/sem-conv": "^1.0", - "php": ">=8.1", + "php": ">=8.2", "spryker/kernel": "^3.30.0", "spryker/monitoring-extension": "^1.0.0", "spryker/symfony": "^3.0.0" diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index ecfddbb..2fb5711 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -119,13 +119,13 @@ function: \'%s\', $scope->detach(); $span = \\OpenTelemetry\\API\\Trace\\Span::fromContext($scope->context()); - if (isset($exception)) { + if ($exception !== null) { $span->recordException($exception); $span->setAttribute(\'error_message\', isset($exception) ? $exception->getMessage() : \'\'); $span->setAttribute(\'error_code\', isset($exception) ? $exception->getCode() : \'\'); } - $span->setStatus(isset($exception) ? \\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_ERROR : \\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_OK); + $span->setStatus($exception !== null ? \\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_ERROR : \\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_OK); $span->end(); } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php index cb9ea31..750ab53 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php @@ -24,6 +24,11 @@ class HookGenerator implements HookGeneratorInterface */ protected const OUTPUT_FILE_PATH_PLACEHOLDER = '%s/%s-%sHook.php'; + /** + * @var string + */ + protected const OUTPUT_FILE_PATH_PLACEHOLDER_BY_MODULE = '%s/%sHook.php'; + /** * @var string */ @@ -80,12 +85,21 @@ public function generate(): void $collectedClasses = $this->collector->collectClasses(); foreach ($collectedClasses as $class) { + $content = PHP_EOL; $this->ensureDirectoryExists(); - file_put_contents( - $this->getOutputFilepath($class), - $this->contentCreator->createHookContent($class), - ); + if (!file_exists($this->getOutputFilepathByModule($class))) { + $content = 'getOutputFilepathByModule($class), 'a'); + + fwrite($file, $content); + fwrite($file, $this->contentCreator->createHookContent($class)); + fclose($file); +// file_put_contents( +// $this->getOutputFilepath($class), +// $this->contentCreator->createHookContent($class), +// ); } } @@ -115,4 +129,20 @@ protected function getOutputFilepath(array $class): string $class[static::CLASS_NAME_KEY], ); } + + /** + * @param array $class + * + * @return string + */ + protected function getOutputFilepathByModule(array $class): string + { + $namespace = explode('\\', $class[static::NAMESPACE_KEY]); + $moduleNamePattern = $namespace[0] . $namespace[1] . $namespace[2]; + return sprintf( + static::OUTPUT_FILE_PATH_PLACEHOLDER_BY_MODULE, + $this->config->getOutputDir(), + $moduleNamePattern, + ); + } } From 891d527714bdc94b832d755528ab8c08ce0e36e7 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Thu, 14 Nov 2024 16:18:44 +0200 Subject: [PATCH 16/48] Changed hook heneration mechanism to group by module --- .../ContentCreator/HookContentCreator.php | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index 2fb5711..dccda24 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -67,21 +67,6 @@ class: \\%s\\%s::class, function: \'%s\', pre: static function ($instance, array $params, string $class, string $function, ?string $filename, ?int $lineno) { $context = \\OpenTelemetry\\Context\\Context::getCurrent(); - $envVars = %s; - - $extractTraceIdFromEnv = function(array $envVars): array { - foreach ($envVars as $key => $envVar) { - if (defined($envVar)) { - return [$key => constant($envVar)]; - } - } - return []; - }; - - $traceId = $extractTraceIdFromEnv($envVars); - if ($traceId !== []) { - $context = \\OpenTelemetry\\API\\Trace\\Propagation\\TraceContextPropagator::getInstance()->extract($traceId); - } $type = $params[1] ?? \\Symfony\\Component\\HttpKernel\\HttpKernelInterface::MAIN_REQUEST; @@ -133,12 +118,11 @@ function: \'%s\', $class[static::NAMESPACE_KEY], $class[static::CLASS_NAME_KEY], $method, - var_export($envVars, true), $this->buildMethodHookName($class, $method), ); } - return ' Date: Thu, 14 Nov 2024 18:58:45 +0200 Subject: [PATCH 17/48] Removed metrics from setup --- .../SprykerInstrumentationBootstrap.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index dca42ea..9109734 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -67,18 +67,18 @@ public static function register(): void $resource = static::createResource($serviceName); $tracerProvider = static::createTracerProvider($resource); - $meterProvider = static::createMeterProvider($resource); + //$meterProvider = static::createMeterProvider($resource); Sdk::builder() ->setTracerProvider($tracerProvider) - ->setMeterProvider($meterProvider) + //->setMeterProvider($meterProvider) ->setPropagator(TraceContextPropagator::getInstance()) ->buildAndRegisterGlobal(); static::registerRootSpan($serviceName); ShutdownHandler::register($tracerProvider->shutdown(...)); - ShutdownHandler::register($meterProvider->shutdown(...)); + //ShutdownHandler::register($meterProvider->shutdown(...)); } /** @@ -179,16 +179,24 @@ protected static function resolveServiceName(): string /** * @param string $servicedName + * * @return void */ protected static function registerRootSpan(string $servicedName): void { $request = (new RequestProcessor())->getRequest(); + $cli = $request->server->get('argv'); + if ($cli) { + $name = implode(' ', $cli); + } else { + $name = $request->getUri(); + } + $instrumentation = CachedInstrumentation::getCachedInstrumentation(); $parent = Context::getCurrent(); $span = $instrumentation->tracer() - ->spanBuilder($servicedName . ' root') + ->spanBuilder($servicedName . ' ' . $name) ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) From a0f0a6ee1d4155e7514feb64f57880d21788494d Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Fri, 15 Nov 2024 17:59:06 +0200 Subject: [PATCH 18/48] Removed dropped spans log processing --- .../Instrumentation/Span/ImmutableSpan.php | 118 +++++++ .../Instrumentation/Span/Span.php | 333 ++++++++++++++++++ .../Instrumentation/Span/SpanBuilder.php | 1 - .../Zed/Opentelemetry/OpentelemetryConfig.php | 20 -- 4 files changed, 451 insertions(+), 21 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php new file mode 100644 index 0000000..70b5ac0 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php @@ -0,0 +1,118 @@ +span->getKind(); + } + + public function getContext(): \OpenTelemetry\API\Trace\SpanContextInterface + { + return $this->span->getContext(); + } + + public function getParentContext(): \OpenTelemetry\API\Trace\SpanContextInterface + { + return $this->span->getParentContext(); + } + + public function getTraceId(): string + { + return $this->getContext()->getTraceId(); + } + + public function getSpanId(): string + { + return $this->getContext()->getSpanId(); + } + + public function getParentSpanId(): string + { + return $this->getParentContext()->getSpanId(); + } + + public function getStartEpochNanos(): int + { + return $this->span->getStartEpochNanos(); + } + + public function getEndEpochNanos(): int + { + return $this->endEpochNanos; + } + + public function getInstrumentationScope(): InstrumentationScopeInterface + { + return $this->span->getInstrumentationScope(); + } + + public function getResource(): ResourceInfo + { + return $this->span->getResource(); + } + + public function getName(): string + { + return $this->name; + } + + /** @inheritDoc */ + public function getLinks(): array + { + return $this->links; + } + + /** @inheritDoc */ + public function getEvents(): array + { + return $this->events; + } + + public function getAttributes(): AttributesInterface + { + return $this->attributes; + } + + public function getTotalDroppedEvents(): int + { + return max(0, $this->totalRecordedEvents - count($this->events)); + } + + public function getTotalDroppedLinks(): int + { + return max(0, $this->totalRecordedLinks - count($this->links)); + } + + public function getStatus(): StatusDataInterface + { + return $this->status; + } + + public function hasEnded(): bool + { + return $this->hasEnded; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php new file mode 100644 index 0000000..2021ab8 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -0,0 +1,333 @@ + */ + private array $events = []; + private int $totalRecordedEvents = 0; + private StatusDataInterface $status; + private int $endEpochNanos = 0; + private bool $hasEnded = false; + + /** + * @param non-empty-string $name + * @param list $links + */ + private function __construct( + private string $name, + private readonly SpanContextInterface $context, + private readonly InstrumentationScopeInterface $instrumentationScope, + private readonly int $kind, + private readonly SpanContextInterface $parentSpanContext, + private readonly SpanLimits $spanLimits, + private readonly SpanProcessorInterface $spanProcessor, + private readonly ResourceInfo $resource, + private AttributesBuilderInterface $attributesBuilder, + private array $links, + private int $totalRecordedLinks, + private readonly int $startEpochNanos, + ) { + $this->status = StatusData::unset(); + } + + public static function startSpan( + string $name, + SpanContextInterface $context, + InstrumentationScopeInterface $instrumentationScope, + int $kind, + SpanInterface $parentSpan, + ContextInterface $parentContext, + SpanLimits $spanLimits, + SpanProcessorInterface $spanProcessor, + ResourceInfo $resource, + AttributesBuilderInterface $attributesBuilder, + array $links, + int $totalRecordedLinks, + int $startEpochNanos, + ): self { + $span = new self( + $name, + $context, + $instrumentationScope, + $kind, + $parentSpan->getContext(), + $spanLimits, + $spanProcessor, + $resource, + $attributesBuilder, + $links, + $totalRecordedLinks, + $startEpochNanos !== 0 ? $startEpochNanos : Clock::getDefault()->now() + ); + + // Call onStart here to ensure the span is fully initialized. + $spanProcessor->onStart($span, $parentContext); + + return $span; + } + + /** + * Backward compatibility methods + * + * @codeCoverageIgnore + */ + public static function formatStackTrace(Throwable $e, ?array &$seen = null): string + { + BcUtil::triggerMethodDeprecationNotice( + __METHOD__, + 'format', + StackTraceFormatter::class + ); + + return StackTraceFormatter::format($e); + } + + /** @inheritDoc */ + public function getContext(): SpanContextInterface + { + return $this->context; + } + + /** @inheritDoc */ + public function isRecording(): bool + { + return !$this->hasEnded; + } + + /** @inheritDoc */ + public function setAttribute(string $key, $value): self + { + if ($this->hasEnded) { + return $this; + } + + $this->attributesBuilder[$key] = $value; + + return $this; + } + + /** @inheritDoc */ + public function setAttributes(iterable $attributes): self + { + foreach ($attributes as $key => $value) { + $this->attributesBuilder[$key] = $value; + } + + return $this; + } + + public function addLink(SpanContextInterface $context, iterable $attributes = []): self + { + if ($this->hasEnded) { + return $this; + } + if (!$context->isValid()) { + return $this; + } + if (++$this->totalRecordedLinks > $this->spanLimits->getLinkCountLimit()) { + return $this; + } + + $this->links[] = new Link( + $context, + $this->spanLimits + ->getLinkAttributesFactory() + ->builder($attributes) + ->build(), + ); + + return $this; + } + + /** @inheritDoc */ + public function addEvent(string $name, iterable $attributes = [], ?int $timestamp = null): self + { + if ($this->hasEnded) { + return $this; + } + if (++$this->totalRecordedEvents > $this->spanLimits->getEventCountLimit()) { + return $this; + } + + $timestamp ??= Clock::getDefault()->now(); + $eventAttributesBuilder = $this->spanLimits->getEventAttributesFactory()->builder($attributes); + + $this->events[] = new Event($name, $timestamp, $eventAttributesBuilder->build()); + + return $this; + } + + /** @inheritDoc */ + public function recordException(Throwable $exception, iterable $attributes = [], ?int $timestamp = null): self + { + if ($this->hasEnded) { + return $this; + } + if (++$this->totalRecordedEvents > $this->spanLimits->getEventCountLimit()) { + return $this; + } + + $timestamp ??= Clock::getDefault()->now(); + $eventAttributesBuilder = $this->spanLimits->getEventAttributesFactory()->builder([ + 'exception.type' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.stacktrace' => StackTraceFormatter::format($exception), + ]); + + foreach ($attributes as $key => $value) { + $eventAttributesBuilder[$key] = $value; + } + + $this->events[] = new Event('exception', $timestamp, $eventAttributesBuilder->build()); + + return $this; + } + + /** @inheritDoc */ + public function updateName(string $name): self + { + if ($this->hasEnded) { + return $this; + } + $this->name = $name; + + return $this; + } + + /** @inheritDoc */ + public function setStatus(string $code, ?string $description = null): self + { + if ($this->hasEnded) { + return $this; + } + + // An attempt to set value Unset SHOULD be ignored. + if ($code === StatusCode::STATUS_UNSET) { + return $this; + } + + // When span status is set to Ok it SHOULD be considered final and any further attempts to change it SHOULD be ignored. + if ($this->status->getCode() === StatusCode::STATUS_OK) { + return $this; + } + $this->status = StatusData::create($code, $description); + + return $this; + } + + /** @inheritDoc */ + public function end(?int $endEpochNanos = null): void + { + if ($this->hasEnded) { + return; + } + + $this->endEpochNanos = $endEpochNanos ?? Clock::getDefault()->now(); + $this->hasEnded = true; + + $this->spanProcessor->onEnd($this); + } + + /** @inheritDoc */ + public function getName(): string + { + return $this->name; + } + + public function getParentContext(): SpanContextInterface + { + return $this->parentSpanContext; + } + + public function getInstrumentationScope(): InstrumentationScopeInterface + { + return $this->instrumentationScope; + } + + public function hasEnded(): bool + { + return $this->hasEnded; + } + + public function toSpanData(): SpanDataInterface + { + return new ImmutableSpan( + $this, + $this->name, + $this->links, + $this->events, + $this->attributesBuilder->build(), + $this->totalRecordedLinks, + $this->totalRecordedEvents, + $this->status, + $this->endEpochNanos, + $this->hasEnded + ); + } + + /** @inheritDoc */ + public function getDuration(): int + { + return ($this->hasEnded ? $this->endEpochNanos : Clock::getDefault()->now()) - $this->startEpochNanos; + } + + /** @inheritDoc */ + public function getKind(): int + { + return $this->kind; + } + + /** @inheritDoc */ + public function getAttribute(string $key) + { + return $this->attributesBuilder[$key]; + } + + public function getStartEpochNanos(): int + { + return $this->startEpochNanos; + } + + public function getTotalRecordedLinks(): int + { + return $this->totalRecordedLinks; + } + + public function getTotalRecordedEvents(): int + { + return $this->totalRecordedEvents; + } + + public function getResource(): ResourceInfo + { + return $this->resource; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index fda51e3..7a58d50 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -19,7 +19,6 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Trace\Link; use OpenTelemetry\SDK\Trace\SamplingResult; -use OpenTelemetry\SDK\Trace\Span; use OpenTelemetry\SDK\Trace\TracerSharedState; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\ParentSpanAwareSamplerInterface; diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 3f1d302..67c7baa 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -88,26 +88,6 @@ public function getOutputDir(): string return APPLICATION_SOURCE_DIR . '/Generated/OpenTelemetry/Hooks/'; } - /** - * Specification: - * - Returns the list of environment variables that should be used for trace propagation. - * - * @api - * - * @return array - */ - public function getOtelEnvVars(): array - { - return [ - 'backoffice_trace_id' => 'OTEL_BACKOFFICE_TRACE_ID', - 'cli_trace_id' => 'OTEL_CLI_TRACE_ID', - 'merchant_portal_trace_id' => 'OTEL_MERCHANT_PORTAL_TRACE_ID', - 'glue_trace_id' => 'OTEL_GLUE_TRACE_ID', - 'yves_trace_id' => 'OTEL_YVES_TRACE_ID', - 'backend_gateway_trace_id' => 'OTEL_BACKEND_GATEWAY_TRACE_ID', - ]; - } - /** * Specification: * - Set to false if you want to instrument all methods, including private and protected ones. From 61836c3d19a10535e57ce959ee70d54c2ae0a96f Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Fri, 15 Nov 2024 18:32:35 +0200 Subject: [PATCH 19/48] Sampling optimisation --- .../Sampler/CriticalSpanTraceIdRatioSampler.php | 17 ++++++++++++++++- .../Sampler/ParentSpanAwareSamplerInterface.php | 8 ++++++++ .../Instrumentation/Span/SpanBuilder.php | 6 ++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index b7c1b16..8900195 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -8,6 +8,7 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; use InvalidArgumentException; +use OpenTelemetry\API\Trace\SpanContextInterface; use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; @@ -32,6 +33,11 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, ParentSpanAwa */ protected ?SpanInterface $parentSpan = null; + /** + * @var \OpenTelemetry\API\Trace\SpanContextInterface|null + */ + protected ?SpanContextInterface $parentSpanContext = null; + /** * @param float $probability */ @@ -62,7 +68,7 @@ public function shouldSample( array $links, ): SamplingResult { $parentSpan = $this->parentSpan ?: Span::fromContext($parentContext); - $parentSpanContext = $parentSpan->getContext(); + $parentSpanContext = $this->parentSpanContext ?: $parentSpan->getContext(); $traceState = $parentSpanContext->getTraceState(); if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { @@ -95,4 +101,13 @@ public function getDescription(): string return sprintf('%s{%.6F}', 'CriticalSpanTraceIdRatioSampler', $this->probability); } + /** + * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext + * + * @return void + */ + public function addParentSpanContext(SpanContextInterface $spanContext): void + { + $this->parentSpanContext = $spanContext; + } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php index f60064e..5d973c0 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php @@ -7,6 +7,7 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; +use OpenTelemetry\API\Trace\SpanContextInterface; use OpenTelemetry\API\Trace\SpanInterface; interface ParentSpanAwareSamplerInterface @@ -17,4 +18,11 @@ interface ParentSpanAwareSamplerInterface * @return void */ public function addParentSpan(SpanInterface $span): void; + + /** + * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext + * + * @return void + */ + public function addParentSpanContext(SpanContextInterface $spanContext): void; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 7a58d50..0a6a852 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -176,7 +176,7 @@ public function startSpan(): SpanInterface $spanId = $this->tracerSharedState->getIdGenerator()->generateSpanId(); $traceId = $parentSpanContext->isValid() ? $parentSpanContext->getTraceId() : $this->tracerSharedState->getIdGenerator()->generateTraceId(); - $samplingResult = $this->getSamplingResult($parentSpan, $parentContext, $traceId); + $samplingResult = $this->getSamplingResult($parentSpan, $parentContext, $traceId, $parentSpanContext); $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); @@ -212,10 +212,11 @@ public function startSpan(): SpanInterface * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan * @param \OpenTelemetry\Context\ContextInterface $parentContext * @param string $traceId + * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext * * @return \OpenTelemetry\SDK\Trace\SamplingResult */ - protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface $parentContext, string $traceId): SamplingResult + protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface $parentContext, string $traceId, SpanContextInterface $spanContext): SamplingResult { $sampler = $this ->tracerSharedState @@ -223,6 +224,7 @@ protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface if ($sampler instanceof ParentSpanAwareSamplerInterface) { $sampler->addParentSpan($parentSpan); + $sampler->addParentSpanContext($spanContext); } return $sampler From f90e96d9490408879b5bca5d02827c12514049f9 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Fri, 15 Nov 2024 20:06:57 +0200 Subject: [PATCH 20/48] Sampling optimisation --- .../Business/Generator/ContentCreator/HookContentCreator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index dccda24..6fc822e 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -57,7 +57,6 @@ public function __construct(OpentelemetryConfig $config) public function createHookContent(array $class): string { $hooks = []; - $envVars = $this->config->getOtelEnvVars(); foreach ($class[static::METHODS_KEY] as $method) { $hooks[] = sprintf( From 00ce8284f181971607bbd2a7708547666dfd4f3c Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Sun, 17 Nov 2024 16:13:37 +0200 Subject: [PATCH 21/48] Span exporter and coverter update --- .../Instrumentation/Span/Span.php | 95 ++++-- .../Instrumentation/Span/SpanConverter.php | 196 +++++++++++++ .../Instrumentation/Span/SpanExporter.php | 70 +++++ .../PostFilterBatchSpanProcessor.php | 270 +++++++++++++++++- .../SprykerInstrumentationBootstrap.php | 7 +- 5 files changed, 613 insertions(+), 25 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php index 2021ab8..f4443ee 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -10,6 +10,7 @@ use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface; +use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Common\Dev\Compatibility\Util as BcUtil; use OpenTelemetry\SDK\Common\Exception\StackTraceFormatter; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; @@ -26,34 +27,36 @@ use OpenTelemetry\SDK\Trace\StatusDataInterface; use Throwable; -class Span extends OtelSpan implements ReadWriteSpanInterface +class Span extends OtelSpan implements ReadWriteSpanInterface, SpanDataInterface { use LogsMessagesTrait; /** @var list */ - private array $events = []; - private int $totalRecordedEvents = 0; - private StatusDataInterface $status; - private int $endEpochNanos = 0; - private bool $hasEnded = false; + protected array $events = []; + protected int $totalRecordedEvents = 0; + protected StatusDataInterface $status; + protected int $endEpochNanos = 0; + protected bool $hasEnded = false; + + protected ?AttributesInterface $attributes = null; /** * @param non-empty-string $name * @param list $links */ - private function __construct( - private string $name, - private readonly SpanContextInterface $context, - private readonly InstrumentationScopeInterface $instrumentationScope, - private readonly int $kind, - private readonly SpanContextInterface $parentSpanContext, - private readonly SpanLimits $spanLimits, - private readonly SpanProcessorInterface $spanProcessor, - private readonly ResourceInfo $resource, - private AttributesBuilderInterface $attributesBuilder, - private array $links, - private int $totalRecordedLinks, - private readonly int $startEpochNanos, + protected function __construct( + protected string $name, + protected readonly SpanContextInterface $context, + protected readonly InstrumentationScopeInterface $instrumentationScope, + protected readonly int $kind, + protected readonly SpanContextInterface $parentSpanContext, + protected readonly SpanLimits $spanLimits, + protected readonly SpanProcessorInterface $spanProcessor, + protected readonly ResourceInfo $resource, + protected AttributesBuilderInterface $attributesBuilder, + protected array $links, + protected int $totalRecordedLinks, + protected readonly int $startEpochNanos, ) { $this->status = StatusData::unset(); } @@ -330,4 +333,58 @@ public function getResource(): ResourceInfo { return $this->resource; } + + public function getTraceId(): string + { + return $this->context->getTraceId(); + } + + public function getSpanId(): string + { + return $this->context->getSpanId(); + } + + public function getParentSpanId(): string + { + return $this->parentSpanContext->getSpanId(); + } + + public function getStatus(): StatusDataInterface + { + return $this->status; + } + + public function getAttributes(): AttributesInterface + { + if (!$this->attributes) { + $this->attributes = $this->attributesBuilder->build(); + } + + return $this->attributes; + } + + public function getEvents(): array + { + return $this->events; + } + + public function getLinks(): array + { + return $this->links; + } + + public function getEndEpochNanos(): int + { + return $this->endEpochNanos; + } + + public function getTotalDroppedEvents(): int + { + return max(0, $this->totalRecordedEvents - count($this->events)); + } + + public function getTotalDroppedLinks(): int + { + return max(0, $this->totalRecordedLinks - count($this->links)); + } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php new file mode 100644 index 0000000..2b226e9 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php @@ -0,0 +1,196 @@ + $spans + * + * @return \Opentelemetry\Proto\Collector\Trace\V1\ExportTraceServiceRequest + */ + public function convert(iterable $spans): ExportTraceServiceRequest + { + $pExportTraceServiceRequest = new ExportTraceServiceRequest(); + + $resourceSpans = []; + $resourceCache = []; + $scopeSpans = []; + $scopeCache = []; + /** @var SpanDataInterface $span */ + foreach ($spans as $span) { + $resource = $span->getResource(); + $instrumentationScope = $span->getInstrumentationScope(); + + $resourceId = $resourceCache[spl_object_id($resource)] ??= serialize([ + $resource->getSchemaUrl(), + $resource->getAttributes()->toArray(), + $resource->getAttributes()->getDroppedAttributesCount(), + ]); + $instrumentationScopeId = $scopeCache[spl_object_id($instrumentationScope)] ??= serialize([ + $instrumentationScope->getName(), + $instrumentationScope->getVersion(), + $instrumentationScope->getSchemaUrl(), + $instrumentationScope->getAttributes()->toArray(), + $instrumentationScope->getAttributes()->getDroppedAttributesCount(), + ]); + + if (($pResourceSpans = $resourceSpans[$resourceId] ?? null) === null) { + /** @psalm-suppress InvalidArgument */ + $pExportTraceServiceRequest->getResourceSpans()[] + = $resourceSpans[$resourceId] + = $pResourceSpans + = $this->convertResourceSpans($resource); + } + + if (($pScopeSpans = $scopeSpans[$resourceId][$instrumentationScopeId] ?? null) === null) { + /** @psalm-suppress InvalidArgument */ + $pResourceSpans->getScopeSpans()[] + = $scopeSpans[$resourceId][$instrumentationScopeId] + = $pScopeSpans + = $this->convertScopeSpans($instrumentationScope); + } + + /** @psalm-suppress InvalidArgument */ + $pScopeSpans->getSpans()[] = $this->convertSpan($span); + } + + return $pExportTraceServiceRequest; + } + + protected function convertResourceSpans(ResourceInfo $resource): ResourceSpans + { + $pResourceSpans = new ResourceSpans(); + $pResource = new Resource_(); + $this->setAttributes($pResource, $resource->getAttributes()); + $pResourceSpans->setResource($pResource); + $pResourceSpans->setSchemaUrl((string) $resource->getSchemaUrl()); + + return $pResourceSpans; + } + + protected function convertScopeSpans(InstrumentationScopeInterface $instrumentationScope): ScopeSpans + { + $pScopeSpans = new ScopeSpans(); + $pInstrumentationScope = new InstrumentationScope(); + $pInstrumentationScope->setName($instrumentationScope->getName()); + $pInstrumentationScope->setVersion((string) $instrumentationScope->getVersion()); + $this->setAttributes($pInstrumentationScope, $instrumentationScope->getAttributes()); + $pScopeSpans->setScope($pInstrumentationScope); + $pScopeSpans->setSchemaUrl((string) $instrumentationScope->getSchemaUrl()); + + return $pScopeSpans; + } + + /** + * @param Resource_|Span|Event|Link|InstrumentationScope $pElement + */ + protected function setAttributes($pElement, AttributesInterface $attributes): void + { + foreach ($attributes as $key => $value) { + /** @psalm-suppress InvalidArgument */ + $pElement->getAttributes()[] = (new KeyValue()) + ->setKey($key) + ->setValue(AttributesConverter::convertAnyValue($value)); + } + $pElement->setDroppedAttributesCount($attributes->getDroppedAttributesCount()); + } + + protected function convertSpanKind(int $kind): int + { + return match ($kind) { + API\SpanKind::KIND_INTERNAL => SpanKind::SPAN_KIND_INTERNAL, + API\SpanKind::KIND_CLIENT => SpanKind::SPAN_KIND_CLIENT, + API\SpanKind::KIND_SERVER => SpanKind::SPAN_KIND_SERVER, + API\SpanKind::KIND_PRODUCER => SpanKind::SPAN_KIND_PRODUCER, + API\SpanKind::KIND_CONSUMER => SpanKind::SPAN_KIND_CONSUMER, + default => SpanKind::SPAN_KIND_UNSPECIFIED, + }; + } + + protected function convertStatusCode(string $status): int + { + switch ($status) { + case API\StatusCode::STATUS_UNSET: return StatusCode::STATUS_CODE_UNSET; + case API\StatusCode::STATUS_OK: return StatusCode::STATUS_CODE_OK; + case API\StatusCode::STATUS_ERROR: return StatusCode::STATUS_CODE_ERROR; + } + + return StatusCode::STATUS_CODE_UNSET; + } + + protected function convertSpan(SpanDataInterface $span): Span + { + $pSpan = new Span(); + $pSpan->setTraceId($span->getContext()->getTraceIdBinary()); + $pSpan->setSpanId($span->getContext()->getSpanIdBinary()); + $pSpan->setFlags(static::traceFlags($span->getContext())); + $pSpan->setTraceState((string)$span->getContext()->getTraceState()); + if ($span->getParentContext()->isValid()) { + $pSpan->setParentSpanId($span->getParentContext()->getSpanIdBinary()); + } + $pSpan->setName($span->getName()); + $pSpan->setKind($this->convertSpanKind($span->getKind())); + $pSpan->setStartTimeUnixNano($span->getStartEpochNanos()); + $pSpan->setEndTimeUnixNano($span->getEndEpochNanos()); + $this->setAttributes($pSpan, $span->getAttributes()); + + foreach ($span->getEvents() as $event) { + /** @psalm-suppress InvalidArgument */ + $pSpan->getEvents()[] = $pEvent = new Event(); + $pEvent->setTimeUnixNano($event->getEpochNanos()); + $pEvent->setName($event->getName()); + $this->setAttributes($pEvent, $event->getAttributes()); + } + $pSpan->setDroppedEventsCount($span->getTotalDroppedEvents()); + + foreach ($span->getLinks() as $link) { + /** @psalm-suppress InvalidArgument */ + $pSpan->getLinks()[] = $pLink = new Link(); + $pLink->setTraceId($link->getSpanContext()->getTraceIdBinary()); + $pLink->setSpanId($link->getSpanContext()->getSpanIdBinary()); + $pLink->setFlags(static::traceFlags($link->getSpanContext())); + $pLink->setTraceState((string)$link->getSpanContext()->getTraceState()); + $this->setAttributes($pLink, $link->getAttributes()); + } + $pSpan->setDroppedLinksCount($span->getTotalDroppedLinks()); + + $pStatus = new Status(); + $pStatus->setMessage($span->getStatus()->getDescription()); + $pStatus->setCode($this->convertStatusCode($span->getStatus()->getCode())); + $pSpan->setStatus($pStatus); + + return $pSpan; + } + + protected static function traceFlags(SpanContextInterface $spanContext): int + { + $flags = $spanContext->getTraceFlags(); + $flags |= SpanFlags::SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK; + if ($spanContext->isRemote()) { + $flags |= SpanFlags::SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK; + } + + return $flags; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php new file mode 100644 index 0000000..1434f09 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php @@ -0,0 +1,70 @@ +transport + ->send((new SpanConverter())->convert($batch)->serializeToString(), $cancellation) + ->map(function (?string $payload): bool { + if ($payload === null) { + return true; + } + + $serviceResponse = new ExportTraceServiceResponse(); + $serviceResponse->mergeFromString($payload); + + $partialSuccess = $serviceResponse->getPartialSuccess(); + if ($partialSuccess !== null && $partialSuccess->getRejectedSpans()) { + self::logError('Export partial success', [ + 'rejected_spans' => $partialSuccess->getRejectedSpans(), + 'error_message' => $partialSuccess->getErrorMessage(), + ]); + + return false; + } + if ($partialSuccess !== null && $partialSuccess->getErrorMessage()) { + self::logWarning('Export success with warnings/suggestions', ['error_message' => $partialSuccess->getErrorMessage()]); + } + + return true; + }) + ->catch(static function (Throwable $throwable): bool { + self::logError('Export failure', ['exception' => $throwable]); + + return false; + }); + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + return $this->transport->shutdown($cancellation); + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return $this->transport->forceFlush($cancellation); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index cf22b5e..6666519 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -7,13 +7,143 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor; +use InvalidArgumentException; +use OpenTelemetry\API\Behavior\LogsMessagesTrait; +use OpenTelemetry\API\Common\Time\ClockInterface; +use OpenTelemetry\API\Metrics\MeterProviderInterface; +use OpenTelemetry\API\Metrics\ObserverInterface; use OpenTelemetry\API\Trace\StatusCode; +use OpenTelemetry\Context\Context; +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; use OpenTelemetry\SDK\Trace\ReadableSpanInterface; -use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor; +use OpenTelemetry\SDK\Trace\ReadWriteSpanInterface; +use OpenTelemetry\SDK\Trace\SpanExporterInterface; +use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessorBuilder; +use OpenTelemetry\SDK\Trace\SpanProcessorInterface; +use SplQueue; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; -class PostFilterBatchSpanProcessor extends BatchSpanProcessor +class PostFilterBatchSpanProcessor implements SpanProcessorInterface { + use LogsMessagesTrait; + + public const DEFAULT_SCHEDULE_DELAY = 5000; + public const DEFAULT_EXPORT_TIMEOUT = 30000; + public const DEFAULT_MAX_QUEUE_SIZE = 2048; + public const DEFAULT_MAX_EXPORT_BATCH_SIZE = 512; + + protected const ATTRIBUTES_PROCESSOR = ['processor' => 'batching']; + protected const ATTRIBUTES_QUEUED = self::ATTRIBUTES_PROCESSOR + ['state' => 'queued']; + protected const ATTRIBUTES_PENDING = self::ATTRIBUTES_PROCESSOR + ['state' => 'pending']; + protected const ATTRIBUTES_PROCESSED = self::ATTRIBUTES_PROCESSOR + ['state' => 'processed']; + protected const ATTRIBUTES_DROPPED = self::ATTRIBUTES_PROCESSOR + ['state' => 'dropped']; + protected const ATTRIBUTES_FREE = self::ATTRIBUTES_PROCESSOR + ['state' => 'free']; + protected int $maxQueueSize; + protected int $scheduledDelayNanos; + protected int $maxExportBatchSize; + protected ContextInterface $exportContext; + + protected ?int $nextScheduledRun = null; + protected bool $running = false; + protected int $dropped = 0; + protected int $processed = 0; + protected int $batchId = 0; + protected int $queueSize = 0; + /** @var list<\Spryker\Service\Opentelemetry\Instrumentation\Span\Span> */ + protected array $batch = []; + /** @var SplQueue> */ + protected SplQueue $queue; + /** @var SplQueue */ + protected SplQueue $flush; + + protected bool $closed = false; + + public function __construct( + protected readonly SpanExporterInterface $exporter, + protected readonly ClockInterface $clock, + int $maxQueueSize = self::DEFAULT_MAX_QUEUE_SIZE, + int $scheduledDelayMillis = self::DEFAULT_SCHEDULE_DELAY, + int $exportTimeoutMillis = self::DEFAULT_EXPORT_TIMEOUT, + int $maxExportBatchSize = self::DEFAULT_MAX_EXPORT_BATCH_SIZE, + protected readonly bool $autoFlush = true, + ?MeterProviderInterface $meterProvider = null, + ) { + if ($maxQueueSize <= 0) { + throw new InvalidArgumentException(sprintf('Maximum queue size (%d) must be greater than zero', $maxQueueSize)); + } + if ($scheduledDelayMillis <= 0) { + throw new InvalidArgumentException(sprintf('Scheduled delay (%d) must be greater than zero', $scheduledDelayMillis)); + } + if ($exportTimeoutMillis <= 0) { + throw new InvalidArgumentException(sprintf('Export timeout (%d) must be greater than zero', $exportTimeoutMillis)); + } + if ($maxExportBatchSize <= 0) { + throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be greater than zero', $maxExportBatchSize)); + } + if ($maxExportBatchSize > $maxQueueSize) { + throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be less than or equal to maximum queue size (%d)', $maxExportBatchSize, $maxQueueSize)); + } + $this->maxQueueSize = $maxQueueSize; + $this->scheduledDelayNanos = $scheduledDelayMillis * 1_000_000; + $this->maxExportBatchSize = $maxExportBatchSize; + + $this->exportContext = Context::getCurrent(); + $this->queue = new SplQueue(); + $this->flush = new SplQueue(); + + if ($meterProvider === null) { + return; + } + + $meter = $meterProvider->getMeter('io.opentelemetry.sdk'); + $meter + ->createObservableUpDownCounter( + 'otel.trace.span_processor.spans', + '{spans}', + 'The number of sampled spans received by the span processor', + ) + ->observe(function (ObserverInterface $observer): void { + $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); + $pending = $this->queueSize - $queued; + $processed = $this->processed; + $dropped = $this->dropped; + + $observer->observe($queued, self::ATTRIBUTES_QUEUED); + $observer->observe($pending, self::ATTRIBUTES_PENDING); + $observer->observe($processed, self::ATTRIBUTES_PROCESSED); + $observer->observe($dropped, self::ATTRIBUTES_DROPPED); + }); + $meter + ->createObservableUpDownCounter( + 'otel.trace.span_processor.queue.limit', + '{spans}', + 'The queue size limit', + ) + ->observe(function (ObserverInterface $observer): void { + $observer->observe($this->maxQueueSize, self::ATTRIBUTES_PROCESSOR); + }); + $meter + ->createObservableUpDownCounter( + 'otel.trace.span_processor.queue.usage', + '{spans}', + 'The current queue usage', + ) + ->observe(function (ObserverInterface $observer): void { + $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); + $pending = $this->queueSize - $queued; + $free = $this->maxQueueSize - $this->queueSize; + + $observer->observe($queued, self::ATTRIBUTES_QUEUED); + $observer->observe($pending, self::ATTRIBUTES_PENDING); + $observer->observe($free, self::ATTRIBUTES_FREE); + }); + } + + public function onStart(ReadWriteSpanInterface $span, ContextInterface $parentContext): void + { + } + /** * @param \OpenTelemetry\SDK\Trace\ReadableSpanInterface $span * @@ -21,6 +151,14 @@ class PostFilterBatchSpanProcessor extends BatchSpanProcessor */ public function onEnd(ReadableSpanInterface $span): void { + if ($this->closed) { + return; + } + + if (!$span->getContext()->isSampled()) { + return; + } + if ( $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() && $span->toSpanData()->getParentSpanId() @@ -28,6 +166,132 @@ public function onEnd(ReadableSpanInterface $span): void ) { return; } - parent::onEnd($span); + + if ($this->queueSize === $this->maxQueueSize) { + $this->dropped++; + + return; + } + + $this->queueSize++; + $this->batch[] = $span; + $this->nextScheduledRun ??= $this->clock->now() + $this->scheduledDelayNanos; + + if (count($this->batch) === $this->maxExportBatchSize) { + $this->enqueueBatch(); + } + if ($this->autoFlush) { + $this->flush(); + } + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + if ($this->closed) { + return false; + } + + return $this->flush(__FUNCTION__, $cancellation); + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + if ($this->closed) { + return false; + } + + $this->closed = true; + + return $this->flush(__FUNCTION__, $cancellation); + } + + public static function builder(SpanExporterInterface $exporter): BatchSpanProcessorBuilder + { + return new BatchSpanProcessorBuilder($exporter); + } + + protected function flush(?string $flushMethod = null, ?CancellationInterface $cancellation = null): bool + { + if ($flushMethod !== null) { + $flushId = $this->batchId + $this->queue->count() + (int) (bool) $this->batch; + $this->flush->enqueue([$flushId, $flushMethod, $cancellation, !$this->running, Context::getCurrent()]); + } + + if ($this->running) { + return false; + } + + $success = true; + $exception = null; + $this->running = true; + + try { + for (;;) { + while (!$this->flush->isEmpty() && $this->flush->bottom()[0] <= $this->batchId) { + [, $flushMethod, $cancellation, $propagateResult, $context] = $this->flush->dequeue(); + $scope = $context->activate(); + + try { + $result = $this->exporter->$flushMethod($cancellation); + if ($propagateResult) { + $success = $result; + } + } catch (Throwable $e) { + if ($propagateResult) { + $exception = $e; + } else { + self::logError(sprintf('Unhandled %s error', $flushMethod), ['exception' => $e]); + } + } finally { + $scope->detach(); + } + } + + if (!$this->shouldFlush()) { + break; + } + + if ($this->queue->isEmpty()) { + $this->enqueueBatch(); + } + $batchSize = count($this->queue->bottom()); + $this->batchId++; + $scope = $this->exportContext->activate(); + + try { + $this->exporter->export($this->queue->dequeue())->await(); + } catch (Throwable $e) { + self::logError('Unhandled export error', ['exception' => $e]); + } finally { + $this->processed += $batchSize; + $this->queueSize -= $batchSize; + $scope->detach(); + } + } + } finally { + $this->running = false; + } + + if ($exception !== null) { + throw $exception; + } + + return $success; + } + + protected function shouldFlush(): bool + { + return !$this->flush->isEmpty() + || $this->autoFlush && !$this->queue->isEmpty() + || $this->autoFlush && $this->nextScheduledRun !== null && $this->clock->now() > $this->nextScheduledRun; + } + + protected function enqueueBatch(): void + { + assert($this->batch !== []); + + $this->queue->enqueue($this->batch); + $this->batch = []; + $this->nextScheduledRun = null; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 9109734..93bf8c4 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -16,7 +16,6 @@ use OpenTelemetry\Context\Context; use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; use OpenTelemetry\Contrib\Otlp\OtlpUtil; -use OpenTelemetry\Contrib\Otlp\SpanExporter; use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Util\ShutdownHandler; use OpenTelemetry\SDK\Metrics\MeterProviderFactory; @@ -24,6 +23,7 @@ use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; +use OpenTelemetry\SDK\Trace\Sampler\ParentBased; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; @@ -31,6 +31,7 @@ use OpenTelemetry\SemConv\ResourceAttributes; use OpenTelemetry\SemConv\TraceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; +use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanExporter; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; @@ -145,7 +146,7 @@ protected static function createSpanProcessor(): SpanProcessorInterface */ protected static function createSampler(): SamplerInterface { - return new CriticalSpanTraceIdRatioSampler(OpentelemetryConfig::getSamplerProbability()); + return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryConfig::getSamplerProbability())); } /** @@ -200,7 +201,7 @@ protected static function registerRootSpan(string $servicedName): void ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) - ->setAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE, true) + //->setAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE, true) ->startSpan(); Context::storage()->attach($span->storeInContext($parent)); From 1d6f1adf6d35989a575d0602904f5d29f45d7c85 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Sun, 17 Nov 2024 18:01:45 +0200 Subject: [PATCH 22/48] Fixed types --- .../Service/Opentelemetry/Instrumentation/Span/SpanExporter.php | 1 + .../SpanProcessor/PostFilterBatchSpanProcessor.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php index 1434f09..5b535a5 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php @@ -9,6 +9,7 @@ use OpenTelemetry\SDK\Common\Future\CancellationInterface; use OpenTelemetry\SDK\Common\Future\FutureInterface; use OpenTelemetry\SDK\Trace\SpanExporterInterface; +use Throwable; class SpanExporter implements SpanExporterInterface { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 6666519..fb87e50 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -158,7 +158,7 @@ public function onEnd(ReadableSpanInterface $span): void if (!$span->getContext()->isSampled()) { return; } - + if ( $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() && $span->toSpanData()->getParentSpanId() From 4ce318aee87f3565f226d29ab20fc1efdb71ad76 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Sun, 17 Nov 2024 18:04:51 +0200 Subject: [PATCH 23/48] Fixed types --- .../Instrumentation/Span/SpanConverter.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php index 2b226e9..bbdf66b 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php @@ -21,6 +21,8 @@ use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Trace\SpanDataInterface; +use OpenTelemetry\API\Trace\SpanKind as TraceSpanKind; +use OpenTelemetry\API\Trace\StatusCode as TraceStatusCode; class SpanConverter { @@ -119,11 +121,11 @@ protected function setAttributes($pElement, AttributesInterface $attributes): vo protected function convertSpanKind(int $kind): int { return match ($kind) { - API\SpanKind::KIND_INTERNAL => SpanKind::SPAN_KIND_INTERNAL, - API\SpanKind::KIND_CLIENT => SpanKind::SPAN_KIND_CLIENT, - API\SpanKind::KIND_SERVER => SpanKind::SPAN_KIND_SERVER, - API\SpanKind::KIND_PRODUCER => SpanKind::SPAN_KIND_PRODUCER, - API\SpanKind::KIND_CONSUMER => SpanKind::SPAN_KIND_CONSUMER, + TraceSpanKind::KIND_INTERNAL => SpanKind::SPAN_KIND_INTERNAL, + TraceSpanKind::KIND_CLIENT => SpanKind::SPAN_KIND_CLIENT, + TraceSpanKind::KIND_SERVER => SpanKind::SPAN_KIND_SERVER, + TraceSpanKind::KIND_PRODUCER => SpanKind::SPAN_KIND_PRODUCER, + TraceSpanKind::KIND_CONSUMER => SpanKind::SPAN_KIND_CONSUMER, default => SpanKind::SPAN_KIND_UNSPECIFIED, }; } @@ -131,9 +133,9 @@ protected function convertSpanKind(int $kind): int protected function convertStatusCode(string $status): int { switch ($status) { - case API\StatusCode::STATUS_UNSET: return StatusCode::STATUS_CODE_UNSET; - case API\StatusCode::STATUS_OK: return StatusCode::STATUS_CODE_OK; - case API\StatusCode::STATUS_ERROR: return StatusCode::STATUS_CODE_ERROR; + case TraceStatusCode::STATUS_UNSET: return StatusCode::STATUS_CODE_UNSET; + case TraceStatusCode::STATUS_OK: return StatusCode::STATUS_CODE_OK; + case TraceStatusCode::STATUS_ERROR: return StatusCode::STATUS_CODE_ERROR; } return StatusCode::STATUS_CODE_UNSET; From 0e3f99db03e94e1328e11ef29445861ee98b3826 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Sun, 17 Nov 2024 23:00:44 +0200 Subject: [PATCH 24/48] Performance improvementes --- .../CriticalSpanTraceIdRatioSampler.php | 24 ++++++------- .../ParentSpanAwareSamplerInterface.php | 14 ++------ .../Span/AttributesBuilder.php | 2 +- .../Instrumentation/Span/Span.php | 34 +++++++++---------- .../Instrumentation/Span/SpanBuilder.php | 8 ++--- .../Instrumentation/Span/SpanExporter.php | 8 +++-- .../PostFilterBatchSpanProcessor.php | 4 +-- .../SprykerInstrumentationBootstrap.php | 2 ++ 8 files changed, 43 insertions(+), 53 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index 8900195..06c9578 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -10,11 +10,11 @@ use InvalidArgumentException; use OpenTelemetry\API\Trace\SpanContextInterface; use OpenTelemetry\API\Trace\SpanInterface; +use OpenTelemetry\API\Trace\TraceStateInterface; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SamplingResult; -use OpenTelemetry\SDK\Trace\Span; class CriticalSpanTraceIdRatioSampler implements SamplerInterface, ParentSpanAwareSamplerInterface { @@ -29,14 +29,9 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, ParentSpanAwa protected float $probability; /** - * @var \OpenTelemetry\API\Trace\SpanInterface|null + * @var \OpenTelemetry\API\Trace\TraceStateInterface|null */ - protected ?SpanInterface $parentSpan = null; - - /** - * @var \OpenTelemetry\API\Trace\SpanContextInterface|null - */ - protected ?SpanContextInterface $parentSpanContext = null; + protected ?TraceStateInterface $traceState = null; /** * @param float $probability @@ -67,12 +62,8 @@ public function shouldSample( AttributesInterface $attributes, array $links, ): SamplingResult { - $parentSpan = $this->parentSpan ?: Span::fromContext($parentContext); - $parentSpanContext = $this->parentSpanContext ?: $parentSpan->getContext(); - $traceState = $parentSpanContext->getTraceState(); - if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { - return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $traceState); + return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $this->traceState); } $traceIdLimit = (1 << 60) - 1; @@ -80,7 +71,7 @@ public function shouldSample( $traceIdCondition = $lowerOrderBytes < round($this->probability * $traceIdLimit); $decision = $traceIdCondition ? SamplingResult::RECORD_AND_SAMPLE : SamplingResult::DROP; - return new SamplingResult($decision, [], $traceState); + return new SamplingResult($decision, [], $this->traceState); } /** @@ -93,6 +84,11 @@ public function addParentSpan(SpanInterface $span): void $this->parentSpan = $span; } + public function addTraceState(TraceStateInterface $traceState): void + { + + } + /** * @return string */ diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php index 5d973c0..139a0fc 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php @@ -7,22 +7,14 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; -use OpenTelemetry\API\Trace\SpanContextInterface; -use OpenTelemetry\API\Trace\SpanInterface; +use OpenTelemetry\API\Trace\TraceStateInterface; interface ParentSpanAwareSamplerInterface { /** - * @param \OpenTelemetry\API\Trace\SpanInterface $span + * @param \OpenTelemetry\API\Trace\TraceStateInterface $span * * @return void */ - public function addParentSpan(SpanInterface $span): void; - - /** - * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext - * - * @return void - */ - public function addParentSpanContext(SpanContextInterface $spanContext): void; + public function addTraceState(TraceStateInterface $span): void; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php index f123f2f..675c90c 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php @@ -88,7 +88,7 @@ public function offsetSet($offset, $value): void return; } - if (!in_array($offset, $this->getSafeAttributes()) && !$this->attributeValidator->validate($value)) { + if (!in_array($offset, $this->getSafeAttributes(), true) && !$this->attributeValidator->validate($value)) { $this->droppedAttributesCount++; return; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php index f4443ee..52090b5 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -96,22 +96,22 @@ public static function startSpan( return $span; } - - /** - * Backward compatibility methods - * - * @codeCoverageIgnore - */ - public static function formatStackTrace(Throwable $e, ?array &$seen = null): string - { - BcUtil::triggerMethodDeprecationNotice( - __METHOD__, - 'format', - StackTraceFormatter::class - ); - - return StackTraceFormatter::format($e); - } +// +// /** +// * Backward compatibility methods +// * +// * @codeCoverageIgnore +// */ +// public static function formatStackTrace(Throwable $e, ?array &$seen = null): string +// { +// BcUtil::triggerMethodDeprecationNotice( +// __METHOD__, +// 'format', +// StackTraceFormatter::class +// ); +// +// return StackTraceFormatter::format($e); +// } /** @inheritDoc */ public function getContext(): SpanContextInterface @@ -292,7 +292,7 @@ public function toSpanData(): SpanDataInterface $this->totalRecordedEvents, $this->status, $this->endEpochNanos, - $this->hasEnded + $this->hasEnded, ); } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 0a6a852..e25b87a 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -176,7 +176,7 @@ public function startSpan(): SpanInterface $spanId = $this->tracerSharedState->getIdGenerator()->generateSpanId(); $traceId = $parentSpanContext->isValid() ? $parentSpanContext->getTraceId() : $this->tracerSharedState->getIdGenerator()->generateTraceId(); - $samplingResult = $this->getSamplingResult($parentSpan, $parentContext, $traceId, $parentSpanContext); + $samplingResult = $this->getSamplingResult($parentSpan, $parentContext, $traceId); $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); @@ -212,19 +212,17 @@ public function startSpan(): SpanInterface * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan * @param \OpenTelemetry\Context\ContextInterface $parentContext * @param string $traceId - * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext * * @return \OpenTelemetry\SDK\Trace\SamplingResult */ - protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface $parentContext, string $traceId, SpanContextInterface $spanContext): SamplingResult + protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface $parentContext, string $traceId): SamplingResult { $sampler = $this ->tracerSharedState ->getSampler(); if ($sampler instanceof ParentSpanAwareSamplerInterface) { - $sampler->addParentSpan($parentSpan); - $sampler->addParentSpanContext($spanContext); + $sampler->addTraceState($parentSpan->getContext()->getTraceState()); } return $sampler diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php index 5b535a5..2626c32 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanExporter.php @@ -3,7 +3,6 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Span; use OpenTelemetry\API\Behavior\LogsMessagesTrait; -use OpenTelemetry\Contrib\Otlp\SpanConverter; use Opentelemetry\Proto\Collector\Trace\V1\ExportTraceServiceResponse; use OpenTelemetry\SDK\Common\Export\TransportInterface; use OpenTelemetry\SDK\Common\Future\CancellationInterface; @@ -15,7 +14,10 @@ class SpanExporter implements SpanExporterInterface { use LogsMessagesTrait; - public function __construct(protected TransportInterface $transport) + public function __construct( + protected TransportInterface $transport, + protected SpanConverter $spanConverter, + ) { } @@ -28,7 +30,7 @@ public function __construct(protected TransportInterface $transport) public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface { return $this->transport - ->send((new SpanConverter())->convert($batch)->serializeToString(), $cancellation) + ->send($this->spanConverter->convert($batch)->serializeToString(), $cancellation) ->map(function (?string $payload): bool { if ($payload === null) { return true; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index fb87e50..0af2d9d 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -161,8 +161,8 @@ public function onEnd(ReadableSpanInterface $span): void if ( $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() - && $span->toSpanData()->getParentSpanId() - && $span->toSpanData()->getStatus()->getCode() === StatusCode::STATUS_OK + && $span->getParentSpanId() + && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 93bf8c4..db4d754 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -31,6 +31,7 @@ use OpenTelemetry\SemConv\ResourceAttributes; use OpenTelemetry\SemConv\TraceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; +use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanConverter; use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanExporter; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; @@ -127,6 +128,7 @@ protected static function createSpanExporter(): SpanExporterInterface { return new SpanExporter( (new GrpcTransportFactory())->create(OpentelemetryConfig::getExporterEndpoint() . OtlpUtil::method(Signals::TRACE)), + new SpanConverter(), ); } From 3c7b069c4be3e8f1a20f53c7a9fbc085f57b23ea Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Sun, 17 Nov 2024 23:24:11 +0200 Subject: [PATCH 25/48] Updated sampling --- .../Sampler/CriticalSpanTraceIdRatioSampler.php | 7 ++++++- .../SpanProcessor/PostFilterBatchSpanProcessor.php | 2 +- .../Instrumentation/SprykerInstrumentationBootstrap.php | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index 06c9578..5a6d386 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -84,9 +84,14 @@ public function addParentSpan(SpanInterface $span): void $this->parentSpan = $span; } + /** + * @param \OpenTelemetry\API\Trace\TraceStateInterface $traceState + * + * @return void + */ public function addTraceState(TraceStateInterface $traceState): void { - + $this->traceState = $traceState; } /** diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 0af2d9d..89166bc 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -66,7 +66,7 @@ public function __construct( int $scheduledDelayMillis = self::DEFAULT_SCHEDULE_DELAY, int $exportTimeoutMillis = self::DEFAULT_EXPORT_TIMEOUT, int $maxExportBatchSize = self::DEFAULT_MAX_EXPORT_BATCH_SIZE, - protected readonly bool $autoFlush = true, + protected readonly bool $autoFlush = false, ?MeterProviderInterface $meterProvider = null, ) { if ($maxQueueSize <= 0) { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index db4d754..55089f6 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -144,7 +144,7 @@ protected static function createSpanProcessor(): SpanProcessorInterface } /** - * @return \OpenTelemetry\API\Trace\SamplerInterface + * @return \OpenTelemetry\SDK\Trace\SamplerInterface */ protected static function createSampler(): SamplerInterface { From ba073bbc1e9a3801d849513440ca8e46039f42c8 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Mon, 18 Nov 2024 07:47:39 +0200 Subject: [PATCH 26/48] Removed heavy hitting methods from generation --- .../SpanProcessor/PostFilterBatchSpanProcessor.php | 1 + src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 89166bc..66930d0 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -164,6 +164,7 @@ public function onEnd(ReadableSpanInterface $span): void && $span->getParentSpanId() && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { + $this->dropped++; return; } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 67c7baa..07500e5 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -50,6 +50,8 @@ public function getExcludedDirs(): array 'Acl', 'Twig', 'WebProfiler', + 'Translator', + 'Money', 'templates', 'config', 'tests', From 66f8d6371b1c82f05f5d2b6188ff82eea1a3c048 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Mon, 18 Nov 2024 07:54:13 +0200 Subject: [PATCH 27/48] Removed heavy hitting methods from generation --- .../Instrumentation/Span/SpanBuilder.php | 1 - .../Instrumentation/Span/SpanContext.php | 110 ++++++++++++++++++ .../Zed/Opentelemetry/OpentelemetryConfig.php | 3 + 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index e25b87a..d5504c8 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -8,7 +8,6 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Span; use OpenTelemetry\API\Trace\SpanBuilderInterface; -use OpenTelemetry\API\Trace\SpanContext; use OpenTelemetry\API\Trace\SpanContextInterface; use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\SpanKind; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php new file mode 100644 index 0000000..04c22bd --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php @@ -0,0 +1,110 @@ +isSampled = ($traceFlags & TraceFlags::SAMPLED) === TraceFlags::SAMPLED; + } + + public function getTraceId(): string + { + return $this->traceId; + } + + public function getTraceIdBinary(): string + { + return hex2bin($this->traceId); + } + + public function getSpanId(): string + { + return $this->spanId; + } + + public function getSpanIdBinary(): string + { + return hex2bin($this->spanId); + } + + public function getTraceState(): ?TraceStateInterface + { + return $this->traceState; + } + + public function isSampled(): bool + { + return $this->isSampled; + } + + public function isValid(): bool + { + return $this->isValid; + } + + public function isRemote(): bool + { + return $this->isRemote; + } + + public function getTraceFlags(): int + { + return $this->traceFlags; + } + + /** @inheritDoc */ + public static function createFromRemoteParent(string $traceId, string $spanId, int $traceFlags = TraceFlags::DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface + { + return new static( + $traceId, + $spanId, + $traceFlags, + true, + $traceState, + ); + } + + /** @inheritDoc */ + public static function create(string $traceId, string $spanId, int $traceFlags = TraceFlags::DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface + { + return new static( + $traceId, + $spanId, + $traceFlags, + false, + $traceState, + ); + } + + /** @inheritDoc */ + public static function getInvalid(): SpanContextInterface + { + if (null === static::$invalidContext) { + static::$invalidContext = self::create(SpanContextValidator::INVALID_TRACE, SpanContextValidator::INVALID_SPAN, 0); + } + + return static::$invalidContext; + } +} diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 07500e5..e96df47 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -52,6 +52,9 @@ public function getExcludedDirs(): array 'WebProfiler', 'Translator', 'Money', + 'Locale', + 'Store', + 'Log', 'templates', 'config', 'tests', From 599c9568661b4d840769ad3a3991558f4892d007 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Mon, 18 Nov 2024 14:30:57 +0200 Subject: [PATCH 28/48] Reduced modules amount --- .../Zed/Opentelemetry/OpentelemetryConfig.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index e96df47..d814b4f 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -33,6 +33,9 @@ public function getExcludedDirs(): array 'OpenTelemetry', 'Dependency', 'Acl', + 'Form', + 'Gui', + 'GracefulRunner', 'AclEntity', 'Container', 'Transfer', @@ -53,8 +56,46 @@ public function getExcludedDirs(): array 'Translator', 'Money', 'Locale', + 'Navigation', + 'Touch', + 'Collector', + 'NavigationGui', 'Store', 'Log', + 'Profiler', + 'Propel', + 'PropelOrm', + 'PropelQueryBuilder', + 'RabbitMq', + 'Redis', + 'Session', + 'SessionFile', + 'SessionRedis', + 'SessionUserValidation', + 'Testify', + 'Validation', + 'Development', + 'ErrorHandler', + 'Form', + 'Glossary', + 'GuiTable', + 'ModuleFinder', + 'Monitoring', + 'Search', + 'SearchElasticsearch', + 'SearchElasticsearchGui', + 'Silex', + 'SearchHttp', + 'Storage', + 'StorageRedis', + 'StorageDatabase', + 'StoreContext', + 'Symfony', + 'Security', + 'Http', + 'SecuritySystemUser', + 'SecurityOauthUser', + 'UserLocale', 'templates', 'config', 'tests', From c2b48dbdf0d5b582892a29f6bca90234d851d9ec Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Mon, 18 Nov 2024 14:46:51 +0200 Subject: [PATCH 29/48] Reduced modules amount --- src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index d814b4f..ccd2054 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -92,10 +92,20 @@ public function getExcludedDirs(): array 'StoreContext', 'Symfony', 'Security', + 'SecurityGui', 'Http', 'SecuritySystemUser', 'SecurityOauthUser', 'UserLocale', + 'User', + 'AclMerchantAgent', + 'Merchant', + 'MerchantStock', + 'MerchantProfile', + 'MerchantGui', + 'MerchantUser', + 'MerchantCategory', + 'ZedUi', 'templates', 'config', 'tests', From 6273eb176e94f0678694e8a632f524fe5a8c9fa4 Mon Sep 17 00:00:00 2001 From: Serhii Chepela Date: Tue, 19 Nov 2024 15:47:54 +0200 Subject: [PATCH 30/48] Updated list of modules and fixedcritical functionality --- .../CriticalSpanTraceIdRatioSampler.php | 28 ++++++------------- .../ParentSpanAwareSamplerInterface.php | 7 +++++ .../Instrumentation/Span/Attributes.php | 4 +-- .../Span/AttributesBuilder.php | 2 ++ .../Instrumentation/Span/Span.php | 22 ++------------- .../Instrumentation/Span/SpanBuilder.php | 1 + .../PostFilterBatchSpanProcessor.php | 4 ++- .../SprykerInstrumentationBootstrap.php | 20 ++++++++++++- .../Zed/Opentelemetry/OpentelemetryConfig.php | 4 +++ 9 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index 5a6d386..a5dddd9 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -8,7 +8,6 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; use InvalidArgumentException; -use OpenTelemetry\API\Trace\SpanContextInterface; use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\TraceStateInterface; use OpenTelemetry\Context\ContextInterface; @@ -33,6 +32,8 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, ParentSpanAwa */ protected ?TraceStateInterface $traceState = null; + protected ?SpanInterface $parentSpan = null; + /** * @param float $probability */ @@ -62,7 +63,7 @@ public function shouldSample( AttributesInterface $attributes, array $links, ): SamplingResult { - if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { + if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE) && $this->parentSpan->getContext()->isValid()) { return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $this->traceState); } @@ -75,23 +76,22 @@ public function shouldSample( } /** - * @param \OpenTelemetry\API\Trace\SpanInterface $span + * @param \OpenTelemetry\API\Trace\TraceStateInterface $traceState * * @return void */ - public function addParentSpan(SpanInterface $span): void + public function addTraceState(TraceStateInterface $traceState): void { - $this->parentSpan = $span; + $this->traceState = $traceState; } /** - * @param \OpenTelemetry\API\Trace\TraceStateInterface $traceState - * + * @param \OpenTelemetry\API\Trace\SpanInterface $span * @return void */ - public function addTraceState(TraceStateInterface $traceState): void + public function addParentSpan(SpanInterface $span): void { - $this->traceState = $traceState; + $this->parentSpan = $span; } /** @@ -101,14 +101,4 @@ public function getDescription(): string { return sprintf('%s{%.6F}', 'CriticalSpanTraceIdRatioSampler', $this->probability); } - - /** - * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext - * - * @return void - */ - public function addParentSpanContext(SpanContextInterface $spanContext): void - { - $this->parentSpanContext = $spanContext; - } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php index 139a0fc..6e351bb 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php @@ -7,6 +7,7 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; +use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\TraceStateInterface; interface ParentSpanAwareSamplerInterface @@ -17,4 +18,10 @@ interface ParentSpanAwareSamplerInterface * @return void */ public function addTraceState(TraceStateInterface $span): void; + + /** + * @param \OpenTelemetry\API\Trace\SpanInterface $span + * @return void + */ + public function addParentSpan(SpanInterface $span): void; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php index 6f15325..0a00bdf 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php @@ -13,8 +13,8 @@ class Attributes implements AttributesInterface, IteratorAggregate * @internal */ public function __construct( - private readonly array $attributes, - private readonly int $droppedAttributesCount, + protected readonly array $attributes, + protected readonly int $droppedAttributesCount, ) { } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php index 675c90c..7f53892 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php @@ -12,6 +12,7 @@ use OpenTelemetry\SDK\Common\Attribute\AttributeValidator; use OpenTelemetry\SDK\Common\Attribute\AttributeValidatorInterface; use OpenTelemetry\SemConv\TraceAttributes; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; class AttributesBuilder implements AttributesBuilderInterface { @@ -131,6 +132,7 @@ protected function getSafeAttributes(): array 'search.query', 'root.url', TraceAttributes::URL_DOMAIN, + CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE, ]; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php index 52090b5..e90db5e 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -11,14 +11,11 @@ use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; -use OpenTelemetry\SDK\Common\Dev\Compatibility\Util as BcUtil; use OpenTelemetry\SDK\Common\Exception\StackTraceFormatter; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Trace\Event; -use OpenTelemetry\SDK\Trace\EventInterface; use OpenTelemetry\SDK\Trace\Link; -use OpenTelemetry\SDK\Trace\LinkInterface; use OpenTelemetry\SDK\Trace\ReadWriteSpanInterface; use OpenTelemetry\SDK\Trace\SpanDataInterface; use OpenTelemetry\SDK\Trace\SpanLimits; @@ -37,6 +34,7 @@ class Span extends OtelSpan implements ReadWriteSpanInterface, SpanDataInterface protected StatusDataInterface $status; protected int $endEpochNanos = 0; protected bool $hasEnded = false; + protected bool $isCritical = false; protected ?AttributesInterface $attributes = null; @@ -96,22 +94,6 @@ public static function startSpan( return $span; } -// -// /** -// * Backward compatibility methods -// * -// * @codeCoverageIgnore -// */ -// public static function formatStackTrace(Throwable $e, ?array &$seen = null): string -// { -// BcUtil::triggerMethodDeprecationNotice( -// __METHOD__, -// 'format', -// StackTraceFormatter::class -// ); -// -// return StackTraceFormatter::format($e); -// } /** @inheritDoc */ public function getContext(): SpanContextInterface @@ -311,7 +293,7 @@ public function getKind(): int /** @inheritDoc */ public function getAttribute(string $key) { - return $this->attributesBuilder[$key]; + return $this->attributesBuilder[$key] ?? null; } public function getStartEpochNanos(): int diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index d5504c8..b5ac21f 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -222,6 +222,7 @@ protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface if ($sampler instanceof ParentSpanAwareSamplerInterface) { $sampler->addTraceState($parentSpan->getContext()->getTraceState()); + $sampler->addParentSpan($parentSpan); } return $sampler diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 66930d0..22c753e 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -22,6 +22,7 @@ use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessorBuilder; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use SplQueue; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; class PostFilterBatchSpanProcessor implements SpanProcessorInterface @@ -160,7 +161,8 @@ public function onEnd(ReadableSpanInterface $span): void } if ( - $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() + $span->getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) !== true + && $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() && $span->getParentSpanId() && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 55089f6..38ff8eb 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -39,6 +39,7 @@ use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; +use Symfony\Component\HttpFoundation\Request; /** * @method \Spryker\Service\Opentelemetry\OpentelemetryServiceFactory getFactory() @@ -50,6 +51,11 @@ class SprykerInstrumentationBootstrap */ public const NAME = 'spryker'; + /** + * @var string + */ + protected const SPAN_NAME_PLACEHOLDER = '%s %s'; + /** * @var string */ @@ -193,7 +199,7 @@ protected static function registerRootSpan(string $servicedName): void if ($cli) { $name = implode(' ', $cli); } else { - $name = $request->getUri(); + $name = static::formatSpanName($request); } $instrumentation = CachedInstrumentation::getCachedInstrumentation(); @@ -211,6 +217,18 @@ protected static function registerRootSpan(string $servicedName): void register_shutdown_function([static::class, 'shutdownHandler']); } + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * + * @return string + */ + protected static function formatSpanName(Request $request): string + { + $relativeUriWithoutQueryString = str_replace('?' . $request->getQueryString(), '', $request->getUri()); + + return sprintf(static::SPAN_NAME_PLACEHOLDER, $request->getMethod(), $relativeUriWithoutQueryString); + } + /** * @return void */ diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index ccd2054..bbb24b7 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -93,6 +93,10 @@ public function getExcludedDirs(): array 'Symfony', 'Security', 'SecurityGui', + 'SecurityBlockerBackofficeGui', + 'SecurityBlockerMerchantPortalGui', + 'AgentSecurityMerchantPortalGui', + 'SecurityMerchantPortalGui', 'Http', 'SecuritySystemUser', 'SecurityOauthUser', From b3038d1b28d8197880e33c02608af16288546fe7 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Wed, 27 Nov 2024 17:54:23 +0200 Subject: [PATCH 31/48] Refactoring --- .../CriticalSpanTraceIdRatioSampler.php | 31 +- ...hp => TraceStateAwareSamplerInterface.php} | 8 +- .../Instrumentation/Span/Attributes.php | 46 ++- .../Span/AttributesBuilder.php | 7 + .../Instrumentation/Span/ImmutableSpan.php | 81 ++++- .../Instrumentation/Span/Span.php | 203 +++++++++-- .../Instrumentation/Span/SpanBuilder.php | 7 +- .../Instrumentation/Span/SpanContext.php | 67 +++- .../Instrumentation/Span/SpanConverter.php | 5 + .../Instrumentation/Span/SpanExporter.php | 23 +- .../PostFilterBatchSpanProcessor.php | 318 +++++++++++++----- .../Instrumentation/Tracer/Tracer.php | 2 +- .../Instrumentation/Tracer/TracerProvider.php | 7 +- 13 files changed, 648 insertions(+), 157 deletions(-) rename src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/{ParentSpanAwareSamplerInterface.php => TraceStateAwareSamplerInterface.php} (72%) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index a5dddd9..069cfe3 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -8,14 +8,13 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; use InvalidArgumentException; -use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\TraceStateInterface; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SamplingResult; -class CriticalSpanTraceIdRatioSampler implements SamplerInterface, ParentSpanAwareSamplerInterface +class CriticalSpanTraceIdRatioSampler implements SamplerInterface, TraceStateAwareSamplerInterface { /** * @var string @@ -32,17 +31,12 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, ParentSpanAwa */ protected ?TraceStateInterface $traceState = null; - protected ?SpanInterface $parentSpan = null; - /** * @param float $probability */ public function __construct(float $probability) { - if ($probability < 0.0 || $probability > 1.0) { - throw new InvalidArgumentException('probability should be be between 0.0 and 1.0.'); - } - $this->probability = $probability; + $this->setProbability($probability); } /** @@ -63,7 +57,7 @@ public function shouldSample( AttributesInterface $attributes, array $links, ): SamplingResult { - if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE) && $this->parentSpan->getContext()->isValid()) { + if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $this->traceState); } @@ -86,19 +80,24 @@ public function addTraceState(TraceStateInterface $traceState): void } /** - * @param \OpenTelemetry\API\Trace\SpanInterface $span - * @return void + * @return string */ - public function addParentSpan(SpanInterface $span): void + public function getDescription(): string { - $this->parentSpan = $span; + return sprintf('%s{%.6F}', 'CriticalSpanTraceIdRatioSampler', $this->probability); } /** - * @return string + * @param float $probability + * + * @return void */ - public function getDescription(): string + protected function setProbability(float $probability): void { - return sprintf('%s{%.6F}', 'CriticalSpanTraceIdRatioSampler', $this->probability); + if ($probability < 0.0 || $probability > 1.0) { + throw new InvalidArgumentException('probability should be be between 0.0 and 1.0.'); + } + + $this->probability = $probability; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php similarity index 72% rename from src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php rename to src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php index 6e351bb..96c1b52 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php @@ -10,7 +10,7 @@ use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\TraceStateInterface; -interface ParentSpanAwareSamplerInterface +interface TraceStateAwareSamplerInterface { /** * @param \OpenTelemetry\API\Trace\TraceStateInterface $span @@ -18,10 +18,4 @@ interface ParentSpanAwareSamplerInterface * @return void */ public function addTraceState(TraceStateInterface $span): void; - - /** - * @param \OpenTelemetry\API\Trace\SpanInterface $span - * @return void - */ - public function addParentSpan(SpanInterface $span): void; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php index 0a00bdf..5616a9d 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php @@ -1,5 +1,10 @@ builder($attributes)->build(); } + /** + * @param int|null $attributeCountLimit + * @param int|null $attributeValueLengthLimit + * + * @return \OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface + */ public static function factory(?int $attributeCountLimit = null, ?int $attributeValueLengthLimit = null): AttributesFactoryInterface { return new AttributesFactory($attributeCountLimit, $attributeValueLengthLimit); } + /** + * @param string $name + * + * @return bool + */ public function has(string $name): bool { return array_key_exists($name, $this->attributes); } + /** + * @param string $name + * + * @return mixed|null + */ public function get(string $name) { return $this->attributes[$name] ?? null; } - /** @psalm-mutation-free */ + /** + * @return int + */ public function count(): int { return count($this->attributes); } + /** + * @return \Traversable + */ public function getIterator(): Traversable { foreach ($this->attributes as $key => $value) { @@ -51,11 +83,17 @@ public function getIterator(): Traversable } } + /** + * @return array + */ public function toArray(): array { return $this->attributes; } + /** + * @return int + */ public function getDroppedAttributesCount(): int { return $this->droppedAttributesCount; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php index 7f53892..6b26409 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php @@ -16,6 +16,13 @@ class AttributesBuilder implements AttributesBuilderInterface { + /** + * @param array $attributes + * @param int|null $attributeCountLimit + * @param int|null $attributeValueLengthLimit + * @param int $droppedAttributesCount + * @param \OpenTelemetry\SDK\Common\Attribute\AttributeValidatorInterface $attributeValidator + */ public function __construct( protected array $attributes, protected ?int $attributeCountLimit, diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php index 70b5ac0..166890f 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/ImmutableSpan.php @@ -1,5 +1,10 @@ span->getKind(); } + /** + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public function getContext(): \OpenTelemetry\API\Trace\SpanContextInterface { return $this->span->getContext(); } + /** + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public function getParentContext(): \OpenTelemetry\API\Trace\SpanContextInterface { return $this->span->getParentContext(); } + /** + * @return string + */ public function getTraceId(): string { return $this->getContext()->getTraceId(); } + /** + * @return string + */ public function getSpanId(): string { return $this->getContext()->getSpanId(); } + /** + * @return string + */ public function getParentSpanId(): string { return $this->getParentContext()->getSpanId(); } + /** + * @return int + */ public function getStartEpochNanos(): int { return $this->span->getStartEpochNanos(); } + /** + * @return int + */ public function getEndEpochNanos(): int { return $this->endEpochNanos; } + /** + * @return \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface + */ public function getInstrumentationScope(): InstrumentationScopeInterface { return $this->span->getInstrumentationScope(); } + /** + * @return \OpenTelemetry\SDK\Resource\ResourceInfo + */ public function getResource(): ResourceInfo { return $this->span->getResource(); } + /** + * @return string + */ public function getName(): string { return $this->name; } - /** @inheritDoc */ + /** + * @return array|\OpenTelemetry\SDK\Trace\LinkInterface[] + */ public function getLinks(): array { return $this->links; } - /** @inheritDoc */ + /** + * @return array|\OpenTelemetry\SDK\Trace\EventInterface[] + */ public function getEvents(): array { return $this->events; } + /** + * @return \OpenTelemetry\SDK\Common\Attribute\AttributesInterface + */ public function getAttributes(): AttributesInterface { return $this->attributes; } + /** + * @return int + */ public function getTotalDroppedEvents(): int { return max(0, $this->totalRecordedEvents - count($this->events)); } + /** + * @return int + */ public function getTotalDroppedLinks(): int { return max(0, $this->totalRecordedLinks - count($this->links)); } + /** + * @return \OpenTelemetry\SDK\Trace\StatusDataInterface + */ public function getStatus(): StatusDataInterface { return $this->status; } + /** + * @return bool + */ public function hasEnded(): bool { return $this->hasEnded; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php index e90db5e..22bccc2 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -1,5 +1,10 @@ */ + /** + * @var list<\OpenTelemetry\SDK\Trace\EventInterface> + */ protected array $events = []; + + /** + * @var int + */ protected int $totalRecordedEvents = 0; + + /** + * @var \OpenTelemetry\SDK\Trace\StatusDataInterface + */ protected StatusDataInterface $status; + + /** + * @var int + */ protected int $endEpochNanos = 0; + + /** + * @var bool + */ protected bool $hasEnded = false; + + /** + * @var bool + */ protected bool $isCritical = false; + /** + * @var \OpenTelemetry\SDK\Common\Attribute\AttributesInterface|null + */ protected ?AttributesInterface $attributes = null; /** - * @param non-empty-string $name - * @param list $links + * @param string $name + * @param list<\OpenTelemetry\SDK\Trace\LinkInterface> $links */ protected function __construct( protected string $name, - protected readonly SpanContextInterface $context, - protected readonly InstrumentationScopeInterface $instrumentationScope, - protected readonly int $kind, - protected readonly SpanContextInterface $parentSpanContext, - protected readonly SpanLimits $spanLimits, - protected readonly SpanProcessorInterface $spanProcessor, - protected readonly ResourceInfo $resource, + protected SpanContextInterface $context, + protected InstrumentationScopeInterface $instrumentationScope, + protected int $kind, + protected SpanContextInterface $parentSpanContext, + protected SpanLimits $spanLimits, + protected SpanProcessorInterface $spanProcessor, + protected ResourceInfo $resource, protected AttributesBuilderInterface $attributesBuilder, protected array $links, protected int $totalRecordedLinks, - protected readonly int $startEpochNanos, + protected int $startEpochNanos, ) { $this->status = StatusData::unset(); } + /** + * @param string $name + * @param \OpenTelemetry\API\Trace\SpanContextInterface $context + * @param \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface $instrumentationScope + * @param int $kind + * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan + * @param \OpenTelemetry\Context\ContextInterface $parentContext + * @param \OpenTelemetry\SDK\Trace\SpanLimits $spanLimits + * @param \OpenTelemetry\SDK\Trace\SpanProcessorInterface $spanProcessor + * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource + * @param \OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface $attributesBuilder + * @param array $links + * @param int $totalRecordedLinks + * @param int $startEpochNanos + * + * @return $this + */ public static function startSpan( string $name, SpanContextInterface $context, @@ -95,19 +142,28 @@ public static function startSpan( return $span; } - /** @inheritDoc */ + /** + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public function getContext(): SpanContextInterface { return $this->context; } - /** @inheritDoc */ + /** + * @return bool + */ public function isRecording(): bool { return !$this->hasEnded; } - /** @inheritDoc */ + /** + * @param string $key + * @param $value + * + * @return $this + */ public function setAttribute(string $key, $value): self { if ($this->hasEnded) { @@ -119,7 +175,11 @@ public function setAttribute(string $key, $value): self return $this; } - /** @inheritDoc */ + /** + * @param iterable $attributes + * + * @return $this + */ public function setAttributes(iterable $attributes): self { foreach ($attributes as $key => $value) { @@ -129,6 +189,12 @@ public function setAttributes(iterable $attributes): self return $this; } + /** + * @param \OpenTelemetry\API\Trace\SpanContextInterface $context + * @param iterable $attributes + * + * @return $this + */ public function addLink(SpanContextInterface $context, iterable $attributes = []): self { if ($this->hasEnded) { @@ -152,7 +218,13 @@ public function addLink(SpanContextInterface $context, iterable $attributes = [] return $this; } - /** @inheritDoc */ + /** + * @param string $name + * @param iterable $attributes + * @param int|null $timestamp + * + * @return $this + */ public function addEvent(string $name, iterable $attributes = [], ?int $timestamp = null): self { if ($this->hasEnded) { @@ -170,7 +242,13 @@ public function addEvent(string $name, iterable $attributes = [], ?int $timestam return $this; } - /** @inheritDoc */ + /** + * @param \Throwable $exception + * @param iterable $attributes + * @param int|null $timestamp + * + * @return $this + */ public function recordException(Throwable $exception, iterable $attributes = [], ?int $timestamp = null): self { if ($this->hasEnded) { @@ -196,7 +274,11 @@ public function recordException(Throwable $exception, iterable $attributes = [], return $this; } - /** @inheritDoc */ + /** + * @param string $name + * + * @return $this + */ public function updateName(string $name): self { if ($this->hasEnded) { @@ -207,7 +289,12 @@ public function updateName(string $name): self return $this; } - /** @inheritDoc */ + /** + * @param string $code + * @param string|null $description + * + * @return $this + */ public function setStatus(string $code, ?string $description = null): self { if ($this->hasEnded) { @@ -228,7 +315,11 @@ public function setStatus(string $code, ?string $description = null): self return $this; } - /** @inheritDoc */ + /** + * @param int|null $endEpochNanos + * + * @return void + */ public function end(?int $endEpochNanos = null): void { if ($this->hasEnded) { @@ -241,27 +332,41 @@ public function end(?int $endEpochNanos = null): void $this->spanProcessor->onEnd($this); } - /** @inheritDoc */ + /** + * @return string + */ public function getName(): string { return $this->name; } + /** + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public function getParentContext(): SpanContextInterface { return $this->parentSpanContext; } + /** + * @return \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface + */ public function getInstrumentationScope(): InstrumentationScopeInterface { return $this->instrumentationScope; } + /** + * @return bool + */ public function hasEnded(): bool { return $this->hasEnded; } + /** + * @return \OpenTelemetry\SDK\Trace\SpanDataInterface + */ public function toSpanData(): SpanDataInterface { return new ImmutableSpan( @@ -278,64 +383,99 @@ public function toSpanData(): SpanDataInterface ); } - /** @inheritDoc */ + /** + * @return int + */ public function getDuration(): int { return ($this->hasEnded ? $this->endEpochNanos : Clock::getDefault()->now()) - $this->startEpochNanos; } - /** @inheritDoc */ + /** + * @return int + */ public function getKind(): int { return $this->kind; } - /** @inheritDoc */ + /** + * @param string $key + * + * @return mixed|null + */ public function getAttribute(string $key) { return $this->attributesBuilder[$key] ?? null; } + /** + * @return int + */ public function getStartEpochNanos(): int { return $this->startEpochNanos; } + /** + * @return int + */ public function getTotalRecordedLinks(): int { return $this->totalRecordedLinks; } + /** + * @return int + */ public function getTotalRecordedEvents(): int { return $this->totalRecordedEvents; } + /** + * @return \OpenTelemetry\SDK\Resource\ResourceInfo + */ public function getResource(): ResourceInfo { return $this->resource; } + /** + * @return string + */ public function getTraceId(): string { return $this->context->getTraceId(); } + /** + * @return string + */ public function getSpanId(): string { return $this->context->getSpanId(); } + /** + * @return string + */ public function getParentSpanId(): string { return $this->parentSpanContext->getSpanId(); } + /** + * @return \OpenTelemetry\SDK\Trace\StatusDataInterface + */ public function getStatus(): StatusDataInterface { return $this->status; } + /** + * @return \OpenTelemetry\SDK\Common\Attribute\AttributesInterface + */ public function getAttributes(): AttributesInterface { if (!$this->attributes) { @@ -345,26 +485,41 @@ public function getAttributes(): AttributesInterface return $this->attributes; } + /** + * @return \OpenTelemetry\SDK\Trace\EventInterface[] + */ public function getEvents(): array { return $this->events; } + /** + * @return \OpenTelemetry\SDK\Trace\LinkInterface[] + */ public function getLinks(): array { return $this->links; } + /** + * @return int + */ public function getEndEpochNanos(): int { return $this->endEpochNanos; } + /** + * @return int + */ public function getTotalDroppedEvents(): int { return max(0, $this->totalRecordedEvents - count($this->events)); } + /** + * @return int + */ public function getTotalDroppedLinks(): int { return max(0, $this->totalRecordedLinks - count($this->links)); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index b5ac21f..22ed3af 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -19,7 +19,7 @@ use OpenTelemetry\SDK\Trace\Link; use OpenTelemetry\SDK\Trace\SamplingResult; use OpenTelemetry\SDK\Trace\TracerSharedState; -use Spryker\Service\Opentelemetry\Instrumentation\Sampler\ParentSpanAwareSamplerInterface; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\TraceStateAwareSamplerInterface; class SpanBuilder implements SpanBuilderInterface { @@ -220,9 +220,8 @@ protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface ->tracerSharedState ->getSampler(); - if ($sampler instanceof ParentSpanAwareSamplerInterface) { - $sampler->addTraceState($parentSpan->getContext()->getTraceState()); - $sampler->addParentSpan($parentSpan); + if ($sampler instanceof TraceStateAwareSamplerInterface) { + $sampler->addTraceState($parentSpan->getContext()->getTraceState());; } return $sampler diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php index 04c22bd..2cd3a2a 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php @@ -1,5 +1,10 @@ isSampled = ($traceFlags & TraceFlags::SAMPLED) === TraceFlags::SAMPLED; } + /** + * @return string + */ public function getTraceId(): string { return $this->traceId; } + /** + * @return string + */ public function getTraceIdBinary(): string { return hex2bin($this->traceId); } + /** + * @return string + */ public function getSpanId(): string { return $this->spanId; } + /** + * @return string + */ public function getSpanIdBinary(): string { return hex2bin($this->spanId); } + /** + * @return \OpenTelemetry\API\Trace\TraceStateInterface|null + */ public function getTraceState(): ?TraceStateInterface { return $this->traceState; } + /** + * @return bool + */ public function isSampled(): bool { return $this->isSampled; } + /** + * @return bool + */ public function isValid(): bool { return $this->isValid; } + /** + * @return bool + */ public function isRemote(): bool { return $this->isRemote; } + /** + * @return int + */ public function getTraceFlags(): int { return $this->traceFlags; } - /** @inheritDoc */ + /** + * @param string $traceId + * @param string $spanId + * @param int $traceFlags + * @param \OpenTelemetry\API\Trace\TraceStateInterface|null $traceState + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public static function createFromRemoteParent(string $traceId, string $spanId, int $traceFlags = TraceFlags::DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface { return new static( @@ -86,7 +137,13 @@ public static function createFromRemoteParent(string $traceId, string $spanId, i ); } - /** @inheritDoc */ + /** + * @param string $traceId + * @param string $spanId + * @param int $traceFlags + * @param \OpenTelemetry\API\Trace\TraceStateInterface|null $traceState + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public static function create(string $traceId, string $spanId, int $traceFlags = TraceFlags::DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface { return new static( @@ -98,7 +155,9 @@ public static function create(string $traceId, string $spanId, int $traceFlags = ); } - /** @inheritDoc */ + /** + * @return \OpenTelemetry\API\Trace\SpanContextInterface + */ public static function getInvalid(): SpanContextInterface { if (null === static::$invalidContext) { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php index bbdf66b..56e2b9a 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php @@ -1,5 +1,10 @@ transport->shutdown($cancellation); } + /** + * @param \OpenTelemetry\SDK\Common\Future\CancellationInterface|null $cancellation + * + * @return bool + */ public function forceFlush(?CancellationInterface $cancellation = null): bool { return $this->transport->forceFlush($cancellation); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 22c753e..6228fb8 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -24,125 +24,165 @@ use SplQueue; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; +use Throwable; class PostFilterBatchSpanProcessor implements SpanProcessorInterface { use LogsMessagesTrait; + /** + * @var int + */ public const DEFAULT_SCHEDULE_DELAY = 5000; - public const DEFAULT_EXPORT_TIMEOUT = 30000; + + /** + * @var int + */ public const DEFAULT_MAX_QUEUE_SIZE = 2048; + + /** + * @var int + */ public const DEFAULT_MAX_EXPORT_BATCH_SIZE = 512; + /** + * @var array + */ protected const ATTRIBUTES_PROCESSOR = ['processor' => 'batching']; - protected const ATTRIBUTES_QUEUED = self::ATTRIBUTES_PROCESSOR + ['state' => 'queued']; - protected const ATTRIBUTES_PENDING = self::ATTRIBUTES_PROCESSOR + ['state' => 'pending']; + + /** + * @var array + */ + protected const ATTRIBUTES_QUEUED = self::ATTRIBUTES_PROCESSOR + ['state' => 'queued']; + + /** + * @var array + */ + protected const ATTRIBUTES_PENDING = self::ATTRIBUTES_PROCESSOR + ['state' => 'pending']; + + /** + * @var array + */ protected const ATTRIBUTES_PROCESSED = self::ATTRIBUTES_PROCESSOR + ['state' => 'processed']; - protected const ATTRIBUTES_DROPPED = self::ATTRIBUTES_PROCESSOR + ['state' => 'dropped']; - protected const ATTRIBUTES_FREE = self::ATTRIBUTES_PROCESSOR + ['state' => 'free']; + + /** + * @var array + */ + protected const ATTRIBUTES_DROPPED = self::ATTRIBUTES_PROCESSOR + ['state' => 'dropped']; + + /** + * @var array + */ + protected const ATTRIBUTES_FREE = self::ATTRIBUTES_PROCESSOR + ['state' => 'free']; + + /** + * @var int + */ protected int $maxQueueSize; + + /** + * @var int + */ protected int $scheduledDelayNanos; + + /** + * @var int + */ protected int $maxExportBatchSize; + + /** + * @var \OpenTelemetry\Context\ContextInterface + */ protected ContextInterface $exportContext; + /** + * @var int|null + */ protected ?int $nextScheduledRun = null; + + /** + * @var bool + */ protected bool $running = false; + + /** + * @var int + */ protected int $dropped = 0; + + /** + * @var int + */ protected int $processed = 0; + + /** + * @var int + */ protected int $batchId = 0; + + /** + * @var int + */ protected int $queueSize = 0; - /** @var list<\Spryker\Service\Opentelemetry\Instrumentation\Span\Span> */ + + /** + * @var list<\Spryker\Service\Opentelemetry\Instrumentation\Span\Span> + */ protected array $batch = []; - /** @var SplQueue> */ + + /** + * @var \SplQueue> + */ protected SplQueue $queue; - /** @var SplQueue */ + + /** + * @var \SplQueue + */ protected SplQueue $flush; + /** + * @var bool + */ protected bool $closed = false; + /** + * @param \OpenTelemetry\SDK\Trace\SpanExporterInterface $exporter + * @param \OpenTelemetry\API\Common\Time\ClockInterface $clock + * @param int $maxQueueSize + * @param int $scheduledDelayMillis + * @param int $maxExportBatchSize + * @param bool $autoFlush + * @param \OpenTelemetry\API\Metrics\MeterProviderInterface|null $meterProvider + */ public function __construct( - protected readonly SpanExporterInterface $exporter, - protected readonly ClockInterface $clock, + protected SpanExporterInterface $exporter, + protected ClockInterface $clock, int $maxQueueSize = self::DEFAULT_MAX_QUEUE_SIZE, int $scheduledDelayMillis = self::DEFAULT_SCHEDULE_DELAY, - int $exportTimeoutMillis = self::DEFAULT_EXPORT_TIMEOUT, int $maxExportBatchSize = self::DEFAULT_MAX_EXPORT_BATCH_SIZE, - protected readonly bool $autoFlush = false, + protected bool $autoFlush = false, ?MeterProviderInterface $meterProvider = null, ) { - if ($maxQueueSize <= 0) { - throw new InvalidArgumentException(sprintf('Maximum queue size (%d) must be greater than zero', $maxQueueSize)); - } - if ($scheduledDelayMillis <= 0) { - throw new InvalidArgumentException(sprintf('Scheduled delay (%d) must be greater than zero', $scheduledDelayMillis)); - } - if ($exportTimeoutMillis <= 0) { - throw new InvalidArgumentException(sprintf('Export timeout (%d) must be greater than zero', $exportTimeoutMillis)); - } - if ($maxExportBatchSize <= 0) { - throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be greater than zero', $maxExportBatchSize)); - } - if ($maxExportBatchSize > $maxQueueSize) { - throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be less than or equal to maximum queue size (%d)', $maxExportBatchSize, $maxQueueSize)); - } - $this->maxQueueSize = $maxQueueSize; - $this->scheduledDelayNanos = $scheduledDelayMillis * 1_000_000; - $this->maxExportBatchSize = $maxExportBatchSize; + $this->setMaxQueueSize($maxQueueSize); + $this->setScheduledDelayTime($scheduledDelayMillis); + $this->setMaxExportBatchSize($maxExportBatchSize, $maxQueueSize); $this->exportContext = Context::getCurrent(); $this->queue = new SplQueue(); $this->flush = new SplQueue(); - if ($meterProvider === null) { - return; - } - - $meter = $meterProvider->getMeter('io.opentelemetry.sdk'); - $meter - ->createObservableUpDownCounter( - 'otel.trace.span_processor.spans', - '{spans}', - 'The number of sampled spans received by the span processor', - ) - ->observe(function (ObserverInterface $observer): void { - $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); - $pending = $this->queueSize - $queued; - $processed = $this->processed; - $dropped = $this->dropped; - - $observer->observe($queued, self::ATTRIBUTES_QUEUED); - $observer->observe($pending, self::ATTRIBUTES_PENDING); - $observer->observe($processed, self::ATTRIBUTES_PROCESSED); - $observer->observe($dropped, self::ATTRIBUTES_DROPPED); - }); - $meter - ->createObservableUpDownCounter( - 'otel.trace.span_processor.queue.limit', - '{spans}', - 'The queue size limit', - ) - ->observe(function (ObserverInterface $observer): void { - $observer->observe($this->maxQueueSize, self::ATTRIBUTES_PROCESSOR); - }); - $meter - ->createObservableUpDownCounter( - 'otel.trace.span_processor.queue.usage', - '{spans}', - 'The current queue usage', - ) - ->observe(function (ObserverInterface $observer): void { - $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); - $pending = $this->queueSize - $queued; - $free = $this->maxQueueSize - $this->queueSize; - - $observer->observe($queued, self::ATTRIBUTES_QUEUED); - $observer->observe($pending, self::ATTRIBUTES_PENDING); - $observer->observe($free, self::ATTRIBUTES_FREE); - }); + $this->initMetrics($meterProvider); } + /** + * @param \OpenTelemetry\SDK\Trace\ReadWriteSpanInterface $span + * @param \OpenTelemetry\Context\ContextInterface $parentContext + * + * @return void + */ public function onStart(ReadWriteSpanInterface $span, ContextInterface $parentContext): void { + //Nothing is required here, but method is a part of an API } /** @@ -188,6 +228,12 @@ public function onEnd(ReadableSpanInterface $span): void } } + /** + * @param \OpenTelemetry\SDK\Common\Future\CancellationInterface|null $cancellation + * @throws \Exception + * + * @return bool + */ public function forceFlush(?CancellationInterface $cancellation = null): bool { if ($this->closed) { @@ -197,6 +243,12 @@ public function forceFlush(?CancellationInterface $cancellation = null): bool return $this->flush(__FUNCTION__, $cancellation); } + /** + * @param \OpenTelemetry\SDK\Common\Future\CancellationInterface|null $cancellation + * @throws \Exception + * + * @return bool + */ public function shutdown(?CancellationInterface $cancellation = null): bool { if ($this->closed) { @@ -208,15 +260,121 @@ public function shutdown(?CancellationInterface $cancellation = null): bool return $this->flush(__FUNCTION__, $cancellation); } + /** + * @param \OpenTelemetry\SDK\Trace\SpanExporterInterface $exporter + * + * @return \OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessorBuilder + */ public static function builder(SpanExporterInterface $exporter): BatchSpanProcessorBuilder { return new BatchSpanProcessorBuilder($exporter); } + /** + * @param int $maxQueueSize + * + * @return void + */ + protected function setMaxQueueSize(int $maxQueueSize): void + { + if ($maxQueueSize <= 0) { + throw new InvalidArgumentException(sprintf('Maximum queue size (%d) must be greater than zero', $maxQueueSize)); + } + + $this->maxQueueSize = $maxQueueSize; + } + + /** + * @param int $scheduledDelayMillis + * + * @return void + */ + protected function setScheduledDelayTime(int $scheduledDelayMillis): void + { + if ($scheduledDelayMillis <= 0) { + throw new InvalidArgumentException(sprintf('Scheduled delay (%d) must be greater than zero', $scheduledDelayMillis)); + } + + $this->scheduledDelayNanos = $scheduledDelayMillis * 1_000_000; + } + + protected function setMaxExportBatchSize(int $maxExportBatchSize, int $maxQueueSize): void + { + if ($maxExportBatchSize <= 0) { + throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be greater than zero', $maxExportBatchSize)); + } + if ($maxExportBatchSize > $maxQueueSize) { + throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be less than or equal to maximum queue size (%d)', $maxExportBatchSize, $maxQueueSize)); + } + + $this->maxExportBatchSize = $maxExportBatchSize; + } + /** + * @param \OpenTelemetry\API\Metrics\MeterProviderInterface|null $meterProvider + * + * @return void + */ + protected function initMetrics(?MeterProviderInterface $meterProvider = null): void + { + if ($meterProvider === null) { + return; + } + + $meter = $meterProvider->getMeter('io.spryker.metrics'); + $meter + ->createObservableUpDownCounter( + 'otel.trace.span_processor.spans', + '{spans}', + 'The number of sampled spans received by the span processor', + ) + ->observe(function (ObserverInterface $observer): void { + $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); + $pending = $this->queueSize - $queued; + $processed = $this->processed; + $dropped = $this->dropped; + + $observer->observe($queued, static::ATTRIBUTES_QUEUED); + $observer->observe($pending, static::ATTRIBUTES_PENDING); + $observer->observe($processed, static::ATTRIBUTES_PROCESSED); + $observer->observe($dropped, static::ATTRIBUTES_DROPPED); + }); + $meter + ->createObservableUpDownCounter( + 'otel.trace.span_processor.queue.limit', + '{spans}', + 'The queue size limit', + ) + ->observe(function (ObserverInterface $observer): void { + $observer->observe($this->maxQueueSize, static::ATTRIBUTES_PROCESSOR); + }); + $meter + ->createObservableUpDownCounter( + 'otel.trace.span_processor.queue.usage', + '{spans}', + 'The current queue usage', + ) + ->observe(function (ObserverInterface $observer): void { + $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); + $pending = $this->queueSize - $queued; + $free = $this->maxQueueSize - $this->queueSize; + + $observer->observe($queued, static::ATTRIBUTES_QUEUED); + $observer->observe($pending, static::ATTRIBUTES_PENDING); + $observer->observe($free, static::ATTRIBUTES_FREE); + }); + } + + /** + * @param string|null $flushMethod + * @param \OpenTelemetry\SDK\Common\Future\CancellationInterface|null $cancellation + * @throws \Throwable + * + * @return bool + */ protected function flush(?string $flushMethod = null, ?CancellationInterface $cancellation = null): bool { if ($flushMethod !== null) { - $flushId = $this->batchId + $this->queue->count() + (int) (bool) $this->batch; + $flushId = $this->batchId + $this->queue->count() + (int)(bool)$this->batch; $this->flush->enqueue([$flushId, $flushMethod, $cancellation, !$this->running, Context::getCurrent()]); } @@ -282,6 +440,9 @@ protected function flush(?string $flushMethod = null, ?CancellationInterface $ca return $success; } + /** + * @return bool + */ protected function shouldFlush(): bool { return !$this->flush->isEmpty() @@ -289,6 +450,9 @@ protected function shouldFlush(): bool || $this->autoFlush && $this->nextScheduledRun !== null && $this->clock->now() > $this->nextScheduledRun; } + /** + * @return void + */ protected function enqueueBatch(): void { assert($this->batch !== []); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php index 141f751..4d340ca 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/Tracer.php @@ -26,7 +26,7 @@ class Tracer implements TracerInterface protected const FALLBACK_SPAN_NAME = 'empty'; /** - * @var \OpenTelemetry\SDK\Common\InstrumentationScope\Config|\OpenTelemetry\SDK\Trace\TracerConfig + * @var \OpenTelemetry\SDK\Common\InstrumentationScope\Config */ protected Config $config; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php index 430b01f..84af050 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Tracer/TracerProvider.php @@ -31,7 +31,7 @@ class TracerProvider implements TracerProviderInterface protected TracerSharedState $tracerSharedState; /** - * @var \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface|\OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory + * @var \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface */ protected InstrumentationScopeFactoryInterface $instrumentationScopeFactory; @@ -43,15 +43,12 @@ class TracerProvider implements TracerProviderInterface /** * @var \Spryker\Service\Opentelemetry\Instrumentation\Tracer\Tracer|null */ - protected static $tracer = null; + protected static ?Tracer $tracer = null; /** * @param \OpenTelemetry\SDK\Trace\SpanProcessorInterface $spanProcessor * @param \OpenTelemetry\SDK\Trace\SamplerInterface $sampler * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource - * @param \OpenTelemetry\SDK\Trace\SpanLimits|null $spanLimits - * @param \OpenTelemetry\SDK\Trace\IdGeneratorInterface|null $idGenerator - * @param \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface|null $instrumentationScopeFactory * @param \OpenTelemetry\SDK\Common\InstrumentationScope\Configurator|null $configurator */ public function __construct( From ab22a15af83eb2837c0fa14b6e27e7a0befb6fca Mon Sep 17 00:00:00 2001 From: gechetspr Date: Thu, 28 Nov 2024 13:36:50 +0200 Subject: [PATCH 32/48] Added root span name processing --- .../SprykerInstrumentationBootstrap.php | 5 ++ .../Opentelemetry/OpentelemetryService.php | 10 ++++ .../OpentelemetryServiceFactory.php | 10 ++++ .../OpentelemetryServiceInterface.php | 12 +++++ ...OpentelemetryMonitoringExtensionPlugin.php | 4 +- .../Storage/CustomParameterStorage.php | 3 ++ .../Storage/RootSpanNameStorage.php | 46 +++++++++++++++++++ .../Storage/RootSpanNameStorageInterface.php | 18 ++++++++ 8 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorage.php create mode 100644 src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorageInterface.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 38ff8eb..3683d5c 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -36,6 +36,7 @@ use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; +use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorage; use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; use Spryker\Zed\Opentelemetry\OpentelemetryConfig; @@ -240,6 +241,10 @@ public static function shutdownHandler(): void } $scope->detach(); $span = Span::fromContext($scope->context()); + $name = RootSpanNameStorage::getInstance()->getName(); + if ($name) { + $span->updateName($name); + } $customParamsStorage = CustomParameterStorage::getInstance(); $span->setAttributes($customParamsStorage->getAttributes()); $span->end(); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryService.php b/src/Spryker/Service/Opentelemetry/OpentelemetryService.php index 2f37d75..1571cc7 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryService.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryService.php @@ -28,4 +28,14 @@ public function setCustomParameter(string $key, $value): void { $this->getFactory()->createCustomParameterStorage()->setAttribute($key, $value); } + + /** + * @param string $name + * + * @return void + */ + public function setRootSpanName(string $name): void + { + $this->getFactory()->createRootSpanNameStorage()->setName($name); + } } diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php index 8b53a63..97e1c41 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php @@ -10,6 +10,8 @@ use Spryker\Service\Kernel\AbstractServiceFactory; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorageInterface; +use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorage; +use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorageInterface; class OpentelemetryServiceFactory extends AbstractServiceFactory { @@ -20,4 +22,12 @@ public function createCustomParameterStorage(): CustomParameterStorageInterface { return CustomParameterStorage::getInstance(); } + + /** + * @return \Spryker\Service\Opentelemetry\Storage\RootSpanNameStorageInterface + */ + public function createRootSpanNameStorage(): RootSpanNameStorageInterface + { + return RootSpanNameStorage::getInstance(); + } } diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php index 3d34cee..4b55fb7 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php @@ -22,4 +22,16 @@ interface OpentelemetryServiceInterface * @return void */ public function setCustomParameter(string $key, $value): void; + + /** + * Specification: + * - Sets root span name that will be shown in the list of all transactions + * + * @api + * + * @param string $name + * + * @return void + */ + public function setRootSpanName(string $name): void; } diff --git a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php index a528aa8..6aebcf1 100644 --- a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php +++ b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php @@ -48,7 +48,8 @@ public function setApplicationName(?string $application = null, ?string $store = /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Sets name for the root span. If no name provided, default name will be generated. + * - This will affect only root span as it will not update the current possible span name. * * @api * @@ -58,6 +59,7 @@ public function setApplicationName(?string $application = null, ?string $store = */ public function setTransactionName(string $name): void { + $this->getService()->setRootSpanName($name); } /** diff --git a/src/Spryker/Service/Opentelemetry/Storage/CustomParameterStorage.php b/src/Spryker/Service/Opentelemetry/Storage/CustomParameterStorage.php index 8062165..2a93d13 100644 --- a/src/Spryker/Service/Opentelemetry/Storage/CustomParameterStorage.php +++ b/src/Spryker/Service/Opentelemetry/Storage/CustomParameterStorage.php @@ -4,6 +4,9 @@ class CustomParameterStorage implements CustomParameterStorageInterface { + /** + * @var \Spryker\Service\Opentelemetry\Storage\CustomParameterStorage|null + */ private static ?CustomParameterStorage $instance = null; /** diff --git a/src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorage.php b/src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorage.php new file mode 100644 index 0000000..2a613cb --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorage.php @@ -0,0 +1,46 @@ +name = $name; + } + + /** + * @return ?string + */ + public function getName(): string + { + return $this->name; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorageInterface.php b/src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorageInterface.php new file mode 100644 index 0000000..c5886eb --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Storage/RootSpanNameStorageInterface.php @@ -0,0 +1,18 @@ + Date: Sat, 30 Nov 2024 11:33:06 +0200 Subject: [PATCH 33/48] Refactored config and plugin to support monitoring service actions --- .../Resource/CompositeResourceDetector.php | 36 +++ .../Instrumentation/Resource/ResourceInfo.php | 95 ++++++++ .../Resource/ResourceInfoFactory.php | 57 +++++ .../CriticalSpanTraceIdRatioSampler.php | 6 +- .../Sampler/TraceSampleResult.php | 79 +++++++ .../Instrumentation/Span/Attributes.php | 17 +- .../Span/WritableAttributesInterface.php | 16 ++ .../PostFilterBatchSpanProcessor.php | 4 +- .../SprykerInstrumentationBootstrap.php | 72 +++--- .../OpentelemetryInstrumentationConfig.php | 221 ++++++++++++++++++ .../Opentelemetry/OpentelemetryService.php | 11 + .../OpentelemetryServiceFactory.php | 9 + ...OpentelemetryMonitoringExtensionPlugin.php | 26 ++- .../Storage/ResourceNameStorage.php | 43 ++++ .../Storage/ResourceNameStorageInterface.php | 13 ++ .../Storage/RootSpanNameStorage.php | 2 +- .../SpanFilter/SamplerSpanFilter.php | 28 --- .../SpanFilter/SpanFilterInterface.php | 21 -- .../Zed/Opentelemetry/OpentelemetryConfig.php | 99 -------- 19 files changed, 659 insertions(+), 196 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfo.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfoFactory.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/WritableAttributesInterface.php create mode 100644 src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php create mode 100644 src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php create mode 100644 src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php delete mode 100644 src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php delete mode 100644 src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SpanFilterInterface.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php new file mode 100644 index 0000000..7d6849f --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php @@ -0,0 +1,36 @@ + $resourceDetectors + */ + public function __construct(protected array $resourceDetectors) + { + } + + /** + * @return \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo + */ + public function getResource(): ResourceInfo + { + $resource = ResourceInfoFactory::emptyResource(); + foreach ($this->resourceDetectors as $resourceDetector) { + $detectorResource = $resourceDetector->getResource(); + $resourceToMerge = new ResourceInfo($detectorResource->getAttributes(), $detectorResource->getSchemaUrl()); + $resource = $resource->mergeSprykerResource($resourceToMerge); + } + + return $resource; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfo.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfo.php new file mode 100644 index 0000000..fcf3cf7 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfo.php @@ -0,0 +1,95 @@ +attributes instanceof WritableAttributesInterface) { + $this->attributes->set(ResourceAttributes::SERVICE_NAME, $name); + } + } + + /** + * @return \OpenTelemetry\SDK\Common\Attribute\AttributesInterface + */ + public function getAttributes(): AttributesInterface + { + return $this->attributes; + } + + /** + * @param \OpenTelemetry\SDK\Common\Attribute\AttributesInterface $attributes + * @param string|null $schemaUrl + * + * @return \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo + */ + public static function createSprykerResource(AttributesInterface $attributes, ?string $schemaUrl = null): ResourceInfo + { + return new ResourceInfo($attributes, $schemaUrl); + } + + /** + * @return string|null + */ + public function getSchemaUrl(): ?string + { + return $this->schemaUrl; + } + + /** + * @param \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo $updating + * + * @return \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo + */ + public function mergeSprykerResource(ResourceInfo $updating): ResourceInfo + { + $schemaUrl = static::mergeSchemaUrl($this->getSchemaUrl(), $updating->getSchemaUrl()); + $attributes = Attributes::factory()->builder()->merge($this->getAttributes(), $updating->getAttributes()); + + return ResourceInfo::createSprykerResource($attributes, $schemaUrl); + } + + /** + * @param string|null $old + * @param string|null $updating + * + * @return string|null + */ + protected static function mergeSchemaUrl(?string $old, ?string $updating): ?string + { + if (empty($old)) { + return $updating; + } + if (empty($updating)) { + return $old; + } + if ($old === $updating) { + return $old; + } + + return null; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfoFactory.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfoFactory.php new file mode 100644 index 0000000..859b42a --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/ResourceInfoFactory.php @@ -0,0 +1,57 @@ +getResource(); + } + + /** + * @return \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo + */ + public static function emptyResource(): ResourceInfo + { + if (null === self::$emptyResource) { + self::$emptyResource = ResourceInfo::createSprykerResource(Attributes::create([])); + } + + return self::$emptyResource; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index 069cfe3..f1da8a3 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SamplingResult; +use Spryker\Service\Opentelemetry\OpentelemetryInstrumentationConfig; class CriticalSpanTraceIdRatioSampler implements SamplerInterface, TraceStateAwareSamplerInterface { @@ -57,13 +58,14 @@ public function shouldSample( AttributesInterface $attributes, array $links, ): SamplingResult { + $probability = $this->probability; if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { - return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $this->traceState); + $probability = OpentelemetryInstrumentationConfig::getSamplerProbabilityForCriticalSpans(); } $traceIdLimit = (1 << 60) - 1; $lowerOrderBytes = hexdec(substr($traceId, strlen($traceId) - 15, 15)); - $traceIdCondition = $lowerOrderBytes < round($this->probability * $traceIdLimit); + $traceIdCondition = $lowerOrderBytes < round($probability * $traceIdLimit); $decision = $traceIdCondition ? SamplingResult::RECORD_AND_SAMPLE : SamplingResult::DROP; return new SamplingResult($decision, [], $this->traceState); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php new file mode 100644 index 0000000..ab10de2 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php @@ -0,0 +1,79 @@ +attributes->get('_route'); + + if (in_array($route, OpentelemetryInstrumentationConfig::getExcludedRoutes(), true)) { + static::$result = self::SAMPLING_RESULT_BLOCK; + + return static::$result; + } + + if (static::decideForRootSpan()) { + static::$result = static::SAMPLING_RESULT_ALLOW_ROOT_SPAN; + + return static::$result; + } + + static::$result = static::SAMPLING_RESULT_ALLOW_ALL; + + return static::$result; + } + + /** + * @return bool + */ + public static function shouldSkipTraceBody(): bool + { + return in_array(static::$result, [static::SAMPLING_RESULT_BLOCK, static::SAMPLING_RESULT_ALLOW_ROOT_SPAN], true); + } + + /** + * @return bool + */ + public static function shouldSkipRootSpan(): bool + { + return static::$result === static::SAMPLING_RESULT_BLOCK; + } + + /** + * @return bool + */ + protected static function decideForRootSpan(): bool + { + return !((mt_rand() / mt_getrandmax()) <= OpentelemetryInstrumentationConfig::getTraceSamplerProbability()); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php index 5616a9d..add33a4 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Attributes.php @@ -12,7 +12,7 @@ use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use Traversable; -class Attributes implements AttributesInterface, IteratorAggregate +class Attributes implements AttributesInterface, IteratorAggregate, WritableAttributesInterface { /** * @param array $attributes @@ -98,4 +98,19 @@ public function getDroppedAttributesCount(): int { return $this->droppedAttributesCount; } + + /** + * @param string $key + * @param mixed $value + * + * @return void + */ + public function set(string $key, $value): void + { + if ($value === null) { + unset($this->attributes[$key]); + } + + $this->attributes[$key] = $value; + } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/WritableAttributesInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/WritableAttributesInterface.php new file mode 100644 index 0000000..a97d5e6 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/WritableAttributesInterface.php @@ -0,0 +1,16 @@ +getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) !== true - && $span->getDuration() < OpentelemetryConfig::getSamplerThresholdNano() + && $span->getDuration() < OpentelemetryInstrumentationConfig::getSamplerThresholdNano() && $span->getParentSpanId() && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 3683d5c..a113145 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -10,18 +10,11 @@ use OpenTelemetry\API\Common\Time\Clock; use OpenTelemetry\API\Signals; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; -use OpenTelemetry\API\Trace\Span; -use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\SpanKind; use OpenTelemetry\Context\Context; use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; use OpenTelemetry\Contrib\Otlp\OtlpUtil; -use OpenTelemetry\SDK\Common\Attribute\Attributes; use OpenTelemetry\SDK\Common\Util\ShutdownHandler; -use OpenTelemetry\SDK\Metrics\MeterProviderFactory; -use OpenTelemetry\SDK\Metrics\MeterProviderInterface; -use OpenTelemetry\SDK\Resource\ResourceInfo; -use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Sdk; use OpenTelemetry\SDK\Trace\Sampler\ParentBased; use OpenTelemetry\SDK\Trace\SamplerInterface; @@ -30,16 +23,22 @@ use OpenTelemetry\SDK\Trace\TracerProviderInterface; use OpenTelemetry\SemConv\ResourceAttributes; use OpenTelemetry\SemConv\TraceAttributes; +use Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo; +use Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfoFactory; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\TraceSampleResult; +use Spryker\Service\Opentelemetry\Instrumentation\Span\Attributes; +use Spryker\Service\Opentelemetry\Instrumentation\Span\Span; use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanConverter; use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanExporter; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; +use Spryker\Service\Opentelemetry\OpentelemetryInstrumentationConfig; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; +use Spryker\Service\Opentelemetry\Storage\ResourceNameStorage; use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorage; use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; -use Spryker\Zed\Opentelemetry\OpentelemetryConfig; use Symfony\Component\HttpFoundation\Request; /** @@ -63,59 +62,56 @@ class SprykerInstrumentationBootstrap protected const INSTRUMENTATION_VERSION = '0.1'; /** - * @var \OpenTelemetry\API\Trace\SpanInterface|null + * @var \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo|null */ - protected static ?SpanInterface $rootSpan = null; + protected static ?ResourceInfo $resourceInfo = null; /** * @return void */ public static function register(): void { + $request = RequestProcessor::getRequest(); + + TraceSampleResult::shouldSample($request); + + if (TraceSampleResult::shouldSkipRootSpan()) { + return; + } + $serviceName = static::resolveServiceName(); $resource = static::createResource($serviceName); $tracerProvider = static::createTracerProvider($resource); - //$meterProvider = static::createMeterProvider($resource); Sdk::builder() ->setTracerProvider($tracerProvider) - //->setMeterProvider($meterProvider) ->setPropagator(TraceContextPropagator::getInstance()) ->buildAndRegisterGlobal(); - static::registerRootSpan($serviceName); + static::registerRootSpan($serviceName, $request); ShutdownHandler::register($tracerProvider->shutdown(...)); - //ShutdownHandler::register($meterProvider->shutdown(...)); } /** * @param string $serviceName * - * @return \OpenTelemetry\SDK\Resource\ResourceInfo + * @return \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo */ protected static function createResource(string $serviceName): ResourceInfo { - return ResourceInfoFactory::defaultResource()->merge(ResourceInfo::create(Attributes::create([ - ResourceAttributes::SERVICE_NAMESPACE => OpentelemetryConfig::getServiceNamespace(), + static::$resourceInfo = ResourceInfoFactory::defaultResource()->mergeSprykerResource(ResourceInfo::createSprykerResource(Attributes::create([ + ResourceAttributes::SERVICE_NAMESPACE => OpentelemetryInstrumentationConfig::getServiceNamespace(), ResourceAttributes::SERVICE_VERSION => static::INSTRUMENTATION_VERSION, ResourceAttributes::SERVICE_NAME => $serviceName, ]))); - } - /** - * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource - * - * @return \OpenTelemetry\SDK\Metrics\MeterProviderInterface - */ - protected static function createMeterProvider(ResourceInfo $resource): MeterProviderInterface - { - return (new MeterProviderFactory())->create($resource); + return static::$resourceInfo; } /** - * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource + * @param \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo $resource * * @return \OpenTelemetry\SDK\Trace\TracerProviderInterface */ @@ -134,7 +130,7 @@ protected static function createTracerProvider(ResourceInfo $resource): TracerPr protected static function createSpanExporter(): SpanExporterInterface { return new SpanExporter( - (new GrpcTransportFactory())->create(OpentelemetryConfig::getExporterEndpoint() . OtlpUtil::method(Signals::TRACE)), + (new GrpcTransportFactory())->create(OpentelemetryInstrumentationConfig::getExporterEndpoint() . OtlpUtil::method(Signals::TRACE)), new SpanConverter(), ); } @@ -147,6 +143,9 @@ protected static function createSpanProcessor(): SpanProcessorInterface return new PostFilterBatchSpanProcessor( static::createSpanExporter(), Clock::getDefault(), + OpentelemetryInstrumentationConfig::getSpanProcessorMaxQueueSize(), + OpentelemetryInstrumentationConfig::getSpanProcessorScheduleDelay(), + OpentelemetryInstrumentationConfig::getSpanProcessorMaxBatchSize(), ); } @@ -155,7 +154,7 @@ protected static function createSpanProcessor(): SpanProcessorInterface */ protected static function createSampler(): SamplerInterface { - return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryConfig::getSamplerProbability())); + return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability())); } /** @@ -176,15 +175,15 @@ protected static function resolveServiceName(): string return sprintf('CLI %s', strtoupper($application)); } - $mapping = OpentelemetryConfig::getServiceNameMapping(); + $mapping = OpentelemetryInstrumentationConfig::getServiceNameMapping(); - foreach ($mapping as $pattern => $serviceName) { + foreach ($mapping as $serviceName => $pattern) { if (preg_match($pattern, $request->getHost())) { return $serviceName; } } - return OpentelemetryConfig::getDefaultServiceName(); + return OpentelemetryInstrumentationConfig::getDefaultServiceName(); } /** @@ -192,10 +191,8 @@ protected static function resolveServiceName(): string * * @return void */ - protected static function registerRootSpan(string $servicedName): void + protected static function registerRootSpan(string $servicedName, Request $request): void { - $request = (new RequestProcessor())->getRequest(); - $cli = $request->server->get('argv'); if ($cli) { $name = implode(' ', $cli); @@ -210,7 +207,6 @@ protected static function registerRootSpan(string $servicedName): void ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) - //->setAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE, true) ->startSpan(); Context::storage()->attach($span->storeInContext($parent)); @@ -235,6 +231,10 @@ protected static function formatSpanName(Request $request): string */ public static function shutdownHandler(): void { + $resourceName = ResourceNameStorage::getInstance()->getName(); + if ($resourceName) { + static::$resourceInfo->setServiceName($resourceName); + } $scope = Context::storage()->scope(); if (!$scope) { return; diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php new file mode 100644 index 0000000..bc54ecf --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -0,0 +1,221 @@ + + */ + public static function getExcludedRoutes(): array + { + $urls = getenv(static::OTEL_PHP_EXCLUDED_URLS) ?: ''; + + return explode(',', $urls); + } + + /** + * @api + * + * @return array + */ + public static function getServiceNameMapping(): array + { + $mapping = getenv(static::OTEL_SERVICE_NAME_MAPPING) ?: '{}'; + $mapping = json_decode($mapping, true); + + if ($mapping === []) { + return [ + 'Yves' => '/(?:https?:\/\/)?(yves)\./', + 'Backoffice' => '/(?:https?:\/\/)?(backoffice)\./', + 'REST API' => '/(?:https?:\/\/)?(glue)\./', + 'Merchant Portal' => '/(?:https?:\/\/)?(merchant)\./', + 'Backend Gateway' => '/(?:https?:\/\/)?(backend-gateway)\./', + 'Storefront API' => '/(?:https?:\/\/)?(glue-storefront)\./', + 'Backend API' => '/(?:https?:\/\/)?(glue-backend)\./', + ]; + } + + return $mapping; + } + + /** + * @api + * + * @return string + */ + public static function getDefaultServiceName(): string + { + return getenv(static::OTEL_DEFAULT_SERVICE_NAME) ?: 'Default Service'; + } + + /** + * @api + * + * @return float + */ + public static function getSamplerProbability(): float + { + $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 1.0; + + return (float)$probability; + } + + /** + * @api + * + * @return float + */ + public static function getSamplerProbabilityForCriticalSpans(): float + { + $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 1.0; + + return (float)$probability; + } + + /** + * @return int + */ + public static function getSpanProcessorScheduleDelay(): int + { + $delay = getenv(static::OTEL_BSP_SCHEDULE_DELAY); + if ($delay === false) { + return 5000; + } + + return (int)$delay; + } + + /** + * @return int + */ + public static function getSpanProcessorMaxQueueSize(): int + { + $delay = getenv(static::OTEL_BSP_MAX_QUEUE_SIZE); + if ($delay === false) { + return 2048; + } + + return (int)$delay; + } + + /** + * @return int + */ + public static function getSpanProcessorMaxBatchSize(): int + { + $delay = getenv(static::OTEL_BSP_MAX_EXPORT_BATCH_SIZE); + if ($delay === false) { + return 512; + } + + return (int)$delay; + } + + /** + * @return float + */ + public static function getTraceSamplerProbability(): float + { + $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 1.0; + + return (float)$probability; + } +} diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryService.php b/src/Spryker/Service/Opentelemetry/OpentelemetryService.php index 1571cc7..8b78ab4 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryService.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryService.php @@ -8,6 +8,7 @@ namespace Spryker\Service\Opentelemetry; use Spryker\Service\Kernel\AbstractService; +use Spryker\Service\Opentelemetry\Storage\ResourceNameStorage; /** * @method \Spryker\Service\Opentelemetry\OpentelemetryServiceFactory getFactory() @@ -38,4 +39,14 @@ public function setRootSpanName(string $name): void { $this->getFactory()->createRootSpanNameStorage()->setName($name); } + + /** + * @param string $name + * + * @return void + */ + public function setResourceName(string $name): void + { + $this->getFactory()->createResourceNameStorage()->setName($name); + } } diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php index 97e1c41..788c351 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php @@ -10,6 +10,7 @@ use Spryker\Service\Kernel\AbstractServiceFactory; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorageInterface; +use Spryker\Service\Opentelemetry\Storage\ResourceNameStorage; use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorage; use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorageInterface; @@ -30,4 +31,12 @@ public function createRootSpanNameStorage(): RootSpanNameStorageInterface { return RootSpanNameStorage::getInstance(); } + + /** + * @return \Spryker\Service\Opentelemetry\Storage\ResourceNameStorage + */ + public function createResourceNameStorage(): ResourceNameStorage + { + return ResourceNameStorage::getInstance(); + } } diff --git a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php index 6aebcf1..f1bffd3 100644 --- a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php +++ b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php @@ -7,8 +7,10 @@ namespace Spryker\Service\Opentelemetry\Plugin; +use OpenTelemetry\Context\Context; use Spryker\Service\Kernel\AbstractPlugin; use Spryker\Service\MonitoringExtension\Dependency\Plugin\MonitoringExtensionPluginInterface; +use Spryker\Service\Opentelemetry\Instrumentation\Span\Span; /** * @method \Spryker\Service\Opentelemetry\OpentelemetryService getService() @@ -17,7 +19,7 @@ class OpentelemetryMonitoringExtensionPlugin extends AbstractPlugin implements M { /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Adds error in to the current active span * * @api * @@ -28,11 +30,18 @@ class OpentelemetryMonitoringExtensionPlugin extends AbstractPlugin implements M */ public function setError(string $message, $exception): void { + $scope = Context::storage()->scope(); + if (!$scope) { + return; + } + + $span = Span::fromContext($scope->context()); + $span->recordException($exception); } /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Sets Service name for traces. If no application name was provided, default one will be used. * * @api * @@ -44,6 +53,7 @@ public function setError(string $message, $exception): void */ public function setApplicationName(?string $application = null, ?string $store = null, ?string $environment = null): void { + $this->getService()->setResourceName(sprintf('%s-%s (%s)', $application ?? '', $store ?? '', $environment ?? '')); } /** @@ -64,7 +74,7 @@ public function setTransactionName(string $name): void /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Opentelemetry instrumentation is completely custom. * * @api * @@ -72,11 +82,12 @@ public function setTransactionName(string $name): void */ public function markStartTransaction(): void { + return; } /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Opentelemetry instrumentation is completely custom. * * @api * @@ -84,6 +95,7 @@ public function markStartTransaction(): void */ public function markEndOfTransaction(): void { + return; } /** @@ -100,7 +112,7 @@ public function markIgnoreTransaction(): void /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Opentelemetry has not attributes to specify background jobs. Service name already defined for CLI commands * * @api * @@ -108,6 +120,7 @@ public function markIgnoreTransaction(): void */ public function markAsConsoleCommand(): void { + return; } /** @@ -128,7 +141,7 @@ public function addCustomParameter(string $key, $value): void /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Opentelemetry instrumentation is completely custom. * * @api * @@ -138,5 +151,6 @@ public function addCustomParameter(string $key, $value): void */ public function addCustomTracer(string $tracer): void { + return; } } diff --git a/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php new file mode 100644 index 0000000..a4da486 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php @@ -0,0 +1,43 @@ +name = $name; + } + + /** + * @return ?string + */ + public function getName(): ?string + { + return $this->name; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php new file mode 100644 index 0000000..df95bad --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php @@ -0,0 +1,13 @@ +name; } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php deleted file mode 100644 index bf1ed1a..0000000 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/SpanFilter/SamplerSpanFilter.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - public static function getExcludedURLs(): array - { - $urls = getenv('OTEL_PHP_EXCLUDED_URLS') ?: []; - - return explode(',', $urls); - } - - /** - * @api - * - * @return array - */ - public static function getServiceNameMapping(): array - { - $mapping = getenv('OTEL_SERVICE_NAME_MAPPING') ?: '{}'; - $mapping = json_decode($mapping, true); - - if ($mapping === []) { - return [ - '/(?:https?:\/\/)?(yves)\./' => 'Yves', - '/(?:https?:\/\/)?(backoffice)\./' => 'Backoffice', - '/(?:https?:\/\/)?(glue)\./' => 'Legacy Glue', - '/(?:https?:\/\/)?(merchant)\./' => 'Merchant Portal', - '/(?:https?:\/\/)?(backend-gateway)\./' => 'Backend Gateway', - '/(?:https?:\/\/)?(glue-storefront)\./' => 'Glue Storefront', - '/(?:https?:\/\/)?(glue-backend)\./' => 'Glue Backend', - ]; - } - - return $mapping; - } - - /** - * @api - * - * @return string - */ - public static function getDefaultServiceName(): string - { - return getenv('OTEL_DEFAULT_SERVICE_NAME') ?: 'Default Service'; - } - - /** - * @api - * - * @return float - */ - public static function getSamplerProbability(): float - { - $probability = getenv('OTEL_TRACES_SAMPLER_ARG') ?: 1.0; - - return (float)$probability; - } } From e443f6213d9f3cca65662e32acb4c7bde61807ff Mon Sep 17 00:00:00 2001 From: gechetspr Date: Mon, 2 Dec 2024 11:04:09 +0200 Subject: [PATCH 34/48] Updated hook generation --- .../Business/Generator/Collector/ClassCollector.php | 1 + .../Business/Generator/ContentCreator/HookContentCreator.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php index 57f972a..1fab705 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php @@ -315,6 +315,7 @@ protected function getExcludedClasses(): array '*Bootstrap.php', 'AbstractSpy*.php', '*Interface.php', + '*Plugin.php', ]; } } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index 6fc822e..1439fb9 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -73,7 +73,7 @@ function: \'%s\', $span = \\Spryker\\Shared\\OpenTelemetry\\Instrumentation\\CachedInstrumentation::getCachedInstrumentation() ->tracer() - ->spanBuilder($request->getMethod() . \' %s\') + ->spanBuilder(\' %s\') ->setParent($context) ->setSpanKind(($type === \\Symfony\\Component\\HttpKernel\\HttpKernelInterface::SUB_REQUEST) ? \\OpenTelemetry\\API\\Trace\\SpanKind::KIND_INTERNAL : \\OpenTelemetry\\API\\Trace\\SpanKind::KIND_SERVER) ->setAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::CODE_FUNCTION, $function) @@ -101,7 +101,7 @@ function: \'%s\', } $scope->detach(); - $span = \\OpenTelemetry\\API\\Trace\\Span::fromContext($scope->context()); + $span = \\Spryker\\Service\\Opentelemetry\\Instrumentation\\Span\\Span::fromContext($scope->context()); if ($exception !== null) { $span->recordException($exception); From 35c6a0a321b7fd276d91959d41d5a1273dabd111 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Mon, 2 Dec 2024 15:22:13 +0200 Subject: [PATCH 35/48] Updated generation and post sampling --- .../CriticalSpanTraceIdRatioSampler.php | 4 +- .../Sampler/TraceSampleResult.php | 2 +- .../TraceStateAwareSamplerInterface.php | 4 +- .../PostFilterBatchSpanProcessor.php | 14 +- .../SprykerInstrumentationBootstrap.php | 4 +- .../OpentelemetryInstrumentationConfig.php | 24 +- .../Generator/Collector/ClassCollector.php | 1 + .../ContentCreator/HookContentCreator.php | 8 +- .../Business/Generator/HookGenerator.php | 19 - .../Zed/Opentelemetry/OpentelemetryConfig.php | 778 +++++++++++++++++- 10 files changed, 824 insertions(+), 34 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index f1da8a3..af22393 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -72,11 +72,11 @@ public function shouldSample( } /** - * @param \OpenTelemetry\API\Trace\TraceStateInterface $traceState + * @param \OpenTelemetry\API\Trace\TraceStateInterface|null $traceState * * @return void */ - public function addTraceState(TraceStateInterface $traceState): void + public function addTraceState(?TraceStateInterface $traceState): void { $this->traceState = $traceState; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php index ab10de2..5acdcb3 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php @@ -74,6 +74,6 @@ public static function shouldSkipRootSpan(): bool */ protected static function decideForRootSpan(): bool { - return !((mt_rand() / mt_getrandmax()) <= OpentelemetryInstrumentationConfig::getTraceSamplerProbability()); + return (mt_rand() / mt_getrandmax()) >= OpentelemetryInstrumentationConfig::getTraceSamplerProbability(); } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php index 96c1b52..df6c8cd 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php @@ -13,9 +13,9 @@ interface TraceStateAwareSamplerInterface { /** - * @param \OpenTelemetry\API\Trace\TraceStateInterface $span + * @param \OpenTelemetry\API\Trace\TraceStateInterface|null $span * * @return void */ - public function addTraceState(TraceStateInterface $span): void; + public function addTraceState(?TraceStateInterface $span): void; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index aa44e8e..f2273bd 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -192,6 +192,7 @@ public function onStart(ReadWriteSpanInterface $span, ContextInterface $parentCo */ public function onEnd(ReadableSpanInterface $span): void { + //$file = fopen(APPLICATION_ROOT_DIR . '/dropped', 'a'); if ($this->closed) { return; } @@ -200,13 +201,20 @@ public function onEnd(ReadableSpanInterface $span): void return; } - if ( - $span->getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) !== true - && $span->getDuration() < OpentelemetryInstrumentationConfig::getSamplerThresholdNano() + $duration = $span->getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) === true + ? OpentelemetryInstrumentationConfig::getSamplerThresholdNanoForCriticalSpan() + : OpentelemetryInstrumentationConfig::getSamplerThresholdNano(); + + + if ($span->getDuration() < $duration && $span->getParentSpanId() && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { $this->dropped++; +// if ($span->getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) !== true) { +// fwrite($file, '\'' . $span->getName() . '\',' . PHP_EOL); +// } +// fclose($file); return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index a113145..057c33a 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -154,7 +154,8 @@ protected static function createSpanProcessor(): SpanProcessorInterface */ protected static function createSampler(): SamplerInterface { - return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability())); + return new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability()); + //return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability())); } /** @@ -207,6 +208,7 @@ protected static function registerRootSpan(string $servicedName, Request $reques ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) + ->setAttribute('FULL_TRACE', !TraceSampleResult::shouldSkipTraceBody()) ->startSpan(); Context::storage()->attach($span->storeInContext($parent)); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index bc54ecf..ccceb5d 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -14,6 +14,11 @@ class OpentelemetryInstrumentationConfig */ protected const OTEL_BSP_MIN_SPAN_DURATION_THRESHOLD = 'OTEL_BSP_MIN_SPAN_DURATION_THRESHOLD'; + /** + * @var string + */ + protected const OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD = 'OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD'; + /** * @var string */ @@ -79,6 +84,21 @@ public static function getSamplerThresholdNano(): int return $multiplicator * 1000000; } + /** + * Specification: + * - The threshold in nanoseconds for the critical span to be sampled. + * + * @api + * + * return int + */ + public static function getSamplerThresholdNanoForCriticalSpan(): int + { + $multiplicator = getenv(static::OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD) ?: 1; + + return $multiplicator * 1000000; + } + /** * @api * @@ -153,7 +173,7 @@ public static function getDefaultServiceName(): string */ public static function getSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 1.0; + $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.5; return (float)$probability; } @@ -165,7 +185,7 @@ public static function getSamplerProbability(): float */ public static function getSamplerProbabilityForCriticalSpans(): float { - $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 1.0; + $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.5; return (float)$probability; } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php index 1fab705..ed57639 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php @@ -316,6 +316,7 @@ protected function getExcludedClasses(): array 'AbstractSpy*.php', '*Interface.php', '*Plugin.php', + '*Mapper.php', ]; } } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index 1439fb9..a5dc8f7 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -59,6 +59,10 @@ public function createHookContent(array $class): string $hooks = []; foreach ($class[static::METHODS_KEY] as $method) { + $methodHookName = $this->buildMethodHookName($class, $method); + if (in_array($methodHookName, $this->config->getExcludedSpans(), true)) { + continue; + } $hooks[] = sprintf( ' \\OpenTelemetry\\Instrumentation\\hook( @@ -73,7 +77,7 @@ function: \'%s\', $span = \\Spryker\\Shared\\OpenTelemetry\\Instrumentation\\CachedInstrumentation::getCachedInstrumentation() ->tracer() - ->spanBuilder(\' %s\') + ->spanBuilder(\'%s\') ->setParent($context) ->setSpanKind(($type === \\Symfony\\Component\\HttpKernel\\HttpKernelInterface::SUB_REQUEST) ? \\OpenTelemetry\\API\\Trace\\SpanKind::KIND_INTERNAL : \\OpenTelemetry\\API\\Trace\\SpanKind::KIND_SERVER) ->setAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::CODE_FUNCTION, $function) @@ -117,7 +121,7 @@ function: \'%s\', $class[static::NAMESPACE_KEY], $class[static::CLASS_NAME_KEY], $method, - $this->buildMethodHookName($class, $method), + $methodHookName, ); } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php index 750ab53..c07d63f 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php @@ -96,10 +96,6 @@ public function generate(): void fwrite($file, $content); fwrite($file, $this->contentCreator->createHookContent($class)); fclose($file); -// file_put_contents( -// $this->getOutputFilepath($class), -// $this->contentCreator->createHookContent($class), -// ); } } @@ -115,21 +111,6 @@ protected function ensureDirectoryExists(): void $this->fileSystem->mkdir($this->config->getOutputDir(), static::DIRECTORY_PERMISSIONS); } - /** - * @param array $class - * - * @return string - */ - protected function getOutputFilepath(array $class): string - { - return sprintf( - static::OUTPUT_FILE_PATH_PLACEHOLDER, - $this->config->getOutputDir(), - str_replace('\\', '-', $class[static::NAMESPACE_KEY]), - $class[static::CLASS_NAME_KEY], - ); - } - /** * @param array $class * diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 4b2cb77..9509370 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -71,7 +71,6 @@ public function getExcludedDirs(): array 'Validation', 'Development', 'ErrorHandler', - 'Form', 'Glossary', 'GuiTable', 'ModuleFinder', @@ -96,7 +95,6 @@ public function getExcludedDirs(): array 'SecuritySystemUser', 'SecurityOauthUser', 'UserLocale', - 'User', 'AclMerchantAgent', 'Merchant', 'MerchantStock', @@ -111,6 +109,782 @@ public function getExcludedDirs(): array ]; } + /** + * Specification: + * - List of Span names (Module-Class::method) that should be excluded from generated hooks. + * - Most of the list are spans that are proven fast and will be skipped from the result in any case. + * + * @api + * + * @return array + */ + public function getExcludedSpans(): array + { + return [ + 'AgentPage-AgentSecurityOptionsBuilder::buildOptions', + 'AgentPage-AgentTokenAfterCustomerAuthenticationSuccessUpdater::execute', + 'AgentPage-AgentUserProvider::refreshUser', + 'AgentPage-LoginCheckUrlFormatter::getLoginCheckPath', + 'AgentPage-SecurityBuilderExpander::extend', + 'AgentPage-SwitchUserEventSubscriber::getSubscribedEvents', + 'AgentWidget-AgentControlBarWidget::getName', + 'AgentWidget-AgentControlBarWidget::getTemplate', + 'AssetWidget-AssetWidget::getName', + 'AssetWidget-AssetWidget::getTemplate', + 'AssetWidget-AssetWidgetDataProvider::getSlotContent', + 'AvailabilityNotification-AvailabilityNotificationSubscriptionReader::getAvailabilityNotifications', + 'AvailabilityNotification-CustomerExpander::expandCustomerTransferWithAvailabilityNotificationSubscriptionList', + 'AvailabilityNotificationWidget-AvailabilityNotificationSubscriptionWidget::getName', + 'BarcodeWidget-BarcodeWidget::getName', + 'BusinessOnBehalf-BusinessOnBehalfFacade::setDefaultCompanyUserToCustomer', + 'BusinessOnBehalf-CustomerExpander::expandCustomer', + 'BusinessOnBehalf-CustomerHydrator::hydrateCustomerWithCompanyUser', + 'BusinessOnBehalfWidget-BusinessOnBehalfStatusWidget::getName', + 'BusinessOnBehalfWidget-BusinessOnBehalfStatusWidget::getTemplate', + 'Cart-CartFacade::cleanUpItems', + 'Cart-CartFacade::expandItemGroupKeysWithCartIdentifier', + 'Cart-GroupKeyExpander::expandItemGroupKeysWithCartIdentifier', + 'Cart-NonPersistentProvider::addItems', + 'Cart-QuoteCleaner::cleanUpItemGroupKeyPrefix', + 'CartCodeWidget-CartCodeFormWidget::getName', + 'CartCodeWidget-CartCodeFormWidget::getTemplate', + 'CartNote-CartNoteSaver::saveCartNoteToOrder', + 'CartNoteWidget-CartItemNoteFormWidget::getName', + 'CartNoteWidget-CartItemNoteFormWidget::getTemplate', + 'CartNoteWidget-CartNoteFormWidget::getName', + 'CartNoteWidget-CartNoteFormWidget::getTemplate', + 'CartPage-AddItemsFormWidget::getName', + 'CartPage-CartAddProductAsSeparateItemWidget::getName', + 'CartPage-CartAddProductAsSeparateItemWidget::getTemplate', + 'CartPage-CartChangeQuantityFormWidget::getName', + 'CartPage-CartChangeQuantityFormWidget::getTemplate', + 'CartPage-CartSummaryHideTaxAmountWidget::getName', + 'CartPage-CartSummaryHideTaxAmountWidget::getTemplate', + 'CartPage-ProductAbstractAddToCartButtonWidget::getName', + 'CartPage-ProductAbstractAddToCartButtonWidget::getTemplate', + 'CartPage-ProductViewExpander::expandProductViewWithCartData', + 'CartPage-RemoveFromCartFormWidget::getName', + 'CartPage-RemoveFromCartFormWidget::getTemplate', + 'CatalogPage-CategoryNodeWalker::start', + 'CatalogPage-UrlGenerator::generateUrlWithoutActiveSearchFilter', + 'CategoryDiscountConnector-CategoryDecisionRuleChecker::isCategorySatisfiedBy', + 'CategoryDiscountConnector-CategoryDiscountConnectorFacade::getDiscountableItemsByCategory', + 'CategoryDiscountConnector-CategoryDiscountConnectorFacade::isCategorySatisfiedBy', + 'CategoryDiscountConnector-CategoryReader::getCategoryKeysGroupedByIdCategoryNode', + 'CategoryDiscountConnector-DiscountableItemReader::getDiscountableItemsByCategory', + 'CategoryDiscountConnector-ProductCategoryReader::getProductCategoriesGroupedByIdProductAbstract', + 'CategoryImageStorageWidget-CategoryImageStorageWidget::getName', + 'CheckoutPage-AbstractBaseStep::execute', + 'CheckoutPage-AbstractBaseStep::preCondition', + 'CheckoutPage-AddressStep::requireInput', + 'CheckoutPage-CustomerAddressViewDataExpander::expand', + 'CheckoutPage-CustomerStep::postCondition', + 'CheckoutPage-CustomerStep::requireInput', + 'CheckoutPage-DataContainer::get', + 'CheckoutPage-DataContainer::set', + 'CheckoutPage-GiftCardItemsChecker::hasOnlyGiftCardItems', + 'CheckoutPage-PaymentMethodKeyExtractor::getPaymentSelectionKey', + 'CheckoutPage-PaymentStep::requireInput', + 'CheckoutPage-PlaceOrderStep::postCondition', + 'CheckoutPage-PlaceOrderStep::preCondition', + 'CheckoutPage-PostConditionChecker::check', + 'CheckoutPage-ShipmentStep::postCondition', + 'CheckoutPage-ShipmentStep::requireInput', + 'CheckoutWidget-CheckoutBreadcrumbWidget::getName', + 'CheckoutWidget-CheckoutBreadcrumbWidget::getTemplate', + 'CheckoutWidget-ProceedToCheckoutButtonWidget::getName', + 'CheckoutWidget-ProceedToCheckoutButtonWidget::getTemplate', + 'ClickAndCollectExample-QuoteProductOfferReplacer::replaceQuoteItemProductOffers', + 'ClickAndCollectPageExample-ClickAndCollectServicePointAddressFormWidget::getName', + 'ClickAndCollectPageExample-ClickAndCollectServicePointAddressFormWidget::getTemplate', + 'Cms-CmsPageUrlBuilder::getPageUrlPrefix', + 'Cms-TemplateContentReader::getTemplateContent', + 'Cms-TemplatePlaceholderParser::getTemplatePlaceholders', + 'CmsBlockWidget-CmsBlockValidator::isValid', + 'CmsContentWidgetProductConnector-CmsProductGroupContentWidgetConfigurationProvider::getAvailableTemplates', + 'CmsContentWidgetProductConnector-CmsProductGroupContentWidgetConfigurationProvider::getFunctionName', + 'CmsSlotBlockWidget-CmsSlotBlockWidgetDataProvider::getSlotContent', + 'Comment-CommentFacade::findCommentThreadByOwner', + 'Comment-CommentThreadReader::findCommentThreadByOwner', + 'Comment-CommentThreadReader::getCommentThreads', + 'CommentWidget-CommentThreadExpander::expandCommentsWithPlainTags', + 'CommentWidget-CommentThreadPreparer::prepareTaggedComments', + 'CommentWidget-CommentThreadWidget::getName', + 'CommentWidget-CommentThreadWidget::getTemplate', + 'CompanyBusinessUnit-CompanyBusinessUnitFacade::getCompanyBusinessUnitById', + 'CompanyBusinessUnit-CompanyBusinessUnitPluginExecutor::executeTransferExpanderPlugins', + 'CompanyBusinessUnit-CompanyBusinessUnitReader::getCompanyBusinessUnitById', + 'CompanyBusinessUnitSalesConnector-CompanyBusinessUnitSalesConnectorFacade::isFilterFieldSet', + 'CompanyBusinessUnitSalesConnector-FilterFieldChecker::isFilterFieldSet', + 'CompanyBusinessUnitSalesConnector-OrderWriter::updateOrderCompanyBusinessUnitUuid', + 'CompanyPage-CompanyBusinessUnitAddressReader::getDefaultBillingAddress', + 'CompanyPage-CompanyUnitAddressExpander::expandWithCompanyUnitAddress', + 'CompanyPage-CompanyUserValidator::hasBusinessUnit', + 'CompanyRole-CompanyRoleFacade::findPermissionsByIdCompanyUser', + 'CompanyRole-CompanyRoleFacade::hydrateCompanyUser', + 'CompanySalesConnector-CompanySalesConnectorFacade::isFilterFieldSet', + 'CompanySalesConnector-FilterFieldChecker::isFilterFieldSet', + 'CompanySalesConnector-OrderWriter::updateOrderCompanyUuid', + 'CompanyUnitAddress-CompanyBusinessUnitAddressReader::getCompanyBusinessUnitAddressesByCriteriaFilter', + 'CompanyUnitAddress-CompanyUnitAddressFacade::getCompanyUnitAddressCollection', + 'CompanyUser-CompanyUserFacade::expandCustomerWithIsActiveCompanyUserExists', + 'CompanyUser-CustomerExpander::expandCustomerWithIsActiveCompanyUserExists', + 'CompanyWidget-AddressProvider::companyBusinessUnitAddressesExists', + 'CompanyWidget-AddressProvider::findCurrentCompanyBusinessUnitAddress', + 'CompanyWidget-AddressProvider::getIndexedCompanyBusinessUnitAddressList', + 'CompanyWidget-AddressProvider::getIndexedCustomerAddressList', + 'CompanyWidget-CompanyMenuItemWidget::getName', + 'CompanyWidget-CompanyMenuItemWidget::getTemplate', + 'ConfigurableBundle-ConfiguredBundleItemCleaner::removeInactiveConfiguredBundleItemsFromQuote', + 'ConfigurableBundleCart-ConfigurableBundleCartFacade::expandConfiguredBundleItemsWithGroupKey', + 'ConfigurableBundleCart-ConfigurableBundleCartFacade::expandConfiguredBundleItemsWithQuantityPerSlot', + 'ConfigurableBundleCart-ConfigurableBundleCartFacade::updateConfiguredBundleQuantityForQuote', + 'ConfigurableBundleCart-ConfigurableBundleCartFacade::updateConfiguredBundleQuantityPerSlotForQuote', + 'ConfigurableBundleCart-ConfiguredBundleGroupKeyExpander::expandConfiguredBundleItemsWithGroupKey', + 'ConfigurableBundleCart-ConfiguredBundleQuantityChecker::checkConfiguredBundleQuantity', + 'ConfigurableBundleCart-ConfiguredBundleQuantityExpander::expandConfiguredBundleItemsWithQuantityPerSlot', + 'ConfigurableBundleCart-ConfiguredBundleQuantityUpdater::updateConfiguredBundleQuantity', + 'ConfigurableBundleCart-ConfiguredBundleQuantityUpdater::updateConfiguredBundleQuantityPerSlot', + 'ConfigurableBundleCart-ConfiguredBundleTemplateSlotChecker::checkConfiguredBundleTemplateSlotCombination', + 'ConfigurableBundleNoteWidget-ConfiguredBundleNoteWidget::getName', + 'ConfigurableBundleWidget-ConfiguredBundleGrouper::getConfiguredBundles', + 'ConfigurableBundleWidget-QuoteConfiguredBundleWidget::getName', + 'ConfigurableBundleWidget-QuoteConfiguredBundleWidget::getTemplate', + 'ContentGui-ContentResolver::getTermKeys', + 'Currency-CurrencyBuilder::fromIsoCode', + 'Currency-CurrencyBuilder::getCurrent', + 'Currency-CurrencyFacade::fromIsoCode', + 'Currency-CurrencyFacade::getByIdCurrency', + 'Currency-CurrencyFacade::validateCurrencyInQuote', + 'Currency-CurrencyReader::getByIdCurrency', + 'Currency-CurrencyReader::getByIsoCode', + 'Currency-QuoteValidator::validate', + 'CurrencyWidget-CurrencyWidget::getName', + 'CurrencyWidget-CurrencyWidget::getTemplate', + 'Customer-CustomerAddressCheckoutSalutationValidator::validate', + 'Customer-CustomerCheckoutSalutationValidator::validate', + 'Customer-CustomerFacade::validateCustomerAddressCheckoutSalutation', + 'Customer-CustomerOrderHydrator::hydrateOrderTransfer', + 'Customer-CustomerOrderSaver::saveOrderCustomer', + 'Customer-DenyListCustomerPasswordPolicy::validatePassword', + 'Customer-LengthCustomerPasswordPolicy::validatePassword', + 'Customer-PreConditionChecker::checkPreConditions', + 'Customer-SequenceCustomerPasswordPolicy::validatePassword', + 'CustomerPage-AddressChoicesResolver::getAddressChoices', + 'CustomerPage-CustomerAddressExpander::expandWithCustomerAddress', + 'CustomerPage-CustomerLoginFormAuthenticator::supports', + 'CustomerPage-CustomerNavigationWidget::getName', + 'CustomerPage-CustomerNavigationWidget::getTemplate', + 'CustomerPage-CustomerRememberMeExpander::expand', + 'CustomerPage-CustomerSecurityOptionsBuilder::buildOptions', + 'CustomerPage-CustomerStepHandler::addToDataClass', + 'CustomerPage-InteractiveLoginEventSubscriber::getSubscribedEvents', + 'CustomerPage-LoginCheckUrlFormatter::getLoginCheckPath', + 'CustomerReorderWidget-CustomerReorderBundleItemCheckboxWidget::getName', + 'CustomerReorderWidget-CustomerReorderFormWidget::getName', + 'CustomerReorderWidget-CustomerReorderItemCheckboxWidget::getName', + 'CustomerReorderWidget-CustomerReorderItemsFormWidget::getName', + 'CustomerValidationPage-LogoutInvalidatedCustomerFilterControllerEventHandler::handle', + 'Discount-AbstractComparator::getExpression', + 'Discount-AbstractComparator::isValidValue', + 'Discount-ClauseValidator::validateClause', + 'Discount-CollectedDiscountItemFilter::filter', + 'Discount-CollectedDiscountSorter::sort', + 'Discount-CollectorContext::collect', + 'Discount-CollectorStrategyResolver::resolveCollector', + 'Discount-ComparatorOperators::compare', + 'Discount-ComparatorOperators::getCompoundComparatorExpressions', + 'Discount-ComparatorOperators::isExistingComparator', + 'Discount-ComparatorOperators::isValidComparatorValue', + 'Discount-CurrencyDecisionRule::isSatisfiedBy', + 'Discount-DayOfWeekDecisionRule::isSatisfiedBy', + 'Discount-DecisionRuleAndSpecification::isSatisfiedBy', + 'Discount-DecisionRuleContext::isSatisfiedBy', + 'Discount-DecisionRuleOrSpecification::isSatisfiedBy', + 'Discount-DiscountableItemFilter::filter', + 'Discount-DiscountableItemTransformer::transformSplittableDiscountableItem', + 'Discount-DiscountFacade::calculatePercentageDiscount', + 'Discount-DiscountFacade::checkDiscountChanges', + 'Discount-DiscountFacade::collectBySku', + 'Discount-DiscountFacade::isCurrencyDecisionRuleSatisfiedBy', + 'Discount-DiscountFacade::isDayOfTheWeekSatisfiedBy', + 'Discount-DiscountFacade::isSubTotalSatisfiedBy', + 'Discount-DiscountFacade::queryStringCompare', + 'Discount-Distributor::distributeDiscountAmountToDiscountableItems', + 'Discount-Equal::compare', + 'Discount-Equal::getAcceptedTypes', + 'Discount-GreaterEqual::compare', + 'Discount-GreaterEqual::getAcceptedTypes', + 'Discount-GreaterEqual::isValidValue', + 'Discount-IsIn::compare', + 'Discount-IsIn::getAcceptedTypes', + 'Discount-MetaDataProvider::isFieldAvailable', + 'Discount-MoneyValueConverter::convertDecimalToCent', + 'Discount-OperatorProvider::createComparators', + 'Discount-PercentageType::calculateDiscount', + 'Discount-QuoteChangeObserver::checkDiscountChanges', + 'Discount-QuoteDiscountMaxUsageValidator::validate', + 'Discount-SpecificationBuilder::buildFromQueryString', + 'Discount-SubTotalDecisionRule::isSatisfiedBy', + 'Discount-Tokenizer::tokenizeQueryString', + 'DiscountPromotion-CartGroupPromotionItems::expandItems', + 'DiscountPromotion-CartValidator::validateCartDiscountPromotions', + 'DiscountPromotion-DiscountPromotionFacade::filterDiscountPromotionItems', + 'DiscountPromotion-DiscountPromotionFacade::isDiscountWithPromotion', + 'DiscountPromotion-DiscountPromotionFacade::validateCartDiscountPromotions', + 'DiscountPromotion-DiscountPromotionItemChecker::isItemPromotional', + 'DiscountPromotion-DiscountPromotionItemChecker::isItemRelatedToDiscountPromotion', + 'DiscountPromotion-DiscountPromotionItemFilter::filterDiscountPromotionItems', + 'DiscountPromotion-DiscountPromotionReader::isDiscountWithPromotion', + 'DiscountPromotion-DiscountVoucherQuoteWriter::addDiscountVoucherCode', + 'DiscountPromotion-MultipleSkusDiscountPromotionCollectorStrategy::isApplicable', + 'DiscountPromotionWidget-CartDiscountPromotionProductListWidget::getName', + 'DiscountPromotionWidget-CartDiscountPromotionProductListWidget::getTemplate', + 'DiscountPromotionWidget-CartFormWidgetParameterExpander::expand', + 'DiscountPromotionWidget-DiscountPromotionDiscountReader::getAbstractSkusGroupedByIdDiscount', + 'DiscountPromotionWidget-DiscountPromotionDiscountReader::getUniqueDiscounts', + 'DummyMarketplacePayment-PaymentMethodFilter::filterPaymentMethods', + 'Event-EventDispatcher::triggerBulk', + 'Event-EventListenerContext::getEventQueueName', + 'Event-EventListenerContext::getQueuePoolName', + 'Event-EventListenerContext::isHandledInQueue', + 'Event-EventLogger::log', + 'Event-SubscriberMerger::mergeSubscribersWith', + 'EventBehavior-EventEntityTransferFilter::getEventTransferForeignKeys', + 'EventBehavior-EventEntityTransferFilter::getEventTransfersAdditionalValues', + 'ExampleProductSalePage-ExampleProductSalePageQueryContainer::queryProductLabelByName', + 'GiftCard-GiftCardCalculator::recalculate', + 'GiftCard-GiftCardDiscountableItemFilter::filterGiftCardDiscountableItems', + 'GiftCard-GiftCardFacade::filterGiftCardDiscountableItems', + 'GiftCard-GiftCardFacade::filterPaymentMethods', + 'GiftCard-OrderGiftCardsRelationshipWriter::saveOrderGiftCards', + 'GiftCard-PaymentMethodFilter::filterPaymentMethods', + 'GiftCard-SalesOrderItemSaver::saveSalesOrderItemGiftCards', + 'GiftCard-SalesOrderPaymentSaver::saveGiftCardOrderPayments', + 'GiftCard-SalesOrderPreChecker::precheckSalesOrderGiftCards', + 'GiftCard-ShipmentMethodCollectionRemover::remove', + 'GiftCard-ShipmentMethodGiftCardChecker::containsOnlyGiftCardItems', + 'GiftCard-ShipmentMethodGiftCardDisallowedChecker::isShipmentMethodSuitable', + 'GiftCard-ShipmentMethodGiftCardFilter::filter', + 'LanguageSwitcherWidget-LanguageSwitcherWidget::getName', + 'LanguageSwitcherWidget-LanguageSwitcherWidget::getTemplate', + 'ManualOrderEntry-OrderSourceHydrator::hydrateOrderSource', + 'MerchantOpeningHoursWidget-MerchantOpeningHoursWidget::getName', + 'MerchantProductOfferWidget-MerchantProductOfferExpander::expandItemTransferWithProductOfferReference', + 'MerchantProductOfferWidget-MerchantProductOffersSelectWidget::getName', + 'MerchantProductOfferWidget-MerchantProductOffersSelectWidget::getTemplate', + 'MerchantProductOfferWidget-MerchantProductOfferWidget::getName', + 'MerchantProductOfferWidget-MerchantProductOfferWidget::getTemplate', + 'MerchantProductOfferWidget-ShopContextResolver::resolve', + 'MerchantProductOption-MerchantProductOptionValidator::validateMerchantProductOptionsInCart', + 'MerchantProductOption-MerchantProductOptionValidator::validateMerchantProductOptionsOnCheckout', + 'MerchantProductWidget-MerchantProductWidget::getName', + 'MerchantProductWidget-MerchantProductWidget::getTemplate', + 'MerchantRelationRequestWidget-MerchantRelationRequestChecker::isMerchantApplicableForRequest', + 'MerchantRelationRequestWidget-MerchantRelationRequestCreateButtonWidget::getName', + 'MerchantRelationRequestWidget-MerchantRelationRequestCreateLinkWidget::getName', + 'MerchantRelationRequestWidget-MerchantRelationRequestCreateLinkWidget::getTemplate', + 'MerchantRelationRequestWidget-MerchantRelationRequestMenuItemWidget::getName', + 'MerchantRelationRequestWidget-MerchantRelationRequestMenuItemWidget::getTemplate', + 'MerchantRelationship-MerchantRelationshipExpander::expandWithName', + 'MerchantRelationship-MerchantRelationshipHydrator::hydrate', + 'MerchantRelationshipSalesOrderThreshold-MerchantRelationshipSalesOrderThresholdFacade::findApplicableThresholds', + 'MerchantRelationshipSalesOrderThreshold-MerchantRelationshipThresholdReader::findApplicableThresholds', + 'MerchantRelationshipWidget-MerchantRelationshipLinkListWidget::getName', + 'MerchantRelationshipWidget-MerchantRelationshipMenuItemWidget::getName', + 'MerchantRelationshipWidget-MerchantRelationshipMenuItemWidget::getTemplate', + 'MerchantSalesOrder-ExpenseExpander::expandShipmentExpenseWithMerchantReference', + 'MerchantSalesOrder-MerchantSalesOrderFacade::expandOrderWithMerchantReferences', + 'MerchantSalesOrder-OrderExpander::expandOrderWithMerchantReferences', + 'MerchantSalesOrder-OrderItemExpander::expandOrderItemWithMerchant', + 'MerchantSalesOrderWidget-MerchantOrderReferenceForItemsWidget::getName', + 'MerchantSalesReturnWidget-MerchantSalesReturnCreateFormWidget::getName', + 'MerchantSearchWidget-MerchantSearchWidget::getName', + 'MerchantShipment-MerchantShipmentFacade::expandCartChangeShipmentWithMerchantReference', + 'MerchantShipment-MerchantShipmentFacade::expandQuoteShipmentWithMerchantReference', + 'MerchantShipment-ShipmentExpander::expandCartChangeShipmentWithMerchantReference', + 'MerchantShipment-ShipmentExpander::expandQuoteShipmentWithMerchantReference', + 'MerchantSwitcherWidget-MerchantSwitcherSelectorFormWidget::getName', + 'MerchantSwitcherWidget-MerchantSwitcherSelectorFormWidget::getTemplate', + 'MerchantWidget-MerchantMetaSchemaWidget::getName', + 'MerchantWidget-MerchantMetaSchemaWidget::getTemplate', + 'MerchantWidget-ShoppingListMerchantWidget::getName', + 'MerchantWidget-SoldByMerchantWidget::getName', + 'MerchantWidget-SoldByMerchantWidget::getTemplate', + 'Messenger-InMemoryMessageTray::getFlashMessagesTransfer', + 'Messenger-InMemoryMessageTray::getMessages', + 'Messenger-MessengerFacade::getStoredMessages', + 'MoneyWidget-CurrencyIsoCodeWidget::getCurrencyIsoCode', + 'MoneyWidget-CurrencyIsoCodeWidget::getName', + 'MoneyWidget-CurrencyIsoCodeWidget::getTemplate', + 'MultiCart-MultiCartMessenger::addDefaultQuoteChangedMessage', + 'MultiCartWidget-AddToMultiCartWidget::getName', + 'MultiCartWidget-AddToMultiCartWidget::getTemplate', + 'MultiCartWidget-CartOperationsWidget::getName', + 'MultiCartWidget-MiniCartWidget::getName', + 'MultiCartWidget-MiniCartWidget::getTemplate', + 'MultiCartWidget-MiniCartWidgetDataProvider::getActiveCart', + 'MultiCartWidget-MiniCartWidgetDataProvider::isMultiCartAllowed', + 'MultiCartWidget-MultiCartListWidget::getName', + 'MultiCartWidget-MultiCartMenuItemWidget::getName', + 'MultiCartWidget-MultiCartMenuItemWidget::getTemplate', + 'MultiCartWidget-QuickOrderPageWidget::getName', + 'NewsletterWidget-NewsletterSubscriptionSummaryWidget::getName', + 'NewsletterWidget-NewsletterSubscriptionSummaryWidget::getTemplate', + 'NewsletterWidget-NewsletterSubscriptionWidget::getName', + 'NewsletterWidget-NewsletterSubscriptionWidget::getTemplate', + 'Nopayment-NopaymentCheckoutPreConditionChecker::checkCondition', + 'Nopayment-NopaymentMethodFilter::filterPaymentMethods', + 'Oms-ActiveProcessFetcher::getReservedStatesFromAllActiveProcesses', + 'Oms-Builder::createProcess', + 'Oms-CommandCollection::add', + 'Oms-CommandCollection::get', + 'Oms-ConditionCollection::add', + 'Oms-Event::getCommand', + 'Oms-Event::getName', + 'Oms-Event::getTransitionsBySource', + 'Oms-Event::hasCommand', + 'Oms-Event::hasTimeout', + 'Oms-Event::isOnEnter', + 'Oms-OrderAggregatedItemStateExpander::expandOrdersWithAggregatedItemStates', + 'Oms-OrderExpander::expandOrderWithOmsStates', + 'Oms-OrderExpander::setOrderIsCancellableByItemState', + 'Oms-ProcessCacheReader::getProcess', + 'Oms-ProcessCacheReader::hasProcess', + 'Oms-State::getEvent', + 'Oms-State::getName', + 'Oms-State::getOnEnterEvent', + 'Oms-State::getOutgoingTransitions', + 'Oms-State::getProcess', + 'Oms-State::hasEvent', + 'Oms-State::hasOnEnterEvent', + 'Oms-State::hasTimeoutEvent', + 'Oms-State::isReserved', + 'Oms-Transition::getEvent', + 'Oms-Transition::getSource', + 'Oms-Transition::getTarget', + 'Oms-Transition::hasCondition', + 'Oms-Transition::hasEvent', + 'Oms-TransitionLog::addCommand', + 'Oms-TransitionLog::addSourceState', + 'Oms-TransitionLog::addTargetState', + 'Oms-TransitionLog::setEvent', + 'OrderCancelWidget-OrderCancelButtonWidget::getName', + 'OrderCustomReferenceWidget-OrderCustomReferenceWidget::getName', + 'OrderCustomReferenceWidget-OrderCustomReferenceWidget::getTemplate', + 'Payment-ForeignPayment::confirmPreOrderPayment', + 'Payment-ForeignPayment::initializePayment', + 'Payment-PaymentCalculator::recalculatePayments', + 'Payment-PaymentFacade::confirmPreOrderPayment', + 'Permission-PermissionExecutor::can', + 'Permission-PermissionFinder::findPermissionPlugin', + 'Price-PriceFacade::getDefaultPriceMode', + 'Price-PriceFacade::getGrossPriceModeIdentifier', + 'Price-PriceFacade::getNetPriceModeIdentifier', + 'Price-PriceFacade::validatePriceModeInQuote', + 'PriceCartConnector-ItemComparator::isSameItem', + 'PriceCartConnector-ItemIdentifierBuilder::buildItemIdentifier', + 'PriceCartConnector-PriceProductFilter::createPriceProductFilterTransfer', + 'PriceProduct-CurrencyReaderWithCache::getCurrencyTransferFromIsoCode', + 'PriceProduct-CurrencyReaderWithCache::getCurrencyTransfersFromIsoCodes', + 'PriceProduct-PriceGrouper::groupPriceProduct', + 'PriceProduct-PriceProductCriteriaBuilder::buildCriteriaFromFilter', + 'PriceProduct-PriceProductExpander::expandPriceProductTransfers', + 'PriceProduct-PriceProductFacade::buildCriteriaFromFilter', + 'PriceProduct-PriceProductFacade::getDefaultPriceTypeName', + 'PriceProduct-PriceProductFacade::groupPriceProductCollection', + 'PriceProduct-PriceProductReaderPluginExecutor::executePriceExtractorPluginsForProductAbstract', + 'PriceProduct-PriceProductReaderPluginExecutor::executePriceExtractorPluginsForProductConcrete', + 'PriceProduct-PriceProductTypeReader::handleDefaultPriceType', + 'PriceProduct-PriceProductTypeReader::hasPriceType', + 'PriceProductVolume-PriceProductVolumeFacade::extractPriceProductVolumesForProductAbstract', + 'PriceProductVolume-PriceProductVolumeFacade::extractPriceProductVolumesForProductConcrete', + 'PriceProductVolume-VolumePriceExtractor::extractPriceProductVolumesForProductAbstract', + 'PriceProductVolume-VolumePriceExtractor::extractPriceProductVolumesForProductConcrete', + 'PriceProductVolume-VolumePriceExtractor::extractPriceProductVolumeTransfersFromArray', + 'PriceProductVolumeWidget-CurrentProductPriceVolumeWidget::getName', + 'PriceProductVolumeWidget-CurrentProductPriceVolumeWidget::getTemplate', + 'PriceProductVolumeWidget-PriceProductVolumeResolver::resolveVolumeProductPrices', + 'PriceProductWidget-PriceProductWidget::getName', + 'PriceWidget-PriceModeSwitcherWidget::getName', + 'PriceWidget-PriceModeSwitcherWidget::getTemplate', + 'Product-AbstractProductAbstractManagerSubject::attachAfterCreateObserver', + 'Product-AbstractProductAbstractManagerSubject::attachAfterUpdateObserver', + 'Product-AbstractProductAbstractManagerSubject::attachBeforeCreateObserver', + 'Product-AbstractProductAbstractManagerSubject::attachBeforeUpdateObserver', + 'Product-AbstractProductAbstractManagerSubject::attachReadObserver', + 'Product-AbstractProductConcreteManagerSubject::attachAfterCreateObserver', + 'Product-AbstractProductConcreteManagerSubject::attachAfterUpdateObserver', + 'Product-AbstractProductConcreteManagerSubject::attachBeforeCreateObserver', + 'Product-AbstractProductConcreteManagerSubject::attachBeforeUpdateObserver', + 'Product-AbstractProductConcreteManagerSubject::attachReadObserver', + 'Product-AttributeEncoder::decodeAttributes', + 'Product-AttributeMerger::merge', + 'Product-ProductConcreteNameGenerator::getLocalizedProductConcreteName', + 'Product-ProductFacade::combineRawProductAttributes', + 'Product-ProductFacade::decodeProductAttributes', + 'Product-ProductFacade::findProductConcreteIdsByAbstractProductId', + 'Product-ProductFacade::getLocalizedProductConcreteName', + 'Product-ProductFacade::getRawProductAbstractTransfersByAbstractSkus', + 'Product-ProductFacade::getRawProductConcreteTransfersByConcreteSkus', + 'ProductAlternative-ProductAlternativeFacade::doAllConcreteProductsHaveAlternatives', + 'ProductAlternative-ProductAlternativeFacade::isAlternativeProductApplicable', + 'ProductAlternative-ProductAlternativeReader::doAllConcreteProductsHaveAlternatives', + 'ProductAlternative-ProductAlternativeReader::isAlternativeProductApplicable', + 'ProductAlternativeWidget-ProductAlternativeListWidget::getName', + 'ProductAlternativeWidget-ProductAlternativeListWidget::getTemplate', + 'ProductAlternativeWidget-ShoppingListProductAlternativeWidget::getName', + 'ProductAlternativeWidget-WishlistProductAlternativeWidget::getName', + 'ProductApproval-ProductReader::getProductAbstractTransfersIndexedByIdProductAbstract', + 'ProductApprovalGui-ArrayExpander::insertArrayItemAfterKey', + 'ProductBarcodeWidget-ProductBarcodeWidget::getName', + 'ProductBundle-PriceReaderWithCache::getNetPriceModeIdentifier', + 'ProductBundle-ProductBundleCache::cacheProductForBundleTransfersBySku', + 'ProductBundle-ProductBundleCache::cacheProductForBundleTransfersBySkus', + 'ProductBundle-ProductBundleCache::hasProductForBundleTransfersBySku', + 'ProductBundle-ProductBundleCartActiveCheck::checkActiveItems', + 'ProductBundle-ProductBundleCartChangeObserver::checkBundleItemsChanges', + 'ProductBundle-ProductBundleCartExpander::expandBundleItems', + 'ProductBundle-ProductBundleCartItemGroupKeyExpander::expandExpandBundleItemGroupKey', + 'ProductBundle-ProductBundleCartPostSaveUpdate::updateBundles', + 'ProductBundle-ProductBundleCartPriceChecker::checkCartPrices', + 'ProductBundle-ProductBundleCheckoutAvailabilityCheck::checkCheckoutAvailability', + 'ProductBundle-ProductBundleIdHydrator::hydrate', + 'ProductBundle-ProductBundleImageCartExpander::expandBundleItems', + 'ProductBundle-ProductBundleOrderSaver::saveOrderBundleItems', + 'ProductBundle-ProductBundlePreReloadUpdater::preReloadItems', + 'ProductBundle-ProductBundlePriceCalculation::calculateForCalculableObjectTransfer', + 'ProductBundle-ProductOptionExpander::expandOrderProductBundlesWithProductOptions', + 'ProductBundleWidget-ProductBundleCartItemsListWidget::getName', + 'ProductBundleWidget-ProductBundleCartItemsListWidget::getTemplate', + 'ProductBundleWidget-ProductBundleProductDetailPageItemsListWidget::getName', + 'ProductBundleWidget-ProductBundleProductDetailPageItemsListWidget::getTemplate', + 'ProductCategorySearch-ProductCategorySearchFacade::expandProductPageMapWithCategoryData', + 'ProductCategorySearch-ProductPageMapCategoryExpander::expandProductPageMapWithCategoryData', + 'ProductCategoryWidget-ProductBreadcrumbsWithCategoriesWidget::getName', + 'ProductCategoryWidget-ProductBreadcrumbsWithCategoriesWidget::getTemplate', + 'ProductCategoryWidget-ProductSchemaOrgCategoryWidget::getName', + 'ProductCategoryWidget-ProductSchemaOrgCategoryWidget::getTemplate', + 'ProductConfigurationCart-ProductConfigurationGroupKeyItemExpander::expandProductConfigurationItemsWithGroupKey', + 'ProductConfigurationCart-ProductConfigurationPriceProductExpander::expandPriceProductTransfersWithProductConfigurationPrices', + 'ProductConfigurationCartWidget-ProductConfigurationCartItemDisplayWidget::getName', + 'ProductConfigurationCartWidget-ProductConfigurationCartItemDisplayWidget::getTemplate', + 'ProductConfigurationCartWidget-ProductConfigurationCartPageButtonWidget::getName', + 'ProductConfigurationCartWidget-ProductConfigurationCartPageButtonWidget::getTemplate', + 'ProductConfigurationCartWidget-ProductConfigurationQuoteValidatorWidget::getName', + 'ProductConfigurationCartWidget-ProductConfigurationQuoteValidatorWidget::getTemplate', + 'ProductConfigurationShoppingListWidget-ProductConfigurationShoppingListItemDisplayWidget::getName', + 'ProductConfigurationShoppingListWidget-ProductConfigurationShoppingListPageButtonWidget::getName', + 'ProductConfigurationWidget-ProductConfigurationProductDetailPageButtonWidget::getName', + 'ProductConfigurationWidget-ProductConfigurationProductDetailPageButtonWidget::getTemplate', + 'ProductConfigurationWidget-ProductConfigurationProductViewDisplayWidget::getName', + 'ProductConfigurationWidget-ProductConfigurationProductViewDisplayWidget::getTemplate', + 'ProductConfigurationWishlistWidget-ProductConfigurationWishlistFormWidget::getName', + 'ProductConfigurationWishlistWidget-ProductConfigurationWishlistItemDisplayWidget::getName', + 'ProductConfigurationWishlistWidget-ProductConfigurationWishlistPageButtonWidget::getName', + 'ProductDiscontinued-ProductDiscontinuedFacade::getProductDiscontinuedCollection', + 'ProductDiscontinuedWidget-ProductDiscontinuedNoteWidget::getName', + 'ProductDiscontinuedWidget-ProductDiscontinuedNoteWidget::getTemplate', + 'ProductDiscontinuedWidget-ProductDiscontinuedWidget::getName', + 'ProductDiscountConnector-AttributeProvider::getAllAttributeTypes', + 'ProductDiscountConnector-ProductDiscountConnectorFacade::getAttributeTypes', + 'ProductGroupWidget-ProductGroupColorWidget::getName', + 'ProductGroupWidget-ProductGroupWidget::getName', + 'ProductGroupWidget-ProductGroupWidget::getTemplate', + 'ProductLabel-ProductAbstractRelationReader::findIdsProductAbstractByIdProductLabel', + 'ProductLabel-ProductLabelFacade::findLabelByLabelName', + 'ProductLabel-ProductLabelFacade::findProductAbstractRelationsByIdProductLabel', + 'ProductLabelWidget-ProductAbstractLabelWidget::getName', + 'ProductLabelWidget-ProductAbstractLabelWidget::getTemplate', + 'ProductLabelWidget-ProductConcreteLabelWidget::getName', + 'ProductList-ProductListRestrictionFilter::filterRestrictedProductConcreteSkus', + 'ProductList-ProductListRestrictionValidator::validateItemAddition', + 'ProductList-RestrictedItemsFilter::filterRestrictedItems', + 'ProductMeasurementUnit-CartChangeExpander::expandWithQuantitySalesUnit', + 'ProductMeasurementUnit-CartChangeSalesUnitExpander::expandItemsWithDefaultQuantitySalesUnit', + 'ProductMeasurementUnit-OrderItemExpander::expandOrderItem', + 'ProductMeasurementUnit-ProductMeasurementSalesUnitGroupKeyGenerator::expandItemGroupKey', + 'ProductMeasurementUnit-ProductMeasurementUnitFacade::expandItemGroupKeyWithQuantitySalesUnit', + 'ProductMeasurementUnitWidget-CartProductMeasurementUnitQuantitySelectorWidget::getName', + 'ProductMeasurementUnitWidget-CartProductMeasurementUnitQuantitySelectorWidget::getTemplate', + 'ProductOffer-InactiveProductOfferItemsFilter::filterInactiveProductOfferItems', + 'ProductOffer-ItemProductOfferChecker::checkItemProductOffer', + 'ProductOffer-ProductOfferCartItemQuantityCounter::countCartItemQuantity', + 'ProductOfferSales-OrderItemExpander::expandWithProductOffer', + 'ProductOfferServicePointAvailability-ProductOfferServicePointAvailabilityReader::getItemsAvailabilityForStore', + 'ProductOfferServicePointAvailability-SellableItemRequestFilter::filterSellableItemRequestTransfersWithProductOfferReferenceAndServicePoint', + 'ProductOfferServicePointAvailabilityWidget-ProductOfferServicePointAvailabilityDisplayWidget::getName', + 'ProductOfferServicePointAvailabilityWidget-ProductOfferServicePointAvailabilityWidget::getName', + 'ProductOfferShipmentTypeAvailability-ProductOfferShipmentTypeAvailabilityReader::getItemsAvailabilityForStore', + 'ProductOfferShipmentTypeAvailability-SellableItemRequestFilter::filterSellableItemRequestTransfersWithProductOfferReferenceAndShipmentType', + 'ProductOfferShoppingListWidget-ProductOfferShoppingListWidget::getName', + 'ProductOfferWarehouseAllocationExample-WarehouseAllocator::allocateSalesOrderWarehouse', + 'ProductOfferWidget-ShoppingListProductOfferWidget::getName', + 'ProductOption-ProductOptionGroupIdHydrator::hydrateProductOptionGroupIds', + 'ProductOption-ProductOptionOrderSaver::saveOrderProductOptions', + 'ProductOption-ProductOptionOrderSaver::saveOrderProductOptionsTransaction', + 'ProductOptionCartConnector-GroupKeyExpander::expand', + 'ProductOptionCartConnector-ProductOptionCartQuantity::changeQuantity', + 'ProductOptionCartConnector-ProductOptionValidator::checkProductOptionExistence', + 'ProductOptionCartConnector-ProductOptionValueExpander::expandProductOptions', + 'ProductOptionCartConnector-ProductOptionValuePriceValidator::validateProductOptionValuePrices', + 'ProductOptionWidget-ProductOptionConfiguratorWidget::getName', + 'ProductOptionWidget-ProductOptionConfiguratorWidget::getTemplate', + 'ProductPackagingUnit-AmountGroupKeyItemExpander::expandCartWithAmountGroupKey', + 'ProductPackagingUnit-AmountSalesUnitItemExpander::expandCartWithAmountSalesUnit', + 'ProductPackagingUnit-OrderItemExpander::expandSalesOrderItemWithAmountAndAmountSku', + 'ProductPackagingUnit-OrderItemExpander::expandSalesOrderItemWithAmountSalesUnit', + 'ProductPackagingUnit-PriceChangeExpander::setCustomAmountPrice', + 'ProductPackagingUnit-ProductPackagingUnitAmountRestrictionValidator::validateItemAddition', + 'ProductPackagingUnit-ProductPackagingUnitAmountSalesUnitValue::calculateAmountSalesUnitValueInQuote', + 'ProductPackagingUnit-ProductPackagingUnitCartPreCheck::checkCartAvailability', + 'ProductPackagingUnit-ProductPackagingUnitCheckoutPreCheck::checkoutAvailabilityPreCheck', + 'ProductPackagingUnit-ProductPackagingUnitFacade::expandSalesOrderItemWithAmountSalesUnit', + 'ProductPackagingUnit-ProductPackagingUnitGroupKeyGenerator::getItemWithGroupKey', + 'ProductPackagingUnit-ProductPackagingUnitItemExpander::expandCartChangeWithProductPackagingUnit', + 'ProductPackagingUnit-ProductPackagingUnitItemQuantityValidator::isProductPackagingUnitItemQuantitySplittable', + 'ProductPackagingUnitWidget-ProductPackagingUnitWidget::getName', + 'ProductPackagingUnitWidget-ProductPackagingUnitWidget::getTemplate', + 'ProductPageSearch-PageMapBuilder::add', + 'ProductPageSearch-PageMapBuilder::addCategory', + 'ProductPageSearch-PageMapBuilder::addCompletionTerms', + 'ProductPageSearch-PageMapBuilder::addFullText', + 'ProductPageSearch-PageMapBuilder::addFullTextBoosted', + 'ProductPageSearch-PageMapBuilder::addIntegerFacet', + 'ProductPageSearch-PageMapBuilder::addIntegerSort', + 'ProductPageSearch-PageMapBuilder::addSearchResultData', + 'ProductPageSearch-PageMapBuilder::addStringFacet', + 'ProductPageSearch-PageMapBuilder::addStringSort', + 'ProductPageSearch-PageMapBuilder::addSuggestionTerms', + 'ProductQuantity-CartChangeTransferNormalizerPreChecker::hasNormalizableItems', + 'ProductRelationWidget-SimilarProductsWidget::getName', + 'ProductRelationWidget-SimilarProductsWidget::getTemplate', + 'ProductRelationWidget-UpSellingProductsWidget::getName', + 'ProductRelationWidget-UpSellingProductsWidget::getTemplate', + 'ProductReplacementForWidget-ProductReplacementForListWidget::getName', + 'ProductReplacementForWidget-ProductReplacementForListWidget::getTemplate', + 'ProductReviewWidget-DisplayProductAbstractReviewWidget::getName', + 'ProductReviewWidget-DisplayProductAbstractReviewWidget::getTemplate', + 'ProductReviewWidget-ProductDetailPageReviewWidget::getName', + 'ProductReviewWidget-ProductDetailPageReviewWidget::getTemplate', + 'ProductReviewWidget-ProductRatingFilterWidget::getName', + 'ProductReviewWidget-ProductRatingFilterWidget::getTemplate', + 'ProductReviewWidget-ProductReviewDisplayWidget::getName', + 'ProductReviewWidget-ProductReviewDisplayWidget::getTemplate', + 'ProductSearchWidget-ProductConcreteAddWidget::getName', + 'ProductSearchWidget-ProductConcreteAddWidget::getTemplate', + 'ProductSearchWidget-ProductConcreteSearchGridWidget::getName', + 'ProductSearchWidget-ProductConcreteSearchWidget::getName', + 'ProductSearchWidget-ProductConcreteSearchWidget::getTemplate', + 'ProductWidget-CatalogPageProductWidget::getName', + 'ProductWidget-CatalogPageProductWidget::getTemplate', + 'ProductWidget-CmsProductGroupWidget::getName', + 'ProductWidget-CmsProductGroupWidget::getTemplate', + 'ProductWidget-CmsProductWidget::getName', + 'ProductWidget-PdpProductRelationWidget::getName', + 'ProductWidget-PdpProductRelationWidget::getTemplate', + 'ProductWidget-PdpProductReplacementForListWidget::getName', + 'ProductWidget-ProductAlternativeWidget::getName', + 'PushNotification-PushNotificationSubscriptionDeliveryLogExtractor::extractDeliveryLogs', + 'PushNotificationWebPushPhp-PushNotificationFilter::filterPushNotificationCollectionByProviderName', + 'PushNotificationWebPushPhp-PushNotificationSender::sendNotifications', + 'PushNotificationWebPushPhp-WebPush::flush', + 'PushNotificationWebPushPhp-WebPushQueueCreator::queuePushNotifications', + 'Quote-QuoteFacade::getQuoteCollection', + 'Quote-QuoteFacade::isQuoteLocked', + 'Quote-QuoteLockStatusValidator::isQuoteLocked', + 'QuoteApproval-QuoteApprovalFacade::getQuoteApprovalsByIdQuote', + 'QuoteApproval-QuoteApprovalFacade::isQuoteInApprovalProcess', + 'QuoteApproval-QuoteStatusCalculator::calculateQuoteStatus', + 'QuoteApprovalShipmentConnector-ShipmentQuoteFieldProvider::getQuoteFieldsAllowedForSaving', + 'QuoteApprovalWidget-QuoteApprovalStatusWidget::getName', + 'QuoteApprovalWidget-QuoteApprovalStatusWidget::getTemplate', + 'QuoteApprovalWidget-QuoteApprovalWidget::getName', + 'QuoteApprovalWidget-QuoteApprovalWidget::getTemplate', + 'QuoteApprovalWidget-QuoteApproveRequestWidget::getName', + 'QuoteApprovalWidget-QuoteApproveRequestWidget::getTemplate', + 'QuoteRequest-QuoteRequestTerminator::closeQuoteRequest', + 'QuoteRequest-QuoteRequestTimeValidator::checkValidUntil', + 'QuoteRequestAgentWidget-QuoteRequestAgentCancelWidget::getName', + 'QuoteRequestAgentWidget-QuoteRequestAgentOverviewWidget::getName', + 'QuoteRequestWidget-QuoteRequestActionsWidget::getName', + 'QuoteRequestWidget-QuoteRequestActionsWidget::getTemplate', + 'QuoteRequestWidget-QuoteRequestCancelWidget::getName', + 'QuoteRequestWidget-QuoteRequestCartWidget::getName', + 'QuoteRequestWidget-QuoteRequestCartWidget::getTemplate', + 'QuoteRequestWidget-QuoteRequestCreateWidget::getName', + 'QuoteRequestWidget-QuoteRequestCreateWidget::getTemplate', + 'QuoteRequestWidget-QuoteRequestMenuItemWidget::getName', + 'QuoteRequestWidget-QuoteRequestMenuItemWidget::getTemplate', + 'Sales-DuplicateOrderChecker::checkDuplicateOrder', + 'Sales-OrderStateMachineResolver::resolve', + 'SalesConfigurableBundle-ConfigurableBundleItemTransformer::transformConfiguredBundleOrderItems', + 'SalesConfigurableBundle-SalesOrderConfiguredBundleWriter::saveSalesOrderConfiguredBundlesFromQuote', + 'SalesConfigurableBundleWidget-OrderItemsConfiguredBundleWidget::getName', + 'SalesMerchantCommission-MerchantCommissionCalculator::recalculateMerchantCommissions', + 'SalesMerchantCommission-MerchantCommissionQuoteSanitizer::sanitizeMerchantCommissionFromQuote', + 'SalesOms-OrderItemExpander::expandOrderItemWithReference', + 'SalesOrderThreshold-ExpenseRemover::removeSalesOrderThresholdExpenses', + 'SalesOrderThreshold-ExpenseSaver::saveSalesOrderSalesOrderThresholdExpense', + 'SalesOrderThreshold-SalesOrderThresholdDataSourceStrategyResolver::findApplicableThresholds', + 'SalesOrderThreshold-SalesOrderThresholdFacade::getSalesOrderThresholds', + 'SalesOrderThreshold-SalesOrderThresholdReader::getSalesOrderThresholds', + 'SalesOrderThreshold-SalesOrderThresholdStrategyResolver::resolveSalesOrderThresholdStrategy', + 'SalesOrderThreshold-ThresholdMessenger::addSalesOrderThresholdMessages', + 'SalesOrderThresholdWidget-SalesOrderThresholdWidget::getName', + 'SalesOrderThresholdWidget-SalesOrderThresholdWidget::getTemplate', + 'SalesProductBundleWidget-OrderItemsProductBundleWidget::getName', + 'SalesProductConfiguration-SalesOrderItemConfigurationWriter::saveSalesOrderItemConfigurationsFromQuote', + 'SalesProductConfigurationWidget-ProductConfigurationOrderItemDisplayWidget::getName', + 'SalesProductConnector-OrderExpander::expandOrdersWithMetadata', + 'SalesQuantity-ItemQuantityValidator::isItemQuantitySplittable', + 'SalesQuantity-SalesQuantityFacade::isItemQuantitySplittable', + 'SalesReturn-OrderRemunerationTotalExpander::expandOrderTotalsWithRemunerationTotal', + 'SalesServicePointWidget-SalesServicePointNameForShipmentGroupWidget::getName', + 'SalesShipmentType-SalesShipmentTypeGrouper::getSalesShipmentTypeTransfersGroupedByKey', + 'SalesShipmentType-SalesShipmentTypeGrouper::getSalesShipmentTypeTransfersIndexedByName', + 'SecurityBlockerPage-SecurityBlockerAgentEventSubscriber::getSubscribedEvents', + 'SecurityBlockerPage-SecurityBlockerAgentEventSubscriber::onKernelRequest', + 'SecurityBlockerPage-SecurityBlockerCustomerEventSubscriber::getSubscribedEvents', + 'SecurityBlockerPage-SecurityBlockerCustomerEventSubscriber::onKernelRequest', + 'SequenceNumber-RandomNumberGenerator::generate', + 'ServicePointCart-QuoteItemServicePointValidator::validate', + 'ServicePointWidget-AddressFormChecker::hasShipmentTypes', + 'ServicePointWidget-AddressFormChecker::isApplicableForServicePointAddressStepFormHydration', + 'ServicePointWidget-AddressFormChecker::isBillingAddressTheSameAsShipping', + 'ServicePointWidget-AddressFormChecker::isDeliverToMultipleAddresses', + 'ServicePointWidget-AddressFormChecker::isShipmentTypeDelivery', + 'ServicePointWidget-ServicePointAddressExpander::expandShipmentsWithServicePointAddress', + 'ServicePointWidget-ServicePointFormPreSetDataHydrator::hydrate', + 'ServicePointWidget-ServicePointFormSubmitDataHydrator::hydrate', + 'ServicePointWidget-ServicePointFormValidator::validateSubmittedData', + 'ServicePointWidget-ServicePointNameForShipmentGroupWidget::getName', + 'ServicePointWidget-ServicePointNameForShipmentGroupWidget::getTemplate', + 'ServicePointWidget-ServicePointSearchWidget::getName', + 'SessionAgentValidation-SaveAgentSessionEventSubscriber::getSubscribedEvents', + 'SessionAgentValidation-SaveAgentSessionEventSubscriber::onLoginSuccess', + 'SessionAgentValidation-SecurityAuthenticationListenerFactoryTypeExpander::expand', + 'SessionAgentValidation-SessionAgentValidationSecurityExtender::extend', + 'SessionAgentValidation-SessionAgentValidationSessionUpdater::update', + 'SessionCustomerValidationPage-SaveCustomerSessionEventSubscriber::getSubscribedEvents', + 'SessionCustomerValidationPage-SessionCustomerValidationSecurityExtender::extend', + 'SharedCart-CustomerShareCartQuoteResponseExpander::expand', + 'SharedCart-QuoteActivator::setDefaultQuote', + 'SharedCart-QuoteCompanyUserWriter::updateQuoteCompanyUsers', + 'SharedCart-QuoteReader::findSharedQuoteCollectionBySharedQuoteCriteriaFilter', + 'SharedCart-QuoteShareDetailsQuoteResponseExpander::expand', + 'SharedCart-QuoteShareDetailsReader::getSharedCartDetails', + 'SharedCart-QuoteShareDetailsReader::getShareDetailsByIdQuote', + 'SharedCart-SharedCartFacade::getSharedCartDetails', + 'SharedCart-SharedCartFacade::getShareDetailsByIdQuote', + 'SharedCart-SharedCartMessenger::addDefaultSharedQuoteChangedMessage', + 'SharedCartWidget-CartDeleteSharingCompanyUsersListWidget::getName', + 'Shipment-ExpenseSanitizer::sanitizeExpenseSumValues', + 'Shipment-MethodAvailabilityChecker::isShipmentMethodAvailableForShipmentGroup', + 'Shipment-MethodDeliveryTimeReader::getDeliveryTimeForShippingGroup', + 'Shipment-MethodPriceReader::findShipmentGroupShippingPrice', + 'Shipment-MultiShipmentExpenseFilter::filterObsoleteShipmentExpenses', + 'Shipment-ShipmentExpenseCollectionRemover::removeExpenseByShipmentHash', + 'Shipment-ShipmentExpenseFilter::filterObsoleteShipmentExpenses', + 'Shipment-ShipmentTaxRateCalculator::recalculateByCalculableObject', + 'Shipment-ShipmentTotalCalculator::calculateShipmentTotal', + 'ShipmentCartConnector-ShipmentCartExpander::updateShipmentPrice', + 'ShipmentCartConnector-ShipmentCartValidator::validateShipment', + 'ShipmentCartConnector-ShipmentSanitizer::clearShipmentMethod', + 'ShipmentDiscountConnector-MethodDiscountDecisionRule::isExpenseSatisfiedBy', + 'ShipmentDiscountConnector-MultiShipmentCollectorStrategyResolver::resolveByTypeAndItems', + 'ShipmentDiscountConnector-ShipmentDiscountCollector::collect', + 'ShipmentDiscountConnector-ShipmentDiscountConnectorFacade::collectDiscountByShipmentMethod', + 'ShipmentType-ShipmentTypeFacade::getShipmentTypeCollection', + 'ShipmentType-ShipmentTypeReader::getShipmentTypeCollection', + 'ShipmentType-ShipmentTypeStoreRelationshipExpander::expandShipmentTypeCollectionWithStoreRelationships', + 'ShipmentTypeCart-ShipmentTypeCartFacade::expandCartChangeItemsWithShipmentType', + 'ShipmentTypeCart-ShipmentTypeCartFacade::expandQuoteItemsWithShipmentType', + 'ShipmentTypeCart-ShipmentTypeExpander::expandCartChangeItemsWithShipmentType', + 'ShipmentTypeCart-ShipmentTypeExpander::expandQuoteItemsWithShipmentType', + 'ShipmentTypeCart-ShipmentTypeReader::getActiveShipmentTypeCollection', + 'ShipmentTypeCart-ShipmentTypesHaveRelationWithShipmentMethodsCheckoutValidationRule::isQuoteReadyForCheckout', + 'ShipmentTypeWidget-AddressFormChecker::isApplicableForShipmentTypeAddressStepFormHydration', + 'ShipmentTypeWidget-AddressFormChecker::isDeliverToMultipleAddresses', + 'ShipmentTypeWidget-QuoteCleaner::cleanShipmentTypeUuidFromQuoteItems', + 'ShipmentTypeWidget-QuoteExpander::expandQuoteItemsWithShipmentType', + 'ShipmentTypeWidget-ShipmentTypeAddressFormWidget::getName', + 'ShipmentTypeWidget-ShipmentTypeAddressFormWidget::getTemplate', + 'ShipmentTypeWidget-ShipmentTypeFormOptionExpander::configureOptions', + 'ShipmentTypeWidget-ShipmentTypeFormPreSetDataHydrator::hydrate', + 'ShipmentTypeWidget-ShipmentTypeFormSubmitDataHydrator::hydrate', + 'ShopApplication-AbstractController::initialize', + 'ShopApplication-ShopApplicationTwigEventSubscriber::getSubscribedEvents', + 'ShoppingListNoteWidget-ShoppingListItemNoteWidget::getName', + 'ShoppingListPage-ShoppingListDismissWidget::getName', + 'ShoppingListWidget-AddItemsToShoppingListWidget::getName', + 'ShoppingListWidget-AddToShoppingListWidget::getName', + 'ShoppingListWidget-CreateShoppingListFromCartWidget::getName', + 'ShoppingListWidget-CreateShoppingListFromCartWidget::getTemplate', + 'ShoppingListWidget-ShoppingListMenuItemWidget::getName', + 'ShoppingListWidget-ShoppingListMenuItemWidget::getTemplate', + 'ShoppingListWidget-ShoppingListNavigationMenuWidget::getName', + 'ShoppingListWidget-ShoppingListNavigationMenuWidget::getTemplate', + 'ShoppingListWidget-ShoppingListSubtotalWidget::getName', + 'ShopUi-NumberFormatterTwigExtender::extend', + 'StorageRouter-StorageUrlGenerator::generate', + 'StorageRouter-StorageUrlGenerator::getContext', + 'StorageRouter-StorageUrlGenerator::setContext', + 'StoreWidget-StoreSwitcherWidget::getName', + 'StoreWidget-StoreSwitcherWidget::getTemplate', + 'Synchronization-InMemoryMessageSynchronizer::addSynchronizationMessage', + 'Synchronization-InMemoryMessageSynchronizer::flushSynchronizationMessages', + 'Synchronization-SynchronizationFacade::addSynchronizationMessageToBuffer', + 'TabsWidget-FullTextSearchTabsWidget::getName', + 'Tax-AccruedTaxCalculator::getTaxValueFromPrice', + 'Tax-PriceCalculationHelper::getTaxValueFromPrice', + 'Tax-TaxAmountAfterCancellationCalculator::recalculate', + 'Tax-TaxAmountCalculator::recalculate', + 'Tax-TaxFacade::calculateTaxRateAverageAggregation', + 'Tax-TaxRateAverageAggregator::recalculate', + 'User-SecurityServiceExtender::extend', + 'User-UserFacade::getCurrentUser', + 'User-UserFacade::hasCurrentUser', + 'User-UserFacade::isSystemUser', + 'WishlistWidget-WishlistMenuItemWidget::getName', + 'WishlistWidget-WishlistMenuItemWidget::getTemplate', + 'ZedRequest-AbstractObject::fromArray', + 'ZedRequest-AbstractObject::toArray', + 'ZedRequest-AbstractRequest::addMetaTransfer', + 'ZedRequest-AbstractRequest::getMetaTransfer', + 'ZedRequest-AbstractRequest::getTransfer', + 'ZedRequest-AbstractRequest::setHost', + 'ZedRequest-AbstractRequest::setSessionId', + 'ZedRequest-AbstractRequest::setTime', + 'ZedRequest-AbstractRequest::setTransfer', + 'ZedRequest-AbstractResponse::addErrorMessages', + 'ZedRequest-AbstractResponse::addInfoMessage', + 'ZedRequest-AbstractResponse::addInfoMessages', + 'ZedRequest-AbstractResponse::addSuccessMessage', + 'ZedRequest-AbstractResponse::addSuccessMessages', + 'ZedRequest-AbstractResponse::fromArray', + 'ZedRequest-AbstractResponse::getErrorMessages', + 'ZedRequest-AbstractResponse::getInfoMessages', + 'ZedRequest-AbstractResponse::getSuccessMessages', + 'ZedRequest-AbstractResponse::getTransfer', + 'ZedRequest-AbstractResponse::setSuccess', + 'ZedRequest-AbstractZedClient::addMetaTransfer', + 'ZedRequest-AbstractZedClient::getErrorStatusMessages', + 'ZedRequest-AbstractZedClient::getInfoStatusMessages', + 'ZedRequest-AbstractZedClient::getLastResponse', + 'ZedRequest-AbstractZedClient::getSuccessStatusMessages', + 'ZedRequest-AbstractZedClient::hasLastResponse', + 'ZedRequest-HandlerStackContainer::getHandlerStack', + 'ZedRequest-LoggableZedClient::addMetaTransfer', + 'ZedRequest-LoggableZedClient::getErrorStatusMessages', + 'ZedRequest-LoggableZedClient::getInfoStatusMessages', + 'ZedRequest-LoggableZedClient::getLastResponse', + 'ZedRequest-LoggableZedClient::getSuccessStatusMessages', + 'ZedRequest-LoggableZedClient::hasLastResponse', + 'ZedRequest-ZedRequestInMemoryLogger::log', + ]; + } + /** * Specification: * - Returns the list of paths that should be instrumented. From 114e503423c49f2f0a194003045ede262b3c6eef Mon Sep 17 00:00:00 2001 From: gechetspr Date: Mon, 2 Dec 2024 19:11:59 +0200 Subject: [PATCH 36/48] Test sampler based on random --- .../CriticalSpanTraceIdRatioSampler.php | 61 +++++-- .../TraceStateAwareSamplerInterface.php | 4 +- .../Instrumentation/Span/SpanBuilder.php | 3 +- .../SprykerInstrumentationBootstrap.php | 5 +- .../OpentelemetryInstrumentationConfig.php | 4 +- .../Business/Generator/HookGenerator.php | 6 +- .../Zed/Opentelemetry/OpentelemetryConfig.php | 164 +++++++++++++++++- 7 files changed, 225 insertions(+), 22 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index af22393..2943915 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -8,6 +8,7 @@ namespace Spryker\Service\Opentelemetry\Instrumentation\Sampler; use InvalidArgumentException; +use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\TraceStateInterface; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; @@ -28,16 +29,19 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, TraceStateAwa protected float $probability; /** - * @var \OpenTelemetry\API\Trace\TraceStateInterface|null + * @var float */ - protected ?TraceStateInterface $traceState = null; + protected float $criticalProbability; + + protected ?SpanInterface $parentSpan = null; /** * @param float $probability */ - public function __construct(float $probability) + public function __construct(float $probability, float $criticalProbability) { $this->setProbability($probability); + $this->setCriticalProbability($criticalProbability); } /** @@ -58,27 +62,36 @@ public function shouldSample( AttributesInterface $attributes, array $links, ): SamplingResult { + if (!$this->parentSpan->getContext()->isValid()) { + return new SamplingResult(SamplingResult::RECORD_AND_SAMPLE, [], $this->parentSpan->getContext()->getTraceState()); + } $probability = $this->probability; if ($attributes->has(static::IS_CRITICAL_ATTRIBUTE)) { - $probability = OpentelemetryInstrumentationConfig::getSamplerProbabilityForCriticalSpans(); + $probability = $this->criticalProbability; } - $traceIdLimit = (1 << 60) - 1; - $lowerOrderBytes = hexdec(substr($traceId, strlen($traceId) - 15, 15)); - $traceIdCondition = $lowerOrderBytes < round($probability * $traceIdLimit); +// $traceIdLimit = (1 << 60) - 1; +// $lowerOrderBytes = hexdec(substr($traceId, strlen($traceId) - 15, 15)); +// $traceIdCondition = $lowerOrderBytes < round($probability * $traceIdLimit); +// if (!$traceIdCondition && $spanName !== 'Backoffice GET http://backoffice.de.spryker.local/') { +// var_dump($traceId,$traceIdCondition, $lowerOrderBytes, round($probability * $traceIdLimit), $traceIdLimit, $spanName);die; +// } + + $traceIdCondition = (mt_rand() / mt_getrandmax()) <= $probability; + //var_dump($traceIdCondition, $probability);die; $decision = $traceIdCondition ? SamplingResult::RECORD_AND_SAMPLE : SamplingResult::DROP; - return new SamplingResult($decision, [], $this->traceState); + return new SamplingResult($decision, [], $this->parentSpan->getContext()->getTraceState()); } /** - * @param \OpenTelemetry\API\Trace\TraceStateInterface|null $traceState + * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan * * @return void */ - public function addTraceState(?TraceStateInterface $traceState): void + public function addParentSpan(SpanInterface $parentSpan): void { - $this->traceState = $traceState; + $this->parentSpan = $parentSpan; } /** @@ -95,11 +108,33 @@ public function getDescription(): string * @return void */ protected function setProbability(float $probability): void + { + $this->validateProbability($probability); + + $this->probability = $probability; + } + + /** + * @param float $probability + * + * @return void + */ + protected function setCriticalProbability(float $probability): void + { + $this->validateProbability($probability); + + $this->criticalProbability = $probability; + } + + /** + * @param float $probability + * + * @return void + */ + protected function validateProbability(float $probability): void { if ($probability < 0.0 || $probability > 1.0) { throw new InvalidArgumentException('probability should be be between 0.0 and 1.0.'); } - - $this->probability = $probability; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php index df6c8cd..0a3d0a7 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php @@ -13,9 +13,9 @@ interface TraceStateAwareSamplerInterface { /** - * @param \OpenTelemetry\API\Trace\TraceStateInterface|null $span + * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan * * @return void */ - public function addTraceState(?TraceStateInterface $span): void; + public function addParentSpan(SpanInterface $parentSpan): void; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 22ed3af..9236206 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -187,6 +187,7 @@ public function startSpan(): SpanInterface ); if (!in_array($samplingDecision, [SamplingResult::RECORD_AND_SAMPLE, SamplingResult::RECORD_ONLY], true)) { + //var_dump($this->spanName);die; return Span::wrap($spanContext); } @@ -221,7 +222,7 @@ protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface ->getSampler(); if ($sampler instanceof TraceStateAwareSamplerInterface) { - $sampler->addTraceState($parentSpan->getContext()->getTraceState());; + $sampler->addParentSpan($parentSpan);; } return $sampler diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 057c33a..269c050 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -154,7 +154,7 @@ protected static function createSpanProcessor(): SpanProcessorInterface */ protected static function createSampler(): SamplerInterface { - return new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability()); + return new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability(), OpentelemetryInstrumentationConfig::getSamplerProbabilityForCriticalSpans()); //return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability())); } @@ -208,7 +208,8 @@ protected static function registerRootSpan(string $servicedName, Request $reques ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) - ->setAttribute('FULL_TRACE', !TraceSampleResult::shouldSkipTraceBody()) + ->setAttribute('is_full_trace', !TraceSampleResult::shouldSkipTraceBody()) + ->setAttribute('method', $request->getMethod()) ->startSpan(); Context::storage()->attach($span->storeInContext($parent)); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index ccceb5d..3ec0fb6 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -185,7 +185,7 @@ public static function getSamplerProbability(): float */ public static function getSamplerProbabilityForCriticalSpans(): float { - $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.5; + $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.9; return (float)$probability; } @@ -234,7 +234,7 @@ public static function getSpanProcessorMaxBatchSize(): int */ public static function getTraceSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 1.0; + $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.7; return (float)$probability; } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php index c07d63f..dba4d76 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php @@ -89,7 +89,11 @@ public function generate(): void $this->ensureDirectoryExists(); if (!file_exists($this->getOutputFilepathByModule($class))) { - $content = 'getOutputFilepathByModule($class), 'a'); diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 9509370..0bc6393 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -28,7 +28,6 @@ public function getExcludedDirs(): array 'OpenTelemetry', 'Dependency', 'Acl', - 'Form', 'Gui', 'GracefulRunner', 'AclEntity', @@ -132,13 +131,16 @@ public function getExcludedSpans(): array 'AssetWidget-AssetWidget::getName', 'AssetWidget-AssetWidget::getTemplate', 'AssetWidget-AssetWidgetDataProvider::getSlotContent', + 'AvailabilityNotification-AvailabilityNotificationSubscriber::getSubscribedEvents', 'AvailabilityNotification-AvailabilityNotificationSubscriptionReader::getAvailabilityNotifications', 'AvailabilityNotification-CustomerExpander::expandCustomerTransferWithAvailabilityNotificationSubscriptionList', 'AvailabilityNotificationWidget-AvailabilityNotificationSubscriptionWidget::getName', + 'AvailabilityStorage-AvailabilityStorageEventSubscriber::getSubscribedEvents', 'BarcodeWidget-BarcodeWidget::getName', 'BusinessOnBehalf-BusinessOnBehalfFacade::setDefaultCompanyUserToCustomer', 'BusinessOnBehalf-CustomerExpander::expandCustomer', 'BusinessOnBehalf-CustomerHydrator::hydrateCustomerWithCompanyUser', + 'BusinessOnBehalfGui-CustomerTableButtonCreator::addAttachCustomerToCompanyButton', 'BusinessOnBehalfWidget-BusinessOnBehalfStatusWidget::getName', 'BusinessOnBehalfWidget-BusinessOnBehalfStatusWidget::getTemplate', 'Cart-CartFacade::cleanUpItems', @@ -173,6 +175,7 @@ public function getExcludedSpans(): array 'CategoryDiscountConnector-CategoryReader::getCategoryKeysGroupedByIdCategoryNode', 'CategoryDiscountConnector-DiscountableItemReader::getDiscountableItemsByCategory', 'CategoryDiscountConnector-ProductCategoryReader::getProductCategoriesGroupedByIdProductAbstract', + 'CategoryImageStorage-CategoryImageStorageEventSubscriber::getSubscribedEvents', 'CategoryImageStorageWidget-CategoryImageStorageWidget::getName', 'CheckoutPage-AbstractBaseStep::execute', 'CheckoutPage-AbstractBaseStep::preCondition', @@ -200,13 +203,23 @@ public function getExcludedSpans(): array 'Cms-CmsPageUrlBuilder::getPageUrlPrefix', 'Cms-TemplateContentReader::getTemplateContent', 'Cms-TemplatePlaceholderParser::getTemplatePlaceholders', + 'CmsBlockCategoryStorage-CmsBlockCategoryStorageEventSubscriber::getSubscribedEvents', + 'CmsBlockProductStorage-CmsBlockProductStorageEventSubscriber::getSubscribedEvents', + 'CmsBlockStorage-CmsBlockStorageEventSubscriber::getSubscribedEvents', 'CmsBlockWidget-CmsBlockValidator::isValid', 'CmsContentWidgetProductConnector-CmsProductGroupContentWidgetConfigurationProvider::getAvailableTemplates', 'CmsContentWidgetProductConnector-CmsProductGroupContentWidgetConfigurationProvider::getFunctionName', + 'CmsPageSearch-CmsPageSearchEventSubscriber::getSubscribedEvents', + 'CmsSlotBlockStorage-CmsSlotBlockStorageEventSubscriber::getSubscribedEvents', 'CmsSlotBlockWidget-CmsSlotBlockWidgetDataProvider::getSlotContent', + 'CmsSlotStorage-CmsSlotStorageEventSubscriber::getSubscribedEvents', 'Comment-CommentFacade::findCommentThreadByOwner', + 'Comment-CommentFacade::getCommentThreads', 'Comment-CommentThreadReader::findCommentThreadByOwner', 'Comment-CommentThreadReader::getCommentThreads', + 'CommentMerchantRelationshipConnector-CommentMerchantRelationshipConnectorFacade::expandMerchantRelationshipCollectionWithCommentThread', + 'CommentMerchantRelationshipConnector-CommentReader::getCommentThreadsIndexedByOwnerId', + 'CommentMerchantRelationshipConnector-CommentThreadExpander::expandMerchantRelationshipCollection', 'CommentWidget-CommentThreadExpander::expandCommentsWithPlainTags', 'CommentWidget-CommentThreadPreparer::prepareTaggedComments', 'CommentWidget-CommentThreadWidget::getName', @@ -226,9 +239,14 @@ public function getExcludedSpans(): array 'CompanySalesConnector-FilterFieldChecker::isFilterFieldSet', 'CompanySalesConnector-OrderWriter::updateOrderCompanyUuid', 'CompanyUnitAddress-CompanyBusinessUnitAddressReader::getCompanyBusinessUnitAddressesByCriteriaFilter', + 'CompanyUnitAddress-CompanyBusinessUnitAddressReader::getCompanyUnitAddressCollectionByCompanyBusinessUnitIds', + 'CompanyUnitAddress-CompanyUnitAddressFacade::expandMerchantRelationshipCollectionWithCompanyUnitAddress', 'CompanyUnitAddress-CompanyUnitAddressFacade::getCompanyUnitAddressCollection', + 'CompanyUnitAddress-MerchantRelationshipExpander::expandMerchantRelationshipCollectionWithCompanyUnitAddress', + 'CompanyUser-CompanyUserFacade::countActiveCompanyUsersByIdCustomer', 'CompanyUser-CompanyUserFacade::expandCustomerWithIsActiveCompanyUserExists', 'CompanyUser-CustomerExpander::expandCustomerWithIsActiveCompanyUserExists', + 'CompanyUserGui-CompanyUserGuiButtonCreator::addAttachCustomerButton', 'CompanyWidget-AddressProvider::companyBusinessUnitAddressesExists', 'CompanyWidget-AddressProvider::findCurrentCompanyBusinessUnitAddress', 'CompanyWidget-AddressProvider::getIndexedCompanyBusinessUnitAddressList', @@ -247,15 +265,20 @@ public function getExcludedSpans(): array 'ConfigurableBundleCart-ConfiguredBundleQuantityUpdater::updateConfiguredBundleQuantityPerSlot', 'ConfigurableBundleCart-ConfiguredBundleTemplateSlotChecker::checkConfiguredBundleTemplateSlotCombination', 'ConfigurableBundleNoteWidget-ConfiguredBundleNoteWidget::getName', + 'ConfigurableBundlePageSearch-ConfigurableBundleTemplateImagePageSearchEventSubscriber::getSubscribedEvents', + 'ConfigurableBundlePageSearch-ConfigurableBundleTemplatePageSearchEventSubscriber::getSubscribedEvents', 'ConfigurableBundleWidget-ConfiguredBundleGrouper::getConfiguredBundles', 'ConfigurableBundleWidget-QuoteConfiguredBundleWidget::getName', 'ConfigurableBundleWidget-QuoteConfiguredBundleWidget::getTemplate', 'ContentGui-ContentResolver::getTermKeys', + 'ContentStorage-ContentStorageEventSubscriber::getSubscribedEvents', 'Currency-CurrencyBuilder::fromIsoCode', 'Currency-CurrencyBuilder::getCurrent', 'Currency-CurrencyFacade::fromIsoCode', + 'Currency-CurrencyFacade::getAllStoresWithCurrencies', 'Currency-CurrencyFacade::getByIdCurrency', 'Currency-CurrencyFacade::validateCurrencyInQuote', + 'Currency-CurrencyReader::getAllStoresWithCurrencies', 'Currency-CurrencyReader::getByIdCurrency', 'Currency-CurrencyReader::getByIsoCode', 'Currency-QuoteValidator::validate', @@ -266,12 +289,14 @@ public function getExcludedSpans(): array 'Customer-CustomerFacade::validateCustomerAddressCheckoutSalutation', 'Customer-CustomerOrderHydrator::hydrateOrderTransfer', 'Customer-CustomerOrderSaver::saveOrderCustomer', + 'Customer-CustomerTableExpanderPluginExecutor::executeActionExpanderPlugins', 'Customer-DenyListCustomerPasswordPolicy::validatePassword', 'Customer-LengthCustomerPasswordPolicy::validatePassword', 'Customer-PreConditionChecker::checkPreConditions', 'Customer-SequenceCustomerPasswordPolicy::validatePassword', 'CustomerPage-AddressChoicesResolver::getAddressChoices', 'CustomerPage-CustomerAddressExpander::expandWithCustomerAddress', + 'CustomerPage-CustomerLoginFormAuthenticator::authenticate', 'CustomerPage-CustomerLoginFormAuthenticator::supports', 'CustomerPage-CustomerNavigationWidget::getName', 'CustomerPage-CustomerNavigationWidget::getTemplate', @@ -280,6 +305,7 @@ public function getExcludedSpans(): array 'CustomerPage-CustomerStepHandler::addToDataClass', 'CustomerPage-InteractiveLoginEventSubscriber::getSubscribedEvents', 'CustomerPage-LoginCheckUrlFormatter::getLoginCheckPath', + 'CustomerPage-SecurityBuilderExpander::extend', 'CustomerReorderWidget-CustomerReorderBundleItemCheckboxWidget::getName', 'CustomerReorderWidget-CustomerReorderFormWidget::getName', 'CustomerReorderWidget-CustomerReorderItemCheckboxWidget::getName', @@ -344,15 +370,28 @@ public function getExcludedSpans(): array 'DiscountPromotionWidget-DiscountPromotionDiscountReader::getAbstractSkusGroupedByIdDiscount', 'DiscountPromotionWidget-DiscountPromotionDiscountReader::getUniqueDiscounts', 'DummyMarketplacePayment-PaymentMethodFilter::filterPaymentMethods', + 'DynamicEntity-DynamicEntityFacade::getDynamicEntityConfigurationCollection', + 'Event-EventDispatcher::trigger', 'Event-EventDispatcher::triggerBulk', + 'Event-EventFacade::trigger', + 'Event-EventFacade::triggerBulk', 'Event-EventListenerContext::getEventQueueName', 'Event-EventListenerContext::getQueuePoolName', 'Event-EventListenerContext::isHandledInQueue', 'Event-EventLogger::log', 'Event-SubscriberMerger::mergeSubscribersWith', + 'EventBehavior-EventBehaviorFacade::getEventTransferForeignKeys', + 'EventBehavior-EventBehaviorFacade::getEventTransferIds', + 'EventBehavior-EventBehaviorFacade::triggerRuntimeEvents', 'EventBehavior-EventEntityTransferFilter::getEventTransferForeignKeys', + 'EventBehavior-EventEntityTransferFilter::getEventTransferIds', 'EventBehavior-EventEntityTransferFilter::getEventTransfersAdditionalValues', + 'EventBehavior-EventResourcePluginResolver::getAvailableResourceNames', + 'EventBehavior-TriggerManager::triggerRuntimeEvents', + 'ExampleProductSalePage-ExampleProductSalePageFacade::findProductLabelProductAbstractRelationChanges', 'ExampleProductSalePage-ExampleProductSalePageQueryContainer::queryProductLabelByName', + 'ExampleProductSalePage-ExampleProductSalePageQueryContainer::queryRelationsBecomingInactive', + 'ExampleProductSalePage-ProductAbstractRelationReader::findProductLabelProductAbstractRelationChanges', 'GiftCard-GiftCardCalculator::recalculate', 'GiftCard-GiftCardDiscountableItemFilter::filterGiftCardDiscountableItems', 'GiftCard-GiftCardFacade::filterGiftCardDiscountableItems', @@ -366,10 +405,14 @@ public function getExcludedSpans(): array 'GiftCard-ShipmentMethodGiftCardChecker::containsOnlyGiftCardItems', 'GiftCard-ShipmentMethodGiftCardDisallowedChecker::isShipmentMethodSuitable', 'GiftCard-ShipmentMethodGiftCardFilter::filter', + 'HomePage-IndexController::indexAction', 'LanguageSwitcherWidget-LanguageSwitcherWidget::getName', 'LanguageSwitcherWidget-LanguageSwitcherWidget::getTemplate', 'ManualOrderEntry-OrderSourceHydrator::hydrateOrderSource', 'MerchantOpeningHoursWidget-MerchantOpeningHoursWidget::getName', + 'MerchantProductApproval-MerchantProductApprovalProductAbstractExpander::expand', + 'MerchantProductGui-MerchantProductQueryCriteriaExpander::expandQueryCriteria', + 'MerchantProductOfferSearch-MerchantProductOfferSearchEventSubscriber::getSubscribedEvents', 'MerchantProductOfferWidget-MerchantProductOfferExpander::expandItemTransferWithProductOfferReference', 'MerchantProductOfferWidget-MerchantProductOffersSelectWidget::getName', 'MerchantProductOfferWidget-MerchantProductOffersSelectWidget::getTemplate', @@ -388,6 +431,8 @@ public function getExcludedSpans(): array 'MerchantRelationRequestWidget-MerchantRelationRequestMenuItemWidget::getTemplate', 'MerchantRelationship-MerchantRelationshipExpander::expandWithName', 'MerchantRelationship-MerchantRelationshipHydrator::hydrate', + 'MerchantRelationshipProductList-MerchantRelationshipProductListExpander::expandMerchantRelationship', + 'MerchantRelationshipProductList-MerchantRelationshipProductListFacade::expandMerchantRelationship', 'MerchantRelationshipSalesOrderThreshold-MerchantRelationshipSalesOrderThresholdFacade::findApplicableThresholds', 'MerchantRelationshipSalesOrderThreshold-MerchantRelationshipThresholdReader::findApplicableThresholds', 'MerchantRelationshipWidget-MerchantRelationshipLinkListWidget::getName', @@ -414,6 +459,12 @@ public function getExcludedSpans(): array 'Messenger-InMemoryMessageTray::getFlashMessagesTransfer', 'Messenger-InMemoryMessageTray::getMessages', 'Messenger-MessengerFacade::getStoredMessages', + 'MoneyGui-MoneyType::buildForm', + 'MoneyGui-MoneyType::buildView', + 'MoneyGui-MoneyType::configureOptions', + 'MoneyGui-MoneyTypeDataProvider::getMoneyCurrencyOptions', + 'MoneyGui-MoneyTypeDataProvider::getStoreById', + 'MoneyGui-SimpleMoneyType::getBlockPrefix', 'MoneyWidget-CurrencyIsoCodeWidget::getCurrencyIsoCode', 'MoneyWidget-CurrencyIsoCodeWidget::getName', 'MoneyWidget-CurrencyIsoCodeWidget::getTemplate', @@ -424,6 +475,7 @@ public function getExcludedSpans(): array 'MultiCartWidget-MiniCartWidget::getName', 'MultiCartWidget-MiniCartWidget::getTemplate', 'MultiCartWidget-MiniCartWidgetDataProvider::getActiveCart', + 'MultiCartWidget-MiniCartWidgetDataProvider::getInActiveQuoteList', 'MultiCartWidget-MiniCartWidgetDataProvider::isMultiCartAllowed', 'MultiCartWidget-MultiCartListWidget::getName', 'MultiCartWidget-MultiCartMenuItemWidget::getName', @@ -446,11 +498,16 @@ public function getExcludedSpans(): array 'Oms-Event::hasCommand', 'Oms-Event::hasTimeout', 'Oms-Event::isOnEnter', + 'Oms-FlagChecker::hasOrderItemsFlag', + 'Oms-LockedOrderStateMachine::checkConditions', + 'Oms-OmsFacade::getOmsReservedProductQuantityForSkus', 'Oms-OrderAggregatedItemStateExpander::expandOrdersWithAggregatedItemStates', 'Oms-OrderExpander::expandOrderWithOmsStates', 'Oms-OrderExpander::setOrderIsCancellableByItemState', + 'Oms-OrderItemStateExpander::expandOrderItemsWithItemState', 'Oms-ProcessCacheReader::getProcess', 'Oms-ProcessCacheReader::hasProcess', + 'Oms-ReservationReader::getOmsReservedProductQuantityForSkus', 'Oms-State::getEvent', 'Oms-State::getName', 'Oms-State::getOnEnterEvent', @@ -460,6 +517,9 @@ public function getExcludedSpans(): array 'Oms-State::hasOnEnterEvent', 'Oms-State::hasTimeoutEvent', 'Oms-State::isReserved', + 'Oms-Timeout::checkTimeouts', + 'Oms-Timeout::dropOldTimeout', + 'Oms-Timeout::setNewTimeout', 'Oms-Transition::getEvent', 'Oms-Transition::getSource', 'Oms-Transition::getTarget', @@ -488,15 +548,33 @@ public function getExcludedSpans(): array 'PriceProduct-CurrencyReaderWithCache::getCurrencyTransferFromIsoCode', 'PriceProduct-CurrencyReaderWithCache::getCurrencyTransfersFromIsoCodes', 'PriceProduct-PriceGrouper::groupPriceProduct', + 'PriceProduct-PriceProductAbstractReader::findProductAbstractPricesById', + 'PriceProduct-PriceProductAbstractReader::findProductAbstractPricesWithoutPriceExtraction', + 'PriceProduct-PriceProductConcreteReader::expandProductConcreteTransfersWithPrices', + 'PriceProduct-PriceProductConcreteWriter::persistProductConcretePriceCollection', 'PriceProduct-PriceProductCriteriaBuilder::buildCriteriaFromFilter', + 'PriceProduct-PriceProductDefaultWriter::persistPriceProductDefault', 'PriceProduct-PriceProductExpander::expandPriceProductTransfers', 'PriceProduct-PriceProductFacade::buildCriteriaFromFilter', + 'PriceProduct-PriceProductFacade::findProductAbstractPrices', + 'PriceProduct-PriceProductFacade::findProductAbstractPricesWithoutPriceExtraction', 'PriceProduct-PriceProductFacade::getDefaultPriceTypeName', + 'PriceProduct-PriceProductFacade::getPriceModeIdentifierForBothType', + 'PriceProduct-PriceProductFacade::getPriceTypeValues', 'PriceProduct-PriceProductFacade::groupPriceProductCollection', 'PriceProduct-PriceProductReaderPluginExecutor::executePriceExtractorPluginsForProductAbstract', 'PriceProduct-PriceProductReaderPluginExecutor::executePriceExtractorPluginsForProductConcrete', + 'PriceProduct-PriceProductStoreWriter::deleteOrphanPriceProductStoreEntities', + 'PriceProduct-PriceProductStoreWriter::persistPriceProductStore', + 'PriceProduct-PriceProductStoreWriterPluginExecutor::executeOrphanPriceProductStoreRemovalVoterPlugins', + 'PriceProduct-PriceProductTypeReader::getPriceTypeByName', + 'PriceProduct-PriceProductTypeReader::getPriceTypes', 'PriceProduct-PriceProductTypeReader::handleDefaultPriceType', 'PriceProduct-PriceProductTypeReader::hasPriceType', + 'PriceProductMerchantRelationshipGui-MerchantRelationshipPriceDimensionForm::buildForm', + 'PriceProductMerchantRelationshipGui-MerchantRelationshipPriceDimensionForm::configureOptions', + 'PriceProductScheduleGui-AbstractProductTabCreator::createScheduledPriceTabForProductAbstract', + 'PriceProductScheduleGui-AbstractScheduledPriceTable::getSearchTerm', 'PriceProductVolume-PriceProductVolumeFacade::extractPriceProductVolumesForProductAbstract', 'PriceProductVolume-PriceProductVolumeFacade::extractPriceProductVolumesForProductConcrete', 'PriceProductVolume-VolumePriceExtractor::extractPriceProductVolumesForProductAbstract', @@ -513,30 +591,60 @@ public function getExcludedSpans(): array 'Product-AbstractProductAbstractManagerSubject::attachBeforeCreateObserver', 'Product-AbstractProductAbstractManagerSubject::attachBeforeUpdateObserver', 'Product-AbstractProductAbstractManagerSubject::attachReadObserver', + 'Product-AbstractProductAbstractManagerSubject::notifyBeforeUpdateObservers', 'Product-AbstractProductConcreteManagerSubject::attachAfterCreateObserver', 'Product-AbstractProductConcreteManagerSubject::attachAfterUpdateObserver', 'Product-AbstractProductConcreteManagerSubject::attachBeforeCreateObserver', 'Product-AbstractProductConcreteManagerSubject::attachBeforeUpdateObserver', 'Product-AbstractProductConcreteManagerSubject::attachReadObserver', + 'Product-AbstractProductConcreteManagerSubject::notifyBeforeCreateObservers', + 'Product-AbstractProductConcreteManagerSubject::notifyReadObservers', 'Product-AttributeEncoder::decodeAttributes', + 'Product-AttributeEncoder::encodeAttributes', + 'Product-AttributeLoader::getCombinedAbstractAttributeKeys', 'Product-AttributeMerger::merge', + 'Product-ProductAbstractAfterUpdateUrlObserver::update', + 'Product-ProductAbstractAssertion::assertProductExists', + 'Product-ProductAbstractAssertion::assertSkuIsUniqueWhenUpdatingProduct', + 'Product-ProductAbstractBeforeCreateObserverPluginManager::create', + 'Product-ProductAbstractBeforeUpdateObserverPluginManager::update', + 'Product-ProductAbstractReadObserverPluginManager::executeProductAbsractReadPlugins', + 'Product-ProductAbstractStatusChecker::isActive', + 'Product-ProductAbstractStoreRelationReader::getStoreRelation', + 'Product-ProductAbstractStoreRelationWriter::save', + 'Product-ProductConcreteAssertion::assertSkuIsUnique', + 'Product-ProductConcreteBeforeCreateObserverPluginManager::create', + 'Product-ProductConcreteManager::findProductConcreteIdBySku', + 'Product-ProductConcreteManager::hasProductConcrete', 'Product-ProductConcreteNameGenerator::getLocalizedProductConcreteName', + 'Product-ProductConcreteReadObserverPluginManager::read', 'Product-ProductFacade::combineRawProductAttributes', 'Product-ProductFacade::decodeProductAttributes', + 'Product-ProductFacade::findProductConcreteIdBySku', 'Product-ProductFacade::findProductConcreteIdsByAbstractProductId', + 'Product-ProductFacade::getCombinedAbstractAttributeKeys', 'Product-ProductFacade::getLocalizedProductConcreteName', 'Product-ProductFacade::getRawProductAbstractTransfersByAbstractSkus', 'Product-ProductFacade::getRawProductConcreteTransfersByConcreteSkus', + 'Product-ProductFacade::hasProductConcrete', + 'Product-SkuGenerator::generateProductAbstractSku', 'ProductAlternative-ProductAlternativeFacade::doAllConcreteProductsHaveAlternatives', + 'ProductAlternative-ProductAlternativeFacade::findProductAbstractIdsWhichConcreteHasAlternative', 'ProductAlternative-ProductAlternativeFacade::isAlternativeProductApplicable', 'ProductAlternative-ProductAlternativeReader::doAllConcreteProductsHaveAlternatives', + 'ProductAlternative-ProductAlternativeReader::findProductAbstractIdsWhichConcreteHasAlternative', 'ProductAlternative-ProductAlternativeReader::isAlternativeProductApplicable', 'ProductAlternativeWidget-ProductAlternativeListWidget::getName', 'ProductAlternativeWidget-ProductAlternativeListWidget::getTemplate', 'ProductAlternativeWidget-ShoppingListProductAlternativeWidget::getName', 'ProductAlternativeWidget-WishlistProductAlternativeWidget::getName', + 'ProductApproval-ProductAbstractExpander::expandProductAbstract', 'ProductApproval-ProductReader::getProductAbstractTransfersIndexedByIdProductAbstract', 'ProductApprovalGui-ArrayExpander::insertArrayItemAfterKey', + 'ProductApprovalGui-ProductApprovalProductTableActionExpander::expandWithProductApprovalStatusActions', + 'ProductApprovalGui-ProductApprovalProductTableConfigurationExpander::expandTableConfiguration', + 'ProductApprovalGui-ProductApprovalProductTableDataExpander::expandTableData', + 'ProductApprovalGui-ProductApprovalStatusReader::getApplicableTableActionApprovalStatuses', 'ProductBarcodeWidget-ProductBarcodeWidget::getName', 'ProductBundle-PriceReaderWithCache::getNetPriceModeIdentifier', 'ProductBundle-ProductBundleCache::cacheProductForBundleTransfersBySku', @@ -554,6 +662,7 @@ public function getExcludedSpans(): array 'ProductBundle-ProductBundleOrderSaver::saveOrderBundleItems', 'ProductBundle-ProductBundlePreReloadUpdater::preReloadItems', 'ProductBundle-ProductBundlePriceCalculation::calculateForCalculableObjectTransfer', + 'ProductBundle-ProductBundleWriter::saveBundledProducts', 'ProductBundle-ProductOptionExpander::expandOrderProductBundlesWithProductOptions', 'ProductBundleWidget-ProductBundleCartItemsListWidget::getName', 'ProductBundleWidget-ProductBundleCartItemsListWidget::getTemplate', @@ -573,6 +682,7 @@ public function getExcludedSpans(): array 'ProductConfigurationCartWidget-ProductConfigurationCartPageButtonWidget::getTemplate', 'ProductConfigurationCartWidget-ProductConfigurationQuoteValidatorWidget::getName', 'ProductConfigurationCartWidget-ProductConfigurationQuoteValidatorWidget::getTemplate', + 'ProductConfigurationGui-ProductConfigurationTableDataExpander::expandProductItemWithProductConfigurationType', 'ProductConfigurationShoppingListWidget-ProductConfigurationShoppingListItemDisplayWidget::getName', 'ProductConfigurationShoppingListWidget-ProductConfigurationShoppingListPageButtonWidget::getName', 'ProductConfigurationWidget-ProductConfigurationProductDetailPageButtonWidget::getName', @@ -583,14 +693,25 @@ public function getExcludedSpans(): array 'ProductConfigurationWishlistWidget-ProductConfigurationWishlistItemDisplayWidget::getName', 'ProductConfigurationWishlistWidget-ProductConfigurationWishlistPageButtonWidget::getName', 'ProductDiscontinued-ProductDiscontinuedFacade::getProductDiscontinuedCollection', + 'ProductDiscontinuedProductBundleConnector-ProductBundleDiscontinuedWriter::discontinueProductBundleByBundledProducts', + 'ProductDiscontinuedProductLabelConnector-ProductAbstractRelationReader::findProductLabelProductAbstractRelationChanges', + 'ProductDiscontinuedProductLabelConnector-ProductDiscontinuedProductLabelConnectorFacade::findProductLabelProductAbstractRelationChanges', 'ProductDiscontinuedWidget-ProductDiscontinuedNoteWidget::getName', 'ProductDiscontinuedWidget-ProductDiscontinuedNoteWidget::getTemplate', 'ProductDiscontinuedWidget-ProductDiscontinuedWidget::getName', 'ProductDiscountConnector-AttributeProvider::getAllAttributeTypes', 'ProductDiscountConnector-ProductDiscountConnectorFacade::getAttributeTypes', 'ProductGroupWidget-ProductGroupColorWidget::getName', + 'ProductGroupWidget-ProductGroupReader::getProductGroups', 'ProductGroupWidget-ProductGroupWidget::getName', 'ProductGroupWidget-ProductGroupWidget::getTemplate', + 'ProductImage-ProductImageFacade::createProductConcreteImageSetCollection', + 'ProductImage-ProductImageFacade::expandProductAbstractWithImageSets', + 'ProductImage-ProductImageFacade::expandProductConcreteTransfersWithImageSets', + 'ProductImage-ProductImageFacade::getProductImagesSetCollectionByProductAbstractId', + 'ProductImage-Reader::expandProductAbstractWithImageSets', + 'ProductImage-Reader::expandProductConcreteTransfersWithImageSets', + 'ProductImage-Reader::getProductImagesSetCollectionByProductAbstractId', 'ProductLabel-ProductAbstractRelationReader::findIdsProductAbstractByIdProductLabel', 'ProductLabel-ProductLabelFacade::findLabelByLabelName', 'ProductLabel-ProductLabelFacade::findProductAbstractRelationsByIdProductLabel', @@ -600,6 +721,29 @@ public function getExcludedSpans(): array 'ProductList-ProductListRestrictionFilter::filterRestrictedProductConcreteSkus', 'ProductList-ProductListRestrictionValidator::validateItemAddition', 'ProductList-RestrictedItemsFilter::filterRestrictedItems', + 'ProductManagement-AbstractProductFormDataProvider::getOptions', + 'ProductManagement-AbstractSubForm::configureOptions', + 'ProductManagement-GeneralForm::buildForm', + 'ProductManagement-ImageCollectionForm::buildForm', + 'ProductManagement-ImageCollectionForm::configureOptions', + 'ProductManagement-ImageCollectionForm::getBlockPrefix', + 'ProductManagement-ImageSetForm::buildForm', + 'ProductManagement-ImageSetForm::configureOptions', + 'ProductManagement-ImageSetForm::getBlockPrefix', + 'ProductManagement-LocaleProvider::getCurrentLocale', + 'ProductManagement-LocaleProvider::getLocaleCollection', + 'ProductManagement-ProductFormAdd::configureOptions', + 'ProductManagement-ProductMoneyCollectionDataProvider::mergeMissingMoneyValues', + 'ProductManagement-ProductMoneyCollectionType::buildForm', + 'ProductManagement-ProductMoneyCollectionType::configureOptions', + 'ProductManagement-ProductMoneyCollectionType::getBlockPrefix', + 'ProductManagement-ProductMoneyType::buildForm', + 'ProductManagement-ProductMoneyType::buildView', + 'ProductManagement-ProductMoneyType::configureOptions', + 'ProductManagement-ProductPriceNotBlankValidator::validate', + 'ProductManagement-ProductTypeHelper::isGiftCardByProductAbstractEntity', + 'ProductManagement-ProductTypeHelper::isProductBundleByProductAbstractEntity', + 'ProductManagement-SeoForm::buildForm', 'ProductMeasurementUnit-CartChangeExpander::expandWithQuantitySalesUnit', 'ProductMeasurementUnit-CartChangeSalesUnitExpander::expandItemsWithDefaultQuantitySalesUnit', 'ProductMeasurementUnit-OrderItemExpander::expandOrderItem', @@ -607,6 +751,8 @@ public function getExcludedSpans(): array 'ProductMeasurementUnit-ProductMeasurementUnitFacade::expandItemGroupKeyWithQuantitySalesUnit', 'ProductMeasurementUnitWidget-CartProductMeasurementUnitQuantitySelectorWidget::getName', 'ProductMeasurementUnitWidget-CartProductMeasurementUnitQuantitySelectorWidget::getTemplate', + 'ProductNew-ProductAbstractRelationReader::findProductLabelProductAbstractRelationChanges', + 'ProductNew-ProductNewFacade::findProductLabelProductAbstractRelationChanges', 'ProductOffer-InactiveProductOfferItemsFilter::filterInactiveProductOfferItems', 'ProductOffer-ItemProductOfferChecker::checkItemProductOffer', 'ProductOffer-ProductOfferCartItemQuantityCounter::countCartItemQuantity', @@ -645,6 +791,7 @@ public function getExcludedSpans(): array 'ProductPackagingUnit-ProductPackagingUnitItemQuantityValidator::isProductPackagingUnitItemQuantitySplittable', 'ProductPackagingUnitWidget-ProductPackagingUnitWidget::getName', 'ProductPackagingUnitWidget-ProductPackagingUnitWidget::getTemplate', + 'ProductPageSearch-AddToCartSkuReader::getProductAbstractAddToCartSkus', 'ProductPageSearch-PageMapBuilder::add', 'ProductPageSearch-PageMapBuilder::addCategory', 'ProductPageSearch-PageMapBuilder::addCompletionTerms', @@ -656,6 +803,7 @@ public function getExcludedSpans(): array 'ProductPageSearch-PageMapBuilder::addStringFacet', 'ProductPageSearch-PageMapBuilder::addStringSort', 'ProductPageSearch-PageMapBuilder::addSuggestionTerms', + 'ProductPageSearch-ProductConcretePageSearchProductLocalizedAttributesEventSubscriber::getSubscribedEvents', 'ProductQuantity-CartChangeTransferNormalizerPreChecker::hasNormalizableItems', 'ProductRelationWidget-SimilarProductsWidget::getName', 'ProductRelationWidget-SimilarProductsWidget::getTemplate', @@ -671,6 +819,7 @@ public function getExcludedSpans(): array 'ProductReviewWidget-ProductRatingFilterWidget::getTemplate', 'ProductReviewWidget-ProductReviewDisplayWidget::getName', 'ProductReviewWidget-ProductReviewDisplayWidget::getTemplate', + 'ProductSearch-ProductSearchMarker::activateProductSearch', 'ProductSearchWidget-ProductConcreteAddWidget::getName', 'ProductSearchWidget-ProductConcreteAddWidget::getTemplate', 'ProductSearchWidget-ProductConcreteSearchGridWidget::getName', @@ -685,9 +834,14 @@ public function getExcludedSpans(): array 'ProductWidget-PdpProductRelationWidget::getTemplate', 'ProductWidget-PdpProductReplacementForListWidget::getName', 'ProductWidget-ProductAlternativeWidget::getName', + 'PushNotification-PushNotificationFacade::getPushNotificationCollection', + 'PushNotification-PushNotificationFacade::sendPushNotifications', + 'PushNotification-PushNotificationSender::sendPushNotifications', + 'PushNotification-PushNotificationSubscriptionDeliveryLogCreator::createPushNotificationSubscriptionDeliveryLogCollection', 'PushNotification-PushNotificationSubscriptionDeliveryLogExtractor::extractDeliveryLogs', 'PushNotificationWebPushPhp-PushNotificationFilter::filterPushNotificationCollectionByProviderName', 'PushNotificationWebPushPhp-PushNotificationSender::sendNotifications', + 'PushNotificationWebPushPhp-PushNotificationWebPushPhpFacade::sendNotifications', 'PushNotificationWebPushPhp-WebPush::flush', 'PushNotificationWebPushPhp-WebPushQueueCreator::queuePushNotifications', 'Quote-QuoteFacade::getQuoteCollection', @@ -815,6 +969,7 @@ public function getExcludedSpans(): array 'ShipmentTypeWidget-ShipmentTypeFormSubmitDataHydrator::hydrate', 'ShopApplication-AbstractController::initialize', 'ShopApplication-ShopApplicationTwigEventSubscriber::getSubscribedEvents', + 'ShopCmsSlot-CmsSlotDataProvider::getSlotContent', 'ShoppingListNoteWidget-ShoppingListItemNoteWidget::getName', 'ShoppingListPage-ShoppingListDismissWidget::getName', 'ShoppingListWidget-AddItemsToShoppingListWidget::getName', @@ -827,14 +982,18 @@ public function getExcludedSpans(): array 'ShoppingListWidget-ShoppingListNavigationMenuWidget::getTemplate', 'ShoppingListWidget-ShoppingListSubtotalWidget::getName', 'ShopUi-NumberFormatterTwigExtender::extend', + 'Stock-StockFacade::isProductAbstractNeverOutOfStockForStore', + 'Stock-StockProductReader::isProductAbstractNeverOutOfStockForStore', 'StorageRouter-StorageUrlGenerator::generate', 'StorageRouter-StorageUrlGenerator::getContext', 'StorageRouter-StorageUrlGenerator::setContext', 'StoreWidget-StoreSwitcherWidget::getName', 'StoreWidget-StoreSwitcherWidget::getTemplate', + 'Synchronization-ExporterPluginResolver::getAvailableResourceNames', 'Synchronization-InMemoryMessageSynchronizer::addSynchronizationMessage', 'Synchronization-InMemoryMessageSynchronizer::flushSynchronizationMessages', 'Synchronization-SynchronizationFacade::addSynchronizationMessageToBuffer', + 'Synchronization-SynchronizationFacade::flushSynchronizationMessagesFromBuffer', 'TabsWidget-FullTextSearchTabsWidget::getName', 'Tax-AccruedTaxCalculator::getTaxValueFromPrice', 'Tax-PriceCalculationHelper::getTaxValueFromPrice', @@ -842,6 +1001,9 @@ public function getExcludedSpans(): array 'Tax-TaxAmountCalculator::recalculate', 'Tax-TaxFacade::calculateTaxRateAverageAggregation', 'Tax-TaxRateAverageAggregator::recalculate', + 'TaxProductConnector-ProductAbstractTaxSetExpander::expand', + 'TaxProductConnector-ProductAbstractTaxWriter::saveTaxSetToProductAbstract', + 'TaxProductConnector-TaxProductConnectorFacade::expandProductAbstract', 'User-SecurityServiceExtender::extend', 'User-UserFacade::getCurrentUser', 'User-UserFacade::hasCurrentUser', From cd9f8e3a29577e5f81a81a46207f34695788da46 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Tue, 3 Dec 2024 17:37:36 +0200 Subject: [PATCH 37/48] Performance testing --- .../Sampler/CriticalSpanTraceIdRatioSampler.php | 4 ++-- .../Instrumentation/Sampler/TraceSampleResult.php | 6 ++++++ .../Instrumentation/Span/SpanBuilder.php | 5 +++-- .../Instrumentation/Span/SpanContext.php | 12 +++++++++--- .../SpanProcessor/PostFilterBatchSpanProcessor.php | 12 ++++++------ .../SprykerInstrumentationBootstrap.php | 14 ++++++++++++-- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index 2943915..d145513 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -77,8 +77,8 @@ public function shouldSample( // var_dump($traceId,$traceIdCondition, $lowerOrderBytes, round($probability * $traceIdLimit), $traceIdLimit, $spanName);die; // } - $traceIdCondition = (mt_rand() / mt_getrandmax()) <= $probability; - //var_dump($traceIdCondition, $probability);die; + $result = mt_rand() / mt_getrandmax(); + $traceIdCondition = $result <= $probability; $decision = $traceIdCondition ? SamplingResult::RECORD_AND_SAMPLE : SamplingResult::DROP; return new SamplingResult($decision, [], $this->parentSpan->getContext()->getTraceState()); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php index 5acdcb3..dbe6862 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php @@ -36,6 +36,12 @@ public static function shouldSample(Request $request): int { $route = $request->attributes->get('_route'); + if ($request->getMethod() !== Request::METHOD_GET) { + static::$result = static::SAMPLING_RESULT_ALLOW_ALL; + + return static::$result; + } + if (in_array($route, OpentelemetryInstrumentationConfig::getExcludedRoutes(), true)) { static::$result = self::SAMPLING_RESULT_BLOCK; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 9236206..b050f49 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -185,9 +185,10 @@ public function startSpan(): SpanInterface $samplingDecision === SamplingResult::RECORD_AND_SAMPLE ? TraceFlags::SAMPLED : TraceFlags::DEFAULT, $samplingResultTraceState, ); - + $fileS = fopen(APPLICATION_ROOT_DIR . '/created', 'a'); + fwrite($fileS, $traceId . ' ' . $this->spanName . ' ' . $samplingDecision . PHP_EOL); + fclose($fileS); if (!in_array($samplingDecision, [SamplingResult::RECORD_AND_SAMPLE, SamplingResult::RECORD_ONLY], true)) { - //var_dump($this->spanName);die; return Span::wrap($spanContext); } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php index 2cd3a2a..52389bd 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php @@ -40,10 +40,16 @@ class SpanContext implements SpanContextInterface protected function __construct( protected string $traceId, protected string $spanId, - protected readonly int $traceFlags, - protected readonly bool $isRemote, - protected readonly ?TraceStateInterface $traceState = null, + protected int $traceFlags, + protected bool $isRemote, + protected ?TraceStateInterface $traceState = null, ) { + if (!$traceId || !$spanId) { + $this->traceId = SpanContextValidator::INVALID_TRACE; + $this->spanId = SpanContextValidator::INVALID_SPAN; + $this->isValid = false; + } + $this->isSampled = ($traceFlags & TraceFlags::SAMPLED) === TraceFlags::SAMPLED; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index f2273bd..62c8f0b 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -192,12 +192,15 @@ public function onStart(ReadWriteSpanInterface $span, ContextInterface $parentCo */ public function onEnd(ReadableSpanInterface $span): void { - //$file = fopen(APPLICATION_ROOT_DIR . '/dropped', 'a'); + $fileS = fopen(APPLICATION_ROOT_DIR . '/sampled-new', 'a'); if ($this->closed) { return; } - + fwrite($fileS, $span->getTraceId() . ' ' . $span->getName() . PHP_EOL); + fclose($fileS); if (!$span->getContext()->isSampled()) { + fwrite($fileS, '\'-' . $span->getName() . '\',' . PHP_EOL); + fclose($fileS); return; } @@ -211,10 +214,7 @@ public function onEnd(ReadableSpanInterface $span): void && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { $this->dropped++; -// if ($span->getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) !== true) { -// fwrite($file, '\'' . $span->getName() . '\',' . PHP_EOL); -// } -// fclose($file); + return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 269c050..02c33bf 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -10,6 +10,7 @@ use OpenTelemetry\API\Common\Time\Clock; use OpenTelemetry\API\Signals; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; +use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\SpanKind; use OpenTelemetry\Context\Context; use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory; @@ -66,6 +67,11 @@ class SprykerInstrumentationBootstrap */ protected static ?ResourceInfo $resourceInfo = null; + /** + * @var \OpenTelemetry\API\Trace\SpanInterface|null + */ + protected static ?SpanInterface $rootSpan = null; + /** * @return void */ @@ -92,6 +98,7 @@ public static function register(): void static::registerRootSpan($serviceName, $request); ShutdownHandler::register($tracerProvider->shutdown(...)); + ShutdownHandler::register([static::class, 'shutdownHandler']); } /** @@ -214,7 +221,7 @@ protected static function registerRootSpan(string $servicedName, Request $reques Context::storage()->attach($span->storeInContext($parent)); - register_shutdown_function([static::class, 'shutdownHandler']); + static::$rootSpan = $span; } /** @@ -243,7 +250,10 @@ public static function shutdownHandler(): void return; } $scope->detach(); - $span = Span::fromContext($scope->context()); + $span = static::$rootSpan; + $fileC = fopen(APPLICATION_ROOT_DIR . '/closed', 'a'); + fwrite($fileC, $span->getName() . PHP_EOL); + fclose($fileC); $name = RootSpanNameStorage::getInstance()->getName(); if ($name) { $span->updateName($name); From d5b8c53ac191683a6c948d698beb3afda141cf63 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Tue, 3 Dec 2024 19:05:45 +0200 Subject: [PATCH 38/48] Added non critical probability processing --- .../CriticalSpanTraceIdRatioSampler.php | 29 ++++++++++++++++++- .../Instrumentation/Span/SpanBuilder.php | 4 +-- .../SprykerInstrumentationBootstrap.php | 12 ++++---- .../OpentelemetryInstrumentationConfig.php | 23 +++++++++++++-- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php index d145513..f044b5f 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php @@ -23,6 +23,11 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, TraceStateAwa */ public const IS_CRITICAL_ATTRIBUTE = 'is_critical'; + /** + * @var string + */ + public const NO_CRITICAL_ATTRIBUTE = 'no_critical'; + /** * @var float */ @@ -33,15 +38,21 @@ class CriticalSpanTraceIdRatioSampler implements SamplerInterface, TraceStateAwa */ protected float $criticalProbability; + /** + * @var float + */ + protected float $nonCriticalProbability; + protected ?SpanInterface $parentSpan = null; /** * @param float $probability */ - public function __construct(float $probability, float $criticalProbability) + public function __construct(float $probability, float $criticalProbability, float $nonCriticalProbability) { $this->setProbability($probability); $this->setCriticalProbability($criticalProbability); + $this->setNonCriticalProbability($nonCriticalProbability); } /** @@ -70,6 +81,10 @@ public function shouldSample( $probability = $this->criticalProbability; } + if ($attributes->has(static::NO_CRITICAL_ATTRIBUTE)) { + $probability = $this->nonCriticalProbability; + } + // $traceIdLimit = (1 << 60) - 1; // $lowerOrderBytes = hexdec(substr($traceId, strlen($traceId) - 15, 15)); // $traceIdCondition = $lowerOrderBytes < round($probability * $traceIdLimit); @@ -126,6 +141,18 @@ protected function setCriticalProbability(float $probability): void $this->criticalProbability = $probability; } + /** + * @param float $probability + * + * @return void + */ + protected function setNonCriticalProbability(float $probability): void + { + $this->validateProbability($probability); + + $this->nonCriticalProbability = $probability; + } + /** * @param float $probability * diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index b050f49..0a39539 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -185,9 +185,7 @@ public function startSpan(): SpanInterface $samplingDecision === SamplingResult::RECORD_AND_SAMPLE ? TraceFlags::SAMPLED : TraceFlags::DEFAULT, $samplingResultTraceState, ); - $fileS = fopen(APPLICATION_ROOT_DIR . '/created', 'a'); - fwrite($fileS, $traceId . ' ' . $this->spanName . ' ' . $samplingDecision . PHP_EOL); - fclose($fileS); + if (!in_array($samplingDecision, [SamplingResult::RECORD_AND_SAMPLE, SamplingResult::RECORD_ONLY], true)) { return Span::wrap($spanContext); } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 02c33bf..5ba9539 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -17,7 +17,6 @@ use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\SDK\Common\Util\ShutdownHandler; use OpenTelemetry\SDK\Sdk; -use OpenTelemetry\SDK\Trace\Sampler\ParentBased; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; @@ -29,7 +28,6 @@ use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\TraceSampleResult; use Spryker\Service\Opentelemetry\Instrumentation\Span\Attributes; -use Spryker\Service\Opentelemetry\Instrumentation\Span\Span; use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanConverter; use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanExporter; use Spryker\Service\Opentelemetry\Instrumentation\SpanProcessor\PostFilterBatchSpanProcessor; @@ -161,8 +159,11 @@ protected static function createSpanProcessor(): SpanProcessorInterface */ protected static function createSampler(): SamplerInterface { - return new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability(), OpentelemetryInstrumentationConfig::getSamplerProbabilityForCriticalSpans()); - //return new ParentBased(new CriticalSpanTraceIdRatioSampler(OpentelemetryInstrumentationConfig::getSamplerProbability())); + return new CriticalSpanTraceIdRatioSampler( + OpentelemetryInstrumentationConfig::getSamplerProbability(), + OpentelemetryInstrumentationConfig::getSamplerProbabilityForCriticalSpans(), + OpentelemetryInstrumentationConfig::getSamplerProbabilityForNonCriticalSpans(), + ); } /** @@ -251,9 +252,6 @@ public static function shutdownHandler(): void } $scope->detach(); $span = static::$rootSpan; - $fileC = fopen(APPLICATION_ROOT_DIR . '/closed', 'a'); - fwrite($fileC, $span->getName() . PHP_EOL); - fclose($fileC); $name = RootSpanNameStorage::getInstance()->getName(); if ($name) { $span->updateName($name); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index 3ec0fb6..04d9108 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -49,6 +49,11 @@ class OpentelemetryInstrumentationConfig */ protected const OTEL_TRACES_CRITICAL_SAMPLER_ARG = 'OTEL_TRACES_CRITICAL_SAMPLER_ARG'; + /** + * @var string + */ + protected const OTEL_TRACES_NON_CRITICAL_SAMPLER_ARG = 'OTEL_TRACES_NON_CRITICAL_SAMPLER_ARG'; + /** * @var string */ @@ -173,7 +178,7 @@ public static function getDefaultServiceName(): string */ public static function getSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.5; + $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.4; return (float)$probability; } @@ -185,7 +190,19 @@ public static function getSamplerProbability(): float */ public static function getSamplerProbabilityForCriticalSpans(): float { - $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.9; + $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.8; + + return (float)$probability; + } + + /** + * @api + * + * @return float + */ + public static function getSamplerProbabilityForNonCriticalSpans(): float + { + $probability = getenv(static::OTEL_TRACES_NON_CRITICAL_SAMPLER_ARG) ?: 0.1; return (float)$probability; } @@ -234,7 +251,7 @@ public static function getSpanProcessorMaxBatchSize(): int */ public static function getTraceSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.7; + $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.5; return (float)$probability; } From 8deb8d40b657c2d7d2175469d057d429183206f0 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Tue, 3 Dec 2024 19:15:49 +0200 Subject: [PATCH 39/48] Added non critical probability processing --- .../SpanProcessor/PostFilterBatchSpanProcessor.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 62c8f0b..76aed24 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -192,15 +192,11 @@ public function onStart(ReadWriteSpanInterface $span, ContextInterface $parentCo */ public function onEnd(ReadableSpanInterface $span): void { - $fileS = fopen(APPLICATION_ROOT_DIR . '/sampled-new', 'a'); if ($this->closed) { return; } - fwrite($fileS, $span->getTraceId() . ' ' . $span->getName() . PHP_EOL); - fclose($fileS); + if (!$span->getContext()->isSampled()) { - fwrite($fileS, '\'-' . $span->getName() . '\',' . PHP_EOL); - fclose($fileS); return; } From 871640bb2759f088d712b314557f74c3cfba285b Mon Sep 17 00:00:00 2001 From: gechetspr Date: Wed, 4 Dec 2024 17:11:07 +0200 Subject: [PATCH 40/48] Incriased visibility and fixed tree structure --- ...mpler.php => CriticalSpanRatioSampler.php} | 13 +-- ...hp => ParentSpanAwareSamplerInterface.php} | 2 +- .../Span/AttributesBuilder.php | 4 +- .../Instrumentation/Span/Span.php | 7 +- .../Instrumentation/Span/SpanBuilder.php | 21 ++++- .../Instrumentation/Span/SpanContext.php | 12 ++- .../SpanIdUpdateAwareSpanContextInterface.php | 12 +++ .../PostFilterBatchSpanProcessor.php | 16 +++- .../SprykerInstrumentationBootstrap.php | 4 +- .../OpentelemetryInstrumentationConfig.php | 2 +- .../Generator/Collector/ClassCollector.php | 23 +++-- .../ContentCreator/HookContentCreator.php | 12 +++ .../Zed/Opentelemetry/OpentelemetryConfig.php | 86 ++++++++++--------- 13 files changed, 138 insertions(+), 76 deletions(-) rename src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/{CriticalSpanTraceIdRatioSampler.php => CriticalSpanRatioSampler.php} (84%) rename src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/{TraceStateAwareSamplerInterface.php => ParentSpanAwareSamplerInterface.php} (92%) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanRatioSampler.php similarity index 84% rename from src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php rename to src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanRatioSampler.php index f044b5f..ce0d2c6 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanTraceIdRatioSampler.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/CriticalSpanRatioSampler.php @@ -9,14 +9,12 @@ use InvalidArgumentException; use OpenTelemetry\API\Trace\SpanInterface; -use OpenTelemetry\API\Trace\TraceStateInterface; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; use OpenTelemetry\SDK\Trace\SamplerInterface; use OpenTelemetry\SDK\Trace\SamplingResult; -use Spryker\Service\Opentelemetry\OpentelemetryInstrumentationConfig; -class CriticalSpanTraceIdRatioSampler implements SamplerInterface, TraceStateAwareSamplerInterface +class CriticalSpanRatioSampler implements SamplerInterface, ParentSpanAwareSamplerInterface { /** * @var string @@ -85,13 +83,6 @@ public function shouldSample( $probability = $this->nonCriticalProbability; } -// $traceIdLimit = (1 << 60) - 1; -// $lowerOrderBytes = hexdec(substr($traceId, strlen($traceId) - 15, 15)); -// $traceIdCondition = $lowerOrderBytes < round($probability * $traceIdLimit); -// if (!$traceIdCondition && $spanName !== 'Backoffice GET http://backoffice.de.spryker.local/') { -// var_dump($traceId,$traceIdCondition, $lowerOrderBytes, round($probability * $traceIdLimit), $traceIdLimit, $spanName);die; -// } - $result = mt_rand() / mt_getrandmax(); $traceIdCondition = $result <= $probability; $decision = $traceIdCondition ? SamplingResult::RECORD_AND_SAMPLE : SamplingResult::DROP; @@ -114,7 +105,7 @@ public function addParentSpan(SpanInterface $parentSpan): void */ public function getDescription(): string { - return sprintf('%s{%.6F}', 'CriticalSpanTraceIdRatioSampler', $this->probability); + return sprintf('%s{%.6F}', 'CriticalSpanRatioSampler', $this->probability); } /** diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php similarity index 92% rename from src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php rename to src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php index 0a3d0a7..7fb8214 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceStateAwareSamplerInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/ParentSpanAwareSamplerInterface.php @@ -10,7 +10,7 @@ use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\TraceStateInterface; -interface TraceStateAwareSamplerInterface +interface ParentSpanAwareSamplerInterface { /** * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php index 6b26409..bb564e2 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php @@ -12,7 +12,7 @@ use OpenTelemetry\SDK\Common\Attribute\AttributeValidator; use OpenTelemetry\SDK\Common\Attribute\AttributeValidatorInterface; use OpenTelemetry\SemConv\TraceAttributes; -use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanRatioSampler; class AttributesBuilder implements AttributesBuilderInterface { @@ -139,7 +139,7 @@ protected function getSafeAttributes(): array 'search.query', 'root.url', TraceAttributes::URL_DOMAIN, - CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE, + CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, ]; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php index 22bccc2..a307645 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -11,7 +11,6 @@ use OpenTelemetry\API\Common\Time\Clock; use OpenTelemetry\API\Trace\Span as OtelSpan; use OpenTelemetry\API\Trace\SpanContextInterface; -use OpenTelemetry\API\Trace\SpanInterface; use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface; @@ -94,7 +93,7 @@ protected function __construct( * @param \OpenTelemetry\API\Trace\SpanContextInterface $context * @param \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface $instrumentationScope * @param int $kind - * @param \OpenTelemetry\API\Trace\SpanInterface $parentSpan + * @param \OpenTelemetry\API\Trace\SpanContextInterface $parentSpanContext * @param \OpenTelemetry\Context\ContextInterface $parentContext * @param \OpenTelemetry\SDK\Trace\SpanLimits $spanLimits * @param \OpenTelemetry\SDK\Trace\SpanProcessorInterface $spanProcessor @@ -111,7 +110,7 @@ public static function startSpan( SpanContextInterface $context, InstrumentationScopeInterface $instrumentationScope, int $kind, - SpanInterface $parentSpan, + SpanContextInterface $parentSpanContext, ContextInterface $parentContext, SpanLimits $spanLimits, SpanProcessorInterface $spanProcessor, @@ -126,7 +125,7 @@ public static function startSpan( $context, $instrumentationScope, $kind, - $parentSpan->getContext(), + $parentSpanContext, $spanLimits, $spanProcessor, $resource, diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 0a39539..0b949a1 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -19,7 +19,7 @@ use OpenTelemetry\SDK\Trace\Link; use OpenTelemetry\SDK\Trace\SamplingResult; use OpenTelemetry\SDK\Trace\TracerSharedState; -use Spryker\Service\Opentelemetry\Instrumentation\Sampler\TraceStateAwareSamplerInterface; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\ParentSpanAwareSamplerInterface; class SpanBuilder implements SpanBuilderInterface { @@ -53,6 +53,11 @@ class SpanBuilder implements SpanBuilderInterface */ protected int $startEpochNanos = 0; + /** + * @var array + */ + protected static $parentMapping = []; + /** * @param string $spanName * @param \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface $instrumentationScope @@ -187,15 +192,25 @@ public function startSpan(): SpanInterface ); if (!in_array($samplingDecision, [SamplingResult::RECORD_AND_SAMPLE, SamplingResult::RECORD_ONLY], true)) { + static::$parentMapping[$spanId] = $parentSpanContext->getSpanId(); + + if ($spanContext instanceof SpanIdUpdateAwareSpanContextInterface) { + $spanContext->updateSpanId($parentSpanContext->getSpanId()); + } + return Span::wrap($spanContext); } + if (isset(static::$parentMapping[$parentSpanContext->getSpanId()]) && $parentSpanContext instanceof SpanIdUpdateAwareSpanContextInterface) { + $parentSpanContext->updateSpanId(static::$parentMapping[$parentSpanContext->getSpanId()]); + } + return Span::startSpan( $this->spanName, $spanContext, $this->instrumentationScope, $this->spanKind, - $parentSpan, + $parentSpanContext, $parentContext, $this->tracerSharedState->getSpanLimits(), $this->tracerSharedState->getSpanProcessor(), @@ -220,7 +235,7 @@ protected function getSamplingResult(SpanInterface $parentSpan, ContextInterface ->tracerSharedState ->getSampler(); - if ($sampler instanceof TraceStateAwareSamplerInterface) { + if ($sampler instanceof ParentSpanAwareSamplerInterface) { $sampler->addParentSpan($parentSpan);; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php index 52389bd..272d16a 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php @@ -13,7 +13,7 @@ use OpenTelemetry\API\Trace\TraceStateInterface; use function hex2bin; -class SpanContext implements SpanContextInterface +class SpanContext implements SpanContextInterface, SpanIdUpdateAwareSpanContextInterface { protected static ?SpanContextInterface $invalidContext = null; @@ -172,4 +172,14 @@ public static function getInvalid(): SpanContextInterface return static::$invalidContext; } + + /** + * @param string $spanId + * + * @return void + */ + public function updateSpanId(string $spanId): void + { + $this->spanId = $spanId; + } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php new file mode 100644 index 0000000..296435a --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php @@ -0,0 +1,12 @@ + + */ + protected static $parentSpanIdMapping = []; + /** * @param \OpenTelemetry\SDK\Trace\SpanExporterInterface $exporter * @param \OpenTelemetry\API\Common\Time\ClockInterface $clock @@ -200,7 +206,7 @@ public function onEnd(ReadableSpanInterface $span): void return; } - $duration = $span->getAttribute(CriticalSpanTraceIdRatioSampler::IS_CRITICAL_ATTRIBUTE) === true + $duration = $span->getAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE) === true ? OpentelemetryInstrumentationConfig::getSamplerThresholdNanoForCriticalSpan() : OpentelemetryInstrumentationConfig::getSamplerThresholdNano(); @@ -210,6 +216,7 @@ public function onEnd(ReadableSpanInterface $span): void && $span->getStatus()->getCode() === StatusCode::STATUS_OK ) { $this->dropped++; + static::$parentSpanIdMapping[$span->getSpanId()] = $span->getParentContext()->getSpanId(); return; } @@ -221,6 +228,11 @@ public function onEnd(ReadableSpanInterface $span): void } $this->queueSize++; + + if (isset(static::$parentSpanIdMapping[$span->getParentContext()->getSpanId()]) && $span->getParentContext() instanceof SpanIdUpdateAwareSpanContextInterface) { + $span->getParentContext()->updateSpanId(static::$parentSpanIdMapping[$span->getParentContext()->getSpanId()]); + } + $this->batch[] = $span; $this->nextScheduledRun ??= $this->clock->now() + $this->scheduledDelayNanos; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 5ba9539..93b2614 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -25,7 +25,7 @@ use OpenTelemetry\SemConv\TraceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo; use Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfoFactory; -use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanTraceIdRatioSampler; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanRatioSampler; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\TraceSampleResult; use Spryker\Service\Opentelemetry\Instrumentation\Span\Attributes; use Spryker\Service\Opentelemetry\Instrumentation\Span\SpanConverter; @@ -159,7 +159,7 @@ protected static function createSpanProcessor(): SpanProcessorInterface */ protected static function createSampler(): SamplerInterface { - return new CriticalSpanTraceIdRatioSampler( + return new CriticalSpanRatioSampler( OpentelemetryInstrumentationConfig::getSamplerProbability(), OpentelemetryInstrumentationConfig::getSamplerProbabilityForCriticalSpans(), OpentelemetryInstrumentationConfig::getSamplerProbabilityForNonCriticalSpans(), diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index 04d9108..6aa9e82 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -180,7 +180,7 @@ public static function getSamplerProbability(): float { $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.4; - return (float)$probability; + return (float)0.4; } /** diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php index ed57639..68effa7 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/Collector/ClassCollector.php @@ -117,7 +117,7 @@ protected function extractClassDetailsFromFile(string $filePath): array $tokens = token_get_all($content); $namespace = $this->parseNamespace($tokens); $class = $this->parseClassName($tokens); - $methods = $this->parseMethods($tokens); + $methods = $this->parseMethods($tokens, $class); if ($class && $methods !== []) { return [ @@ -187,10 +187,11 @@ protected function parseClassName(array $tokens): string /** * @param array $tokens + * @param string $class * * @return array */ - protected function parseMethods(array $tokens): array + protected function parseMethods(array $tokens, string $class): array { $methods = []; $functionLevel = 0; @@ -199,7 +200,7 @@ protected function parseMethods(array $tokens): array for ($i = 0; $i < $tokensCount; $i++) { if ($tokens[$i][0] === T_FUNCTION) { - if (!$this->isMethodAllowed($tokens, $i)) { + if (!$this->isMethodAllowed($tokens, $i, $class)) { break; } $isAnonymousFunction = false; @@ -241,20 +242,28 @@ protected function parseMethods(array $tokens): array return $methods; } - protected function isMethodAllowed(array $tokens, int $functionIndex): bool + /** + * @param array $tokens + * @param int $functionIndex + * @param string $class + * + * @return bool + */ + protected function isMethodAllowed(array $tokens, int $functionIndex, string $class): bool { - return $this->checkForPublicMethods($tokens, $functionIndex) && $this->checkForSimpleMethods($tokens, $functionIndex); + return $this->checkForPublicMethods($tokens, $functionIndex, $class) && $this->checkForSimpleMethods($tokens, $functionIndex); } /** * @param array $tokens * @param int $functionIndex + * @param string $class * * @return bool */ - protected function checkForPublicMethods(array $tokens, int $functionIndex): bool + protected function checkForPublicMethods(array $tokens, int $functionIndex, string $class): bool { - if (!$this->config->areOnlyPublicMethodsInstrumented()) { + if (!$this->config->areOnlyPublicMethodsInstrumented() || str_contains($class, 'Controller')) { return true; } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index a5dc8f7..67c5aad 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -84,6 +84,7 @@ function: \'%s\', ->setAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::CODE_NAMESPACE, $class) ->setAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::CODE_FILEPATH, $filename) ->setAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::CODE_LINENO, $lineno) + ->setAttribute(\\Spryker\\Service\\Opentelemetry\\Instrumentation\\Sampler\\CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, %s) ->startSpan(); \\OpenTelemetry\\Context\\Context::storage()->attach($span->storeInContext($context)); @@ -122,6 +123,7 @@ function: \'%s\', $class[static::CLASS_NAME_KEY], $method, $methodHookName, + $this->isCriticalHook($class) ? 'true' : 'null', ); } @@ -143,4 +145,14 @@ protected function buildMethodHookName(array $class, string $method): string $method, ); } + + /** + * @param array $class + * + * @return bool + */ + protected function isCriticalHook(array $class): bool + { + return str_contains($class[static::CLASS_NAME_KEY], 'Facade') || str_contains($class[static::CLASS_NAME_KEY], 'Controller'); + } } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 0bc6393..d688538 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -28,13 +28,13 @@ public function getExcludedDirs(): array 'OpenTelemetry', 'Dependency', 'Acl', - 'Gui', + //'Gui', 'GracefulRunner', 'AclEntity', 'Container', 'Transfer', - 'Kernel', - 'Application', + //'Kernel', + //'Application', 'Installer', 'Console', 'Config', @@ -42,7 +42,7 @@ public function getExcludedDirs(): array 'PropelReplicationCache', 'GitHook', 'ArchitectureSniffer', - 'Router', + //'Router', 'ZedNavigation', 'Acl', 'Twig', @@ -54,7 +54,7 @@ public function getExcludedDirs(): array 'Touch', 'Collector', 'NavigationGui', - 'Store', + //'Store', 'Log', 'Profiler', 'Propel', @@ -62,19 +62,19 @@ public function getExcludedDirs(): array 'PropelQueryBuilder', 'RabbitMq', 'Redis', - 'Session', + //'Session', 'SessionFile', 'SessionRedis', 'SessionUserValidation', 'Testify', - 'Validation', + //'Validation', 'Development', 'ErrorHandler', 'Glossary', 'GuiTable', 'ModuleFinder', 'Monitoring', - 'Search', + //'Search', 'SearchElasticsearch', 'SearchElasticsearchGui', 'Silex', @@ -93,14 +93,14 @@ public function getExcludedDirs(): array 'Http', 'SecuritySystemUser', 'SecurityOauthUser', - 'UserLocale', + //'UserLocale', 'AclMerchantAgent', - 'Merchant', - 'MerchantStock', - 'MerchantProfile', - 'MerchantGui', - 'MerchantUser', - 'MerchantCategory', + //'Merchant', + //'MerchantStock', + //'MerchantProfile', + //'MerchantGui', + //'MerchantUser', + //'MerchantCategory', 'ZedUi', 'templates', 'config', @@ -143,7 +143,6 @@ public function getExcludedSpans(): array 'BusinessOnBehalfGui-CustomerTableButtonCreator::addAttachCustomerToCompanyButton', 'BusinessOnBehalfWidget-BusinessOnBehalfStatusWidget::getName', 'BusinessOnBehalfWidget-BusinessOnBehalfStatusWidget::getTemplate', - 'Cart-CartFacade::cleanUpItems', 'Cart-CartFacade::expandItemGroupKeysWithCartIdentifier', 'Cart-GroupKeyExpander::expandItemGroupKeysWithCartIdentifier', 'Cart-NonPersistentProvider::addItems', @@ -277,7 +276,7 @@ public function getExcludedSpans(): array 'Currency-CurrencyFacade::fromIsoCode', 'Currency-CurrencyFacade::getAllStoresWithCurrencies', 'Currency-CurrencyFacade::getByIdCurrency', - 'Currency-CurrencyFacade::validateCurrencyInQuote', + //'Currency-CurrencyFacade::validateCurrencyInQuote', 'Currency-CurrencyReader::getAllStoresWithCurrencies', 'Currency-CurrencyReader::getByIdCurrency', 'Currency-CurrencyReader::getByIsoCode', @@ -329,13 +328,13 @@ public function getExcludedSpans(): array 'Discount-DecisionRuleOrSpecification::isSatisfiedBy', 'Discount-DiscountableItemFilter::filter', 'Discount-DiscountableItemTransformer::transformSplittableDiscountableItem', - 'Discount-DiscountFacade::calculatePercentageDiscount', - 'Discount-DiscountFacade::checkDiscountChanges', - 'Discount-DiscountFacade::collectBySku', - 'Discount-DiscountFacade::isCurrencyDecisionRuleSatisfiedBy', - 'Discount-DiscountFacade::isDayOfTheWeekSatisfiedBy', - 'Discount-DiscountFacade::isSubTotalSatisfiedBy', - 'Discount-DiscountFacade::queryStringCompare', +// 'Discount-DiscountFacade::calculatePercentageDiscount', +// 'Discount-DiscountFacade::checkDiscountChanges', +// 'Discount-DiscountFacade::collectBySku', +// 'Discount-DiscountFacade::isCurrencyDecisionRuleSatisfiedBy', +// 'Discount-DiscountFacade::isDayOfTheWeekSatisfiedBy', +// 'Discount-DiscountFacade::isSubTotalSatisfiedBy', +// 'Discount-DiscountFacade::queryStringCompare', 'Discount-Distributor::distributeDiscountAmountToDiscountableItems', 'Discount-Equal::compare', 'Discount-Equal::getAcceptedTypes', @@ -405,7 +404,9 @@ public function getExcludedSpans(): array 'GiftCard-ShipmentMethodGiftCardChecker::containsOnlyGiftCardItems', 'GiftCard-ShipmentMethodGiftCardDisallowedChecker::isShipmentMethodSuitable', 'GiftCard-ShipmentMethodGiftCardFilter::filter', - 'HomePage-IndexController::indexAction', + 'Kernel-ClassNameFinder::findClassName', + 'Kernel-AbstractClassResolver::resolve', + 'Kernel-ClassNameCandidatesBuilder::buildClassNames', 'LanguageSwitcherWidget-LanguageSwitcherWidget::getName', 'LanguageSwitcherWidget-LanguageSwitcherWidget::getTemplate', 'ManualOrderEntry-OrderSourceHydrator::hydrateOrderSource', @@ -445,10 +446,10 @@ public function getExcludedSpans(): array 'MerchantSalesOrderWidget-MerchantOrderReferenceForItemsWidget::getName', 'MerchantSalesReturnWidget-MerchantSalesReturnCreateFormWidget::getName', 'MerchantSearchWidget-MerchantSearchWidget::getName', - 'MerchantShipment-MerchantShipmentFacade::expandCartChangeShipmentWithMerchantReference', - 'MerchantShipment-MerchantShipmentFacade::expandQuoteShipmentWithMerchantReference', - 'MerchantShipment-ShipmentExpander::expandCartChangeShipmentWithMerchantReference', - 'MerchantShipment-ShipmentExpander::expandQuoteShipmentWithMerchantReference', +// 'MerchantShipment-MerchantShipmentFacade::expandCartChangeShipmentWithMerchantReference', +// 'MerchantShipment-MerchantShipmentFacade::expandQuoteShipmentWithMerchantReference', +// 'MerchantShipment-ShipmentExpander::expandCartChangeShipmentWithMerchantReference', +// 'MerchantShipment-ShipmentExpander::expandQuoteShipmentWithMerchantReference', 'MerchantSwitcherWidget-MerchantSwitcherSelectorFormWidget::getName', 'MerchantSwitcherWidget-MerchantSwitcherSelectorFormWidget::getTemplate', 'MerchantWidget-MerchantMetaSchemaWidget::getName', @@ -618,15 +619,15 @@ public function getExcludedSpans(): array 'Product-ProductConcreteManager::hasProductConcrete', 'Product-ProductConcreteNameGenerator::getLocalizedProductConcreteName', 'Product-ProductConcreteReadObserverPluginManager::read', - 'Product-ProductFacade::combineRawProductAttributes', - 'Product-ProductFacade::decodeProductAttributes', - 'Product-ProductFacade::findProductConcreteIdBySku', - 'Product-ProductFacade::findProductConcreteIdsByAbstractProductId', - 'Product-ProductFacade::getCombinedAbstractAttributeKeys', - 'Product-ProductFacade::getLocalizedProductConcreteName', - 'Product-ProductFacade::getRawProductAbstractTransfersByAbstractSkus', - 'Product-ProductFacade::getRawProductConcreteTransfersByConcreteSkus', - 'Product-ProductFacade::hasProductConcrete', +// 'Product-ProductFacade::combineRawProductAttributes', +// 'Product-ProductFacade::decodeProductAttributes', +// 'Product-ProductFacade::findProductConcreteIdBySku', +// 'Product-ProductFacade::findProductConcreteIdsByAbstractProductId', +// 'Product-ProductFacade::getCombinedAbstractAttributeKeys', +// 'Product-ProductFacade::getLocalizedProductConcreteName', +// 'Product-ProductFacade::getRawProductAbstractTransfersByAbstractSkus', +// 'Product-ProductFacade::getRawProductConcreteTransfersByConcreteSkus', +// 'Product-ProductFacade::hasProductConcrete', 'Product-SkuGenerator::generateProductAbstractSku', 'ProductAlternative-ProductAlternativeFacade::doAllConcreteProductsHaveAlternatives', 'ProductAlternative-ProductAlternativeFacade::findProductAbstractIdsWhichConcreteHasAlternative', @@ -705,10 +706,10 @@ public function getExcludedSpans(): array 'ProductGroupWidget-ProductGroupReader::getProductGroups', 'ProductGroupWidget-ProductGroupWidget::getName', 'ProductGroupWidget-ProductGroupWidget::getTemplate', - 'ProductImage-ProductImageFacade::createProductConcreteImageSetCollection', - 'ProductImage-ProductImageFacade::expandProductAbstractWithImageSets', - 'ProductImage-ProductImageFacade::expandProductConcreteTransfersWithImageSets', - 'ProductImage-ProductImageFacade::getProductImagesSetCollectionByProductAbstractId', +// 'ProductImage-ProductImageFacade::createProductConcreteImageSetCollection', +// 'ProductImage-ProductImageFacade::expandProductAbstractWithImageSets', +// 'ProductImage-ProductImageFacade::expandProductConcreteTransfersWithImageSets', +// 'ProductImage-ProductImageFacade::getProductImagesSetCollectionByProductAbstractId', 'ProductImage-Reader::expandProductAbstractWithImageSets', 'ProductImage-Reader::expandProductConcreteTransfersWithImageSets', 'ProductImage-Reader::getProductImagesSetCollectionByProductAbstractId', @@ -987,6 +988,7 @@ public function getExcludedSpans(): array 'StorageRouter-StorageUrlGenerator::generate', 'StorageRouter-StorageUrlGenerator::getContext', 'StorageRouter-StorageUrlGenerator::setContext', + 'Store-StoreReader::getStoreByName', 'StoreWidget-StoreSwitcherWidget::getName', 'StoreWidget-StoreSwitcherWidget::getTemplate', 'Synchronization-ExporterPluginResolver::getAvailableResourceNames', From c7698e2e5310ab48fcecd203890483043f602d66 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Wed, 4 Dec 2024 19:09:11 +0200 Subject: [PATCH 41/48] Disabled Kernel --- src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index d688538..3109a50 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -33,7 +33,7 @@ public function getExcludedDirs(): array 'AclEntity', 'Container', 'Transfer', - //'Kernel', + 'Kernel', //'Application', 'Installer', 'Console', From b3c193eda4ea145c9d4ed2a48c3f7e2cfd871134 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Thu, 5 Dec 2024 10:08:04 +0200 Subject: [PATCH 42/48] Reverted enabled modules --- .../Instrumentation/Span/SpanBuilder.php | 3 + .../Zed/Opentelemetry/OpentelemetryConfig.php | 58 ++++++++++--------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 0b949a1..731b8c2 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -184,6 +184,9 @@ public function startSpan(): SpanInterface $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); + $file = fopen(APPLICATION_ROOT_DIR . '/span' . $traceId, 'a'); + fwrite($file, $this->spanName . PHP_EOL); + fclose($file); $spanContext = SpanContext::create( $traceId, $spanId, diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 3109a50..f386782 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -28,13 +28,13 @@ public function getExcludedDirs(): array 'OpenTelemetry', 'Dependency', 'Acl', - //'Gui', + 'Gui', 'GracefulRunner', 'AclEntity', 'Container', 'Transfer', 'Kernel', - //'Application', + 'Application', 'Installer', 'Console', 'Config', @@ -42,7 +42,7 @@ public function getExcludedDirs(): array 'PropelReplicationCache', 'GitHook', 'ArchitectureSniffer', - //'Router', + 'Router', 'ZedNavigation', 'Acl', 'Twig', @@ -54,7 +54,7 @@ public function getExcludedDirs(): array 'Touch', 'Collector', 'NavigationGui', - //'Store', + 'Store', 'Log', 'Profiler', 'Propel', @@ -62,19 +62,19 @@ public function getExcludedDirs(): array 'PropelQueryBuilder', 'RabbitMq', 'Redis', - //'Session', + 'Session', 'SessionFile', 'SessionRedis', 'SessionUserValidation', 'Testify', - //'Validation', + 'Validation', 'Development', 'ErrorHandler', 'Glossary', 'GuiTable', 'ModuleFinder', 'Monitoring', - //'Search', + 'Search', 'SearchElasticsearch', 'SearchElasticsearchGui', 'Silex', @@ -93,14 +93,14 @@ public function getExcludedDirs(): array 'Http', 'SecuritySystemUser', 'SecurityOauthUser', - //'UserLocale', + 'UserLocale', 'AclMerchantAgent', - //'Merchant', - //'MerchantStock', - //'MerchantProfile', - //'MerchantGui', - //'MerchantUser', - //'MerchantCategory', + 'Merchant', + 'MerchantStock', + 'MerchantProfile', + 'MerchantGui', + 'MerchantUser', + 'MerchantCategory', 'ZedUi', 'templates', 'config', @@ -446,10 +446,8 @@ public function getExcludedSpans(): array 'MerchantSalesOrderWidget-MerchantOrderReferenceForItemsWidget::getName', 'MerchantSalesReturnWidget-MerchantSalesReturnCreateFormWidget::getName', 'MerchantSearchWidget-MerchantSearchWidget::getName', -// 'MerchantShipment-MerchantShipmentFacade::expandCartChangeShipmentWithMerchantReference', -// 'MerchantShipment-MerchantShipmentFacade::expandQuoteShipmentWithMerchantReference', -// 'MerchantShipment-ShipmentExpander::expandCartChangeShipmentWithMerchantReference', -// 'MerchantShipment-ShipmentExpander::expandQuoteShipmentWithMerchantReference', + 'MerchantShipment-ShipmentExpander::expandCartChangeShipmentWithMerchantReference', + 'MerchantShipment-ShipmentExpander::expandQuoteShipmentWithMerchantReference', 'MerchantSwitcherWidget-MerchantSwitcherSelectorFormWidget::getName', 'MerchantSwitcherWidget-MerchantSwitcherSelectorFormWidget::getTemplate', 'MerchantWidget-MerchantMetaSchemaWidget::getName', @@ -460,6 +458,9 @@ public function getExcludedSpans(): array 'Messenger-InMemoryMessageTray::getFlashMessagesTransfer', 'Messenger-InMemoryMessageTray::getMessages', 'Messenger-MessengerFacade::getStoredMessages', + 'Messenger-MessengerFacade::addSuccessMessage', + 'Messenger-SessionMessageTray::addSuccessMessage', + 'Messenger-MessageTranslator::translate', 'MoneyGui-MoneyType::buildForm', 'MoneyGui-MoneyType::buildView', 'MoneyGui-MoneyType::configureOptions', @@ -587,6 +588,7 @@ public function getExcludedSpans(): array 'PriceProductWidget-PriceProductWidget::getName', 'PriceWidget-PriceModeSwitcherWidget::getName', 'PriceWidget-PriceModeSwitcherWidget::getTemplate', + 'Product-ProductFacade::touchProductAbstract', 'Product-AbstractProductAbstractManagerSubject::attachAfterCreateObserver', 'Product-AbstractProductAbstractManagerSubject::attachAfterUpdateObserver', 'Product-AbstractProductAbstractManagerSubject::attachBeforeCreateObserver', @@ -619,15 +621,6 @@ public function getExcludedSpans(): array 'Product-ProductConcreteManager::hasProductConcrete', 'Product-ProductConcreteNameGenerator::getLocalizedProductConcreteName', 'Product-ProductConcreteReadObserverPluginManager::read', -// 'Product-ProductFacade::combineRawProductAttributes', -// 'Product-ProductFacade::decodeProductAttributes', -// 'Product-ProductFacade::findProductConcreteIdBySku', -// 'Product-ProductFacade::findProductConcreteIdsByAbstractProductId', -// 'Product-ProductFacade::getCombinedAbstractAttributeKeys', -// 'Product-ProductFacade::getLocalizedProductConcreteName', -// 'Product-ProductFacade::getRawProductAbstractTransfersByAbstractSkus', -// 'Product-ProductFacade::getRawProductConcreteTransfersByConcreteSkus', -// 'Product-ProductFacade::hasProductConcrete', 'Product-SkuGenerator::generateProductAbstractSku', 'ProductAlternative-ProductAlternativeFacade::doAllConcreteProductsHaveAlternatives', 'ProductAlternative-ProductAlternativeFacade::findProductAbstractIdsWhichConcreteHasAlternative', @@ -923,6 +916,16 @@ public function getExcludedSpans(): array 'SessionAgentValidation-SessionAgentValidationSessionUpdater::update', 'SessionCustomerValidationPage-SaveCustomerSessionEventSubscriber::getSubscribedEvents', 'SessionCustomerValidationPage-SessionCustomerValidationSecurityExtender::extend', + 'Session-SessionStorage::getOptions', + 'Session-SessionStorageOptions::getOptions', + 'Session-SessionStorage::getAndRegisterHandler', + 'Session-SessionStorageHandlerPool::getHandler', + 'Session-SaveSessionListener::getSubscribedEvents', + 'User-UserReader::getUserCollection', + 'UserLocale-UserLocaleFacade::expandUserCollectionWithLocale', + 'UserLocale-UserExpander::expandUserCollectionWithLocale', + 'Router-ControllerResolver::getControllerFromArray', + 'Router-ControllerResolver::injectContainerAndInitialize', 'SharedCart-CustomerShareCartQuoteResponseExpander::expand', 'SharedCart-QuoteActivator::setDefaultQuote', 'SharedCart-QuoteCompanyUserWriter::updateQuoteCompanyUsers', @@ -985,6 +988,7 @@ public function getExcludedSpans(): array 'ShopUi-NumberFormatterTwigExtender::extend', 'Stock-StockFacade::isProductAbstractNeverOutOfStockForStore', 'Stock-StockProductReader::isProductAbstractNeverOutOfStockForStore', + 'Store-StoreFacade::isDynamicStoreEnabled', 'StorageRouter-StorageUrlGenerator::generate', 'StorageRouter-StorageUrlGenerator::getContext', 'StorageRouter-StorageUrlGenerator::setContext', From dffb37e153d8c260a8302d0da7ad9fe52cdef3b0 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Thu, 5 Dec 2024 10:23:26 +0200 Subject: [PATCH 43/48] Reverted enabled modules --- .../Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php index 731b8c2..0b949a1 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanBuilder.php @@ -184,9 +184,6 @@ public function startSpan(): SpanInterface $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); - $file = fopen(APPLICATION_ROOT_DIR . '/span' . $traceId, 'a'); - fwrite($file, $this->spanName . PHP_EOL); - fclose($file); $spanContext = SpanContext::create( $traceId, $spanId, From 3480f4a5d963db1c27de26057e8c66122aa0f729 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Thu, 5 Dec 2024 17:21:25 +0200 Subject: [PATCH 44/48] Fixes after rewiew and test of big hook file --- .github/workflows/ci.yml | 4 +-- .../Span/AttributesBuilder.php | 4 +++ .../Instrumentation/Span/Span.php | 6 ++-- .../Instrumentation/Span/SpanContext.php | 3 ++ .../Instrumentation/Span/SpanConverter.php | 33 +++++++++++++++++++ .../SpanIdUpdateAwareSpanContextInterface.php | 1 + .../PostFilterBatchSpanProcessor.php | 6 ++++ .../SprykerInstrumentationBootstrap.php | 15 +++++++-- .../OpentelemetryInstrumentationConfig.php | 2 +- ...OpentelemetryMonitoringExtensionPlugin.php | 4 +-- .../Business/Generator/HookGenerator.php | 2 +- .../Zed/Opentelemetry/OpentelemetryConfig.php | 14 ++++---- 12 files changed, 76 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c4979b..3608bf2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,8 +14,8 @@ jobs: fail-fast: false matrix: php-version: [ - '8.1', - '8.2' + '8.2', + '8.3' ] steps: diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php index bb564e2..4b9cf71 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/AttributesBuilder.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Common\Attribute\AttributeValidatorInterface; use OpenTelemetry\SemConv\TraceAttributes; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanRatioSampler; +use Spryker\Service\Opentelemetry\Instrumentation\SprykerInstrumentationBootstrap; class AttributesBuilder implements AttributesBuilderInterface { @@ -140,6 +141,9 @@ protected function getSafeAttributes(): array 'root.url', TraceAttributes::URL_DOMAIN, CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, + CriticalSpanRatioSampler::NO_CRITICAL_ATTRIBUTE, + SprykerInstrumentationBootstrap::ATTRIBUTE_HTTP_METHOD, + SprykerInstrumentationBootstrap::ATTRIBUTE_IS_DETAILED_TRACE, ]; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php index a307645..7b9f372 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/Span.php @@ -99,7 +99,7 @@ protected function __construct( * @param \OpenTelemetry\SDK\Trace\SpanProcessorInterface $spanProcessor * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource * @param \OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface $attributesBuilder - * @param array $links + * @param list<\OpenTelemetry\SDK\Trace\LinkInterface> $links * @param int $totalRecordedLinks * @param int $startEpochNanos * @@ -485,7 +485,7 @@ public function getAttributes(): AttributesInterface } /** - * @return \OpenTelemetry\SDK\Trace\EventInterface[] + * @return array<\OpenTelemetry\SDK\Trace\EventInterface> */ public function getEvents(): array { @@ -493,7 +493,7 @@ public function getEvents(): array } /** - * @return \OpenTelemetry\SDK\Trace\LinkInterface[] + * @return array<\OpenTelemetry\SDK\Trace\LinkInterface> */ public function getLinks(): array { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php index 272d16a..341afa7 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanContext.php @@ -15,6 +15,9 @@ class SpanContext implements SpanContextInterface, SpanIdUpdateAwareSpanContextInterface { + /** + * @var \OpenTelemetry\API\Trace\SpanContextInterface|null + */ protected static ?SpanContextInterface $invalidContext = null; /** diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php index 56e2b9a..1101dc9 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanConverter.php @@ -85,6 +85,11 @@ public function convert(iterable $spans): ExportTraceServiceRequest return $pExportTraceServiceRequest; } + /** + * @param \OpenTelemetry\SDK\Resource\ResourceInfo $resource + * + * @return \Opentelemetry\Proto\Trace\V1\ResourceSpans + */ protected function convertResourceSpans(ResourceInfo $resource): ResourceSpans { $pResourceSpans = new ResourceSpans(); @@ -96,6 +101,11 @@ protected function convertResourceSpans(ResourceInfo $resource): ResourceSpans return $pResourceSpans; } + /** + * @param \OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface $instrumentationScope + * + * @return \Opentelemetry\Proto\Trace\V1\ScopeSpans + */ protected function convertScopeSpans(InstrumentationScopeInterface $instrumentationScope): ScopeSpans { $pScopeSpans = new ScopeSpans(); @@ -111,6 +121,9 @@ protected function convertScopeSpans(InstrumentationScopeInterface $instrumentat /** * @param Resource_|Span|Event|Link|InstrumentationScope $pElement + * @param \OpenTelemetry\SDK\Common\Attribute\AttributesInterface $attributes + * + * @return void */ protected function setAttributes($pElement, AttributesInterface $attributes): void { @@ -123,6 +136,11 @@ protected function setAttributes($pElement, AttributesInterface $attributes): vo $pElement->setDroppedAttributesCount($attributes->getDroppedAttributesCount()); } + /** + * @param int $kind + * + * @return int + */ protected function convertSpanKind(int $kind): int { return match ($kind) { @@ -135,6 +153,11 @@ protected function convertSpanKind(int $kind): int }; } + /** + * @param string $status + * + * @return int + */ protected function convertStatusCode(string $status): int { switch ($status) { @@ -146,6 +169,11 @@ protected function convertStatusCode(string $status): int return StatusCode::STATUS_CODE_UNSET; } + /** + * @param \OpenTelemetry\SDK\Trace\SpanDataInterface $span + * + * @return \Opentelemetry\Proto\Trace\V1\Span + */ protected function convertSpan(SpanDataInterface $span): Span { $pSpan = new Span(); @@ -190,6 +218,11 @@ protected function convertSpan(SpanDataInterface $span): Span return $pSpan; } + /** + * @param \OpenTelemetry\API\Trace\SpanContextInterface $spanContext + * + * @return int + */ protected static function traceFlags(SpanContextInterface $spanContext): int { $flags = $spanContext->getTraceFlags(); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php index 296435a..9307d55 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Span/SpanIdUpdateAwareSpanContextInterface.php @@ -6,6 +6,7 @@ interface SpanIdUpdateAwareSpanContextInterface { /** * @param string $spanId + * * @return void */ public function updateSpanId(string $spanId): void; diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php index 8c2f26d..b44abbb 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SpanProcessor/PostFilterBatchSpanProcessor.php @@ -314,6 +314,12 @@ protected function setScheduledDelayTime(int $scheduledDelayMillis): void $this->scheduledDelayNanos = $scheduledDelayMillis * 1_000_000; } + /** + * @param int $maxExportBatchSize + * @param int $maxQueueSize + * + * @return void + */ protected function setMaxExportBatchSize(int $maxExportBatchSize, int $maxQueueSize): void { if ($maxExportBatchSize <= 0) { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 93b2614..32567a2 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -50,6 +50,16 @@ class SprykerInstrumentationBootstrap */ public const NAME = 'spryker'; + /** + * @var string + */ + public const ATTRIBUTE_IS_DETAILED_TRACE = 'is_full_trace'; + + /** + * @var string + */ + public const ATTRIBUTE_HTTP_METHOD = 'method'; + /** * @var string */ @@ -97,6 +107,7 @@ public static function register(): void ShutdownHandler::register($tracerProvider->shutdown(...)); ShutdownHandler::register([static::class, 'shutdownHandler']); + include_once APPLICATION_ROOT_DIR . '/src/Generated/OpenTelemetry/Hooks/BigHookHook.php'; } /** @@ -216,8 +227,8 @@ protected static function registerRootSpan(string $servicedName, Request $reques ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) - ->setAttribute('is_full_trace', !TraceSampleResult::shouldSkipTraceBody()) - ->setAttribute('method', $request->getMethod()) + ->setAttribute(static::ATTRIBUTE_IS_DETAILED_TRACE, TraceSampleResult::shouldSkipTraceBody() ? null : false) + ->setAttribute(static::ATTRIBUTE_HTTP_METHOD, $request->getMethod()) ->startSpan(); Context::storage()->attach($span->storeInContext($parent)); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index 6aa9e82..04d9108 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -180,7 +180,7 @@ public static function getSamplerProbability(): float { $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.4; - return (float)0.4; + return (float)$probability; } /** diff --git a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php index f1bffd3..ba40ddd 100644 --- a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php +++ b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php @@ -19,7 +19,7 @@ class OpentelemetryMonitoringExtensionPlugin extends AbstractPlugin implements M { /** * Specification: - * - Adds error in to the current active span + * - Adds error to the current active span * * @api * @@ -58,7 +58,7 @@ public function setApplicationName(?string $application = null, ?string $store = /** * Specification: - * - Sets name for the root span. If no name provided, default name will be generated. + * - Sets name for the root span. If no name was provided, default name will be generated. * - This will affect only root span as it will not update the current possible span name. * * @api diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php index dba4d76..08706ff 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php @@ -127,7 +127,7 @@ protected function getOutputFilepathByModule(array $class): string return sprintf( static::OUTPUT_FILE_PATH_PLACEHOLDER_BY_MODULE, $this->config->getOutputDir(), - $moduleNamePattern, + 'BigHook', ); } } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index f386782..3ec6060 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -328,13 +328,13 @@ public function getExcludedSpans(): array 'Discount-DecisionRuleOrSpecification::isSatisfiedBy', 'Discount-DiscountableItemFilter::filter', 'Discount-DiscountableItemTransformer::transformSplittableDiscountableItem', -// 'Discount-DiscountFacade::calculatePercentageDiscount', -// 'Discount-DiscountFacade::checkDiscountChanges', -// 'Discount-DiscountFacade::collectBySku', -// 'Discount-DiscountFacade::isCurrencyDecisionRuleSatisfiedBy', -// 'Discount-DiscountFacade::isDayOfTheWeekSatisfiedBy', -// 'Discount-DiscountFacade::isSubTotalSatisfiedBy', -// 'Discount-DiscountFacade::queryStringCompare', + 'Discount-DiscountFacade::calculatePercentageDiscount', + 'Discount-DiscountFacade::checkDiscountChanges', + 'Discount-DiscountFacade::collectBySku', + 'Discount-DiscountFacade::isCurrencyDecisionRuleSatisfiedBy', + 'Discount-DiscountFacade::isDayOfTheWeekSatisfiedBy', + 'Discount-DiscountFacade::isSubTotalSatisfiedBy', + 'Discount-DiscountFacade::queryStringCompare', 'Discount-Distributor::distributeDiscountAmountToDiscountableItems', 'Discount-Equal::compare', 'Discount-Equal::getAcceptedTypes', From aca3018d74cb7d06adca28dcb72c0c24a595bc6f Mon Sep 17 00:00:00 2001 From: gechetspr Date: Thu, 5 Dec 2024 19:11:08 +0200 Subject: [PATCH 45/48] Changed detailed flag --- .../Instrumentation/SprykerInstrumentationBootstrap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 32567a2..7995ed9 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -53,7 +53,7 @@ class SprykerInstrumentationBootstrap /** * @var string */ - public const ATTRIBUTE_IS_DETAILED_TRACE = 'is_full_trace'; + public const ATTRIBUTE_IS_DETAILED_TRACE = 'detailed'; /** * @var string @@ -227,7 +227,7 @@ protected static function registerRootSpan(string $servicedName, Request $reques ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) - ->setAttribute(static::ATTRIBUTE_IS_DETAILED_TRACE, TraceSampleResult::shouldSkipTraceBody() ? null : false) + ->setAttribute(static::ATTRIBUTE_IS_DETAILED_TRACE, TraceSampleResult::shouldSkipTraceBody() ? false : null) ->setAttribute(static::ATTRIBUTE_HTTP_METHOD, $request->getMethod()) ->startSpan(); From b3af58a74a7d887ea88dd8c961a1fdde40ad0751 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Fri, 6 Dec 2024 12:16:20 +0200 Subject: [PATCH 46/48] Default values for config and disabled additional instrumentation --- .../SprykerInstrumentationBootstrap.php | 36 ++++++++++++++++--- .../OpentelemetryInstrumentationConfig.php | 12 +++---- .../Business/Generator/HookGenerator.php | 14 ++++---- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 7995ed9..0bc0fa2 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -38,6 +38,7 @@ use Spryker\Service\Opentelemetry\Storage\RootSpanNameStorage; use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; +use Spryker\Zed\Opentelemetry\Business\Generator\HookGenerator; use Symfony\Component\HttpFoundation\Request; /** @@ -68,7 +69,17 @@ class SprykerInstrumentationBootstrap /** * @var string */ - protected const INSTRUMENTATION_VERSION = '0.1'; + protected const INSTRUMENTATION_VERSION = '1.0'; + + /** + * @var string + */ + protected const ZED_BIN_FILE_NAME = 'console'; + + /** + * @var string + */ + protected const ZED_CLI_APPLICATION_NAME = 'CLI ZED'; /** * @var \Spryker\Service\Opentelemetry\Instrumentation\Resource\ResourceInfo|null @@ -107,7 +118,22 @@ public static function register(): void ShutdownHandler::register($tracerProvider->shutdown(...)); ShutdownHandler::register([static::class, 'shutdownHandler']); - include_once APPLICATION_ROOT_DIR . '/src/Generated/OpenTelemetry/Hooks/BigHookHook.php'; + + static::registerAdditionalHooks(); + } + + /** + * @return void + */ + protected static function registerAdditionalHooks(): void + { + if (TraceSampleResult::shouldSkipTraceBody()) { + putenv('OTEL_PHP_DISABLED_INSTRUMENTATIONS=all'); + + return; + } + + include_once sprintf('%s/src/Generated/OpenTelemetry/Hooks/%s.php', APPLICATION_ROOT_DIR, HookGenerator::GLOBAL_HOOK_FILE_NAME); } /** @@ -188,8 +214,8 @@ protected static function resolveServiceName(): string if ($cli) { [$vendor, $bin, $application] = explode('/', $cli[0]); - if ($application === 'console') { - return 'CLI ZED'; + if ($application === static::ZED_BIN_FILE_NAME) { + return static::ZED_CLI_APPLICATION_NAME; } return sprintf('CLI %s', strtoupper($application)); @@ -227,7 +253,7 @@ protected static function registerRootSpan(string $servicedName, Request $reques ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) - ->setAttribute(static::ATTRIBUTE_IS_DETAILED_TRACE, TraceSampleResult::shouldSkipTraceBody() ? false : null) + ->setAttribute(static::ATTRIBUTE_IS_DETAILED_TRACE, !TraceSampleResult::shouldSkipTraceBody()) ->setAttribute(static::ATTRIBUTE_HTTP_METHOD, $request->getMethod()) ->startSpan(); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index 04d9108..b83c447 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -84,7 +84,7 @@ class OpentelemetryInstrumentationConfig */ public static function getSamplerThresholdNano(): int { - $multiplicator = getenv(static::OTEL_BSP_MIN_SPAN_DURATION_THRESHOLD) ?: 1; + $multiplicator = getenv(static::OTEL_BSP_MIN_SPAN_DURATION_THRESHOLD) ?: 20; return $multiplicator * 1000000; } @@ -99,7 +99,7 @@ public static function getSamplerThresholdNano(): int */ public static function getSamplerThresholdNanoForCriticalSpan(): int { - $multiplicator = getenv(static::OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD) ?: 1; + $multiplicator = getenv(static::OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD) ?: 10; return $multiplicator * 1000000; } @@ -178,7 +178,7 @@ public static function getDefaultServiceName(): string */ public static function getSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.4; + $probability = getenv(static::OTEL_TRACES_SAMPLER_ARG) ?: 0.3; return (float)$probability; } @@ -190,7 +190,7 @@ public static function getSamplerProbability(): float */ public static function getSamplerProbabilityForCriticalSpans(): float { - $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.8; + $probability = getenv(static::OTEL_TRACES_CRITICAL_SAMPLER_ARG) ?: 0.5; return (float)$probability; } @@ -214,7 +214,7 @@ public static function getSpanProcessorScheduleDelay(): int { $delay = getenv(static::OTEL_BSP_SCHEDULE_DELAY); if ($delay === false) { - return 5000; + return 1000; } return (int)$delay; @@ -251,7 +251,7 @@ public static function getSpanProcessorMaxBatchSize(): int */ public static function getTraceSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.5; + $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.1; return (float)$probability; } diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php index 08706ff..7c3af0f 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/HookGenerator.php @@ -15,19 +15,19 @@ class HookGenerator implements HookGeneratorInterface { /** - * @var int + * @var string */ - protected const DIRECTORY_PERMISSIONS = 0755; + public const GLOBAL_HOOK_FILE_NAME = 'GlobalHook'; /** - * @var string + * @var int */ - protected const OUTPUT_FILE_PATH_PLACEHOLDER = '%s/%s-%sHook.php'; + protected const DIRECTORY_PERMISSIONS = 0755; /** * @var string */ - protected const OUTPUT_FILE_PATH_PLACEHOLDER_BY_MODULE = '%s/%sHook.php'; + protected const OUTPUT_FILE_PATH_PLACEHOLDER_GLOBAL = '%s/%s.php'; /** * @var string @@ -125,9 +125,9 @@ protected function getOutputFilepathByModule(array $class): string $namespace = explode('\\', $class[static::NAMESPACE_KEY]); $moduleNamePattern = $namespace[0] . $namespace[1] . $namespace[2]; return sprintf( - static::OUTPUT_FILE_PATH_PLACEHOLDER_BY_MODULE, + static::OUTPUT_FILE_PATH_PLACEHOLDER_GLOBAL, $this->config->getOutputDir(), - 'BigHook', + static::GLOBAL_HOOK_FILE_NAME, ); } } From 52ed7fb1b781e6a2b8bbe942f37b8fa2d5556ad6 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Fri, 6 Dec 2024 14:35:40 +0200 Subject: [PATCH 47/48] Fixes after a code review --- .../Resource/CompositeResourceDetector.php | 1 - ...OpentelemetryMonitoringExtensionPlugin.php | 10 ++++----- .../Storage/ResourceNameStorage.php | 3 +++ .../Storage/ResourceNameStorageInterface.php | 5 +++++ .../ContentCreator/HookContentCreator.php | 7 ++++++- .../Zed/Opentelemetry/OpentelemetryConfig.php | 21 +++++++++++++++---- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php index 7d6849f..cfd5a4f 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Resource/CompositeResourceDetector.php @@ -11,7 +11,6 @@ class CompositeResourceDetector implements ResourceDetectorInterface { - /** * @param array<\OpenTelemetry\SDK\Resource\ResourceDetectorInterface> $resourceDetectors */ diff --git a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php index ba40ddd..d241d8e 100644 --- a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php +++ b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php @@ -19,7 +19,7 @@ class OpentelemetryMonitoringExtensionPlugin extends AbstractPlugin implements M { /** * Specification: - * - Adds error to the current active span + * - Adds error to the current active span. * * @api * @@ -74,7 +74,7 @@ public function setTransactionName(string $name): void /** * Specification: - * - Opentelemetry instrumentation is completely custom. + * - Opentelemetry instrumentation doesn't require additional calls to start ot end transaction methods. * * @api * @@ -87,7 +87,7 @@ public function markStartTransaction(): void /** * Specification: - * - Opentelemetry instrumentation is completely custom. + * - Opentelemetry instrumentation doesn't require additional calls to start ot end transaction methods. * * @api * @@ -100,7 +100,7 @@ public function markEndOfTransaction(): void /** * Specification: - * - Will be fixed in stable version. Not in use for now + * - Transaction should be ignored before it was started in Opentelemetery in order to not generate additional load to the system. * * @api * @@ -112,7 +112,7 @@ public function markIgnoreTransaction(): void /** * Specification: - * - Opentelemetry has not attributes to specify background jobs. Service name already defined for CLI commands + * - Opentelemetry has no attributes to specify background jobs. Service name already defined for CLI commands. * * @api * diff --git a/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php index a4da486..c815ee1 100644 --- a/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php +++ b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorage.php @@ -4,6 +4,9 @@ class ResourceNameStorage implements ResourceNameStorageInterface { + /** + * @var \Spryker\Service\Opentelemetry\Storage\ResourceNameStorage|null + */ private static ?ResourceNameStorage $instance = null; /** diff --git a/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php index df95bad..d074567 100644 --- a/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php +++ b/src/Spryker/Service/Opentelemetry/Storage/ResourceNameStorageInterface.php @@ -4,6 +4,11 @@ interface ResourceNameStorageInterface { + /** + * @param string $name + * + * @return void + */ public function setName(string $name): void; /** diff --git a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php index 67c5aad..2c83535 100644 --- a/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php +++ b/src/Spryker/Zed/Opentelemetry/Business/Generator/ContentCreator/HookContentCreator.php @@ -153,6 +153,11 @@ protected function buildMethodHookName(array $class, string $method): string */ protected function isCriticalHook(array $class): bool { - return str_contains($class[static::CLASS_NAME_KEY], 'Facade') || str_contains($class[static::CLASS_NAME_KEY], 'Controller'); + foreach ($this->config->getCriticalClassNamePatterns() as $classNamePattern) { + if (str_contains($class[static::CLASS_NAME_KEY], $classNamePattern)) { + return true; + } + } + return false; } } diff --git a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php index 3ec6060..1eb578d 100644 --- a/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php +++ b/src/Spryker/Zed/Opentelemetry/OpentelemetryConfig.php @@ -699,10 +699,6 @@ public function getExcludedSpans(): array 'ProductGroupWidget-ProductGroupReader::getProductGroups', 'ProductGroupWidget-ProductGroupWidget::getName', 'ProductGroupWidget-ProductGroupWidget::getTemplate', -// 'ProductImage-ProductImageFacade::createProductConcreteImageSetCollection', -// 'ProductImage-ProductImageFacade::expandProductAbstractWithImageSets', -// 'ProductImage-ProductImageFacade::expandProductConcreteTransfersWithImageSets', -// 'ProductImage-ProductImageFacade::getProductImagesSetCollectionByProductAbstractId', 'ProductImage-Reader::expandProductAbstractWithImageSets', 'ProductImage-Reader::expandProductConcreteTransfersWithImageSets', 'ProductImage-Reader::getProductImagesSetCollectionByProductAbstractId', @@ -1097,4 +1093,21 @@ public function areOnlyPublicMethodsInstrumented(): bool { return true; } + + /** + * Specification: + * - List of class names or part of class names that should be considered as critical. + * - Critical classes will generate hooks that are marked as critical and will be process with more prio to show. + * + * @api + * + * @return array + */ + public function getCriticalClassNamePatterns(): array + { + return [ + 'Facade', + 'Controller', + ]; + } } From fb88dca5d20b6f699f7a1c086370f6f04015ddb4 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Fri, 6 Dec 2024 15:52:57 +0200 Subject: [PATCH 48/48] Updated requirements --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index 74f2984..a42e209 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,12 @@ "description": "Opentelemetry module", "license": "proprietary", "require": { + "ext-grpc": "*", + "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", + "open-telemetry/exporter-otlp": "^1.0", + "open-telemetry/gen-otlp-protobuf": "^1.1", + "open-telemetry/transport-grpc": "^1.0", "open-telemetry/sdk": "^1.0", "open-telemetry/sem-conv": "^1.0", "php": ">=8.2",