From 80106db716ee5e4d96ab50c0a9b7f9675af31f69 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Tue, 7 Jan 2025 10:17:47 +0200 Subject: [PATCH 1/5] Moved instrumentations to main module --- _register.php | 8 + .../ElasticaInstrumentation.php | 125 +++++++ .../Instrumentation/PropelInstrumentation.php | 102 ++++++ .../RabbitMqInstrumentation.php | 163 +++++++++ .../Instrumentation/RedisInstrumentation.php | 338 ++++++++++++++++++ 5 files changed, 736 insertions(+) create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php create mode 100644 src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php diff --git a/_register.php b/_register.php index f16bdbe..9c1d5a6 100644 --- a/_register.php +++ b/_register.php @@ -3,6 +3,10 @@ declare(strict_types=1); use OpenTelemetry\SDK\Sdk; +use Spryker\Service\Opentelemetry\Instrumentation\ElasticaInstrumentation; +use Spryker\Service\Opentelemetry\Instrumentation\PropelInstrumentation; +use Spryker\Service\Opentelemetry\Instrumentation\RabbitMqInstrumentation; +use Spryker\Service\Opentelemetry\Instrumentation\RedisInstrumentation; use Spryker\Service\Opentelemetry\Instrumentation\SprykerInstrumentationBootstrap; if (!class_exists(Sdk::class)) { @@ -18,3 +22,7 @@ } SprykerInstrumentationBootstrap::register(); +ElasticaInstrumentation::register(); +PropelInstrumentation::register(); +RabbitMqInstrumentation::register(); +RedisInstrumentation::register(); diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php new file mode 100644 index 0000000..8371d87 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php @@ -0,0 +1,125 @@ +tracer() + ->spanBuilder(static::SPAN_NAME) + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) + ->setAttribute(static::ATTRIBUTE_SEARCH_INDEX, $params[0]) + ->setAttribute(static::ATTRIBUTE_SEARCH_QUERY, serialize($params[2])) + ->setAttribute(static::ATTRIBUTE_ROOT_URL, $request->getRequest()->getUri()) + ->setAttribute(TraceAttributes::URL_DOMAIN, $request->getRequest()->headers->get(static::HEADER_HOST)) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: function (Client $client, array $params, $response, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + + $scope = Context::storage()->scope(); + + if ($scope === null) { + return; + } + + $scope->detach(); + $span = Span::fromContext($scope->context()); + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setAttribute(static::ATTRIBUTE_QUERY_TIME, $response->getQueryTime()); + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php new file mode 100644 index 0000000..1b9468a --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php @@ -0,0 +1,102 @@ +getStatement()->queryString; + $criticalAttr = str_contains($query, 'SELECT') ? CriticalSpanRatioSampler::NO_CRITICAL_ATTRIBUTE : CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE; + $span = CachedInstrumentation::getCachedInstrumentation() + ->tracer() + ->spanBuilder(sprintf(static::SPAN_NAME_PATTERN, substr($query, 0, 20))) + ->setParent($context) + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setAttribute(static::ATTRIBUTE_QUERY, $query) + ->setAttribute($criticalAttr, true) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: function (StatementInterface $statement, array $params, $response, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + + $scope = Context::storage()->scope(); + + if ($scope === null) { + return; + } + + $scope->detach(); + + $span = Span::fromContext($scope->context()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + } + ); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php new file mode 100644 index 0000000..58d9ad3 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php @@ -0,0 +1,163 @@ + static::SPAN_NAME_SEND_MESSAGE, + static::FUNCTION_SEND_MESSAGES => static::SPAN_NAME_SEND_MESSAGES, + ]; + + foreach ($functions as $function => $spanName) { + static::registerHook($function, $spanName); + } + } + + /** + * @param string $functionName + * @param string $spanName + * + * @return void + */ + protected static function registerHook(string $functionName, string $spanName): void + { + if (!class_exists(RabbitMqAdapter::class) || Sdk::isInstrumentationDisabled(static::NAME) === true) { + return; + } + + $instrumentation = CachedInstrumentation::getCachedInstrumentation(); + $request = (new RequestProcessor())->getRequest(); + + hook( + class: RabbitMqAdapter::class, + function: $functionName, + pre: function (RabbitMqAdapter $rabbitMqAdapter, array $params) use ($instrumentation, $spanName, $request): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder($spanName) + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) + ->setAttribute(TraceAttributes::HTTP_REQUEST_METHOD, $request->getMethod()) + ->setAttribute(static::ATTRIBUTE_QUEUE_NAME, $params[0]); + + if (static::isValidMessage($params)) { + $eventQueueSendMessageBodyArray = json_decode($params[1][0]->getBody(), true); + if (array_key_exists(EventQueueSendMessageBodyTransfer::EVENT_NAME, $eventQueueSendMessageBodyArray)) { + $span->setAttribute(TraceAttributes::EVENT_NAME, $eventQueueSendMessageBodyArray[EventQueueSendMessageBodyTransfer::EVENT_NAME]); + } + if (array_key_exists(EventQueueSendMessageBodyTransfer::LISTENER_CLASS_NAME, $eventQueueSendMessageBodyArray)) { + $span->setAttribute(static::ATTRIBUTE_EVENT_LISTENER_CLASS_NAME, $eventQueueSendMessageBodyArray[EventQueueSendMessageBodyTransfer::LISTENER_CLASS_NAME]); + } + } + + $span = $span->setAttribute(TraceAttributes::URL_DOMAIN, $request->headers->get(static::HEADER_HOST)) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: function (RabbitMqAdapter $rabbitMqAdapter, array $params, $response, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + } + ); + } + + /** + * @param array $params + * + * @return bool + */ + protected static function isValidMessage(array $params): bool + { + $queueSendMessageTransfer = $params[1][0] ?? null; + + if ($queueSendMessageTransfer === null) { + return false; + } + + return $queueSendMessageTransfer instanceof QueueSendMessageTransfer + && is_string($queueSendMessageTransfer->getBody()); + } +} diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php new file mode 100644 index 0000000..cc2bc17 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php @@ -0,0 +1,338 @@ +tracer() + ->spanBuilder('Redis::select') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_NAMESPACE, $params[0]) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'get', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::get') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, isset($params[0]) ? 'GET ' . $params[0] : 'undefined') + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'eval', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::eval') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(static::PARAM_EVAL_SCRIPT, $params[0] ?? 'undefined') + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'exists', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::exists') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', $params)) + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'mset', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::mset') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', array_keys($params[0]))) + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'msetnx', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::msetnx') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', array_keys($params[0]))) + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'set', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::set') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, $params[0] ?? 'undefined') + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + + hook( + Redis::class, + 'setex', + pre: static function (Redis $redis, array $params) use ($instrumentation): void { + + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $context = Context::getCurrent(); + $span = $instrumentation->tracer() + ->spanBuilder('Redis::set') + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setParent($context) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, $params[0] ?? 'undefined') + ->setAttribute(static::PARAM_EXPIRATION, $params[0] ?? 'undefined') + ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->startSpan(); + + Context::storage()->attach($span->storeInContext($context)); + }, + post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + if (TraceSampleResult::shouldSkipTraceBody()) { + return; + } + $span = Span::fromContext(Context::getCurrent()); + + if ($exception !== null) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR); + } else { + $span->setStatus(StatusCode::STATUS_OK); + } + + $span->end(); + }, + ); + } +} From cb16211f9e7129a7c4341b7644b01b9dacce0c0a Mon Sep 17 00:00:00 2001 From: gechetspr Date: Thu, 9 Jan 2025 17:14:35 +0200 Subject: [PATCH 2/5] Added custom events processing --- _register.php | 2 +- composer.json | 4 +- .../ElasticaInstrumentation.php | 7 +- .../Instrumentation/PropelInstrumentation.php | 7 +- .../RabbitMqInstrumentation.php | 7 +- .../Instrumentation/RedisInstrumentation.php | 132 +++++------------- .../Sampler/TraceSampleResult.php | 10 +- .../SprykerInstrumentationBootstrap.php | 14 +- .../OpentelemetryInstrumentationConfig.php | 23 ++- .../Opentelemetry/OpentelemetryService.php | 15 ++ .../OpentelemetryServiceFactory.php | 10 ++ .../OpentelemetryServiceInterface.php | 13 ++ ...OpentelemetryMonitoringExtensionPlugin.php | 17 ++- .../Storage/CustomEventsStorage.php | 53 +++++++ .../Storage/CustomEventsStorageInterface.php | 29 ++++ 15 files changed, 224 insertions(+), 119 deletions(-) create mode 100644 src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorage.php create mode 100644 src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorageInterface.php diff --git a/_register.php b/_register.php index 9c1d5a6..afbf15d 100644 --- a/_register.php +++ b/_register.php @@ -21,8 +21,8 @@ return; } -SprykerInstrumentationBootstrap::register(); ElasticaInstrumentation::register(); PropelInstrumentation::register(); RabbitMqInstrumentation::register(); RedisInstrumentation::register(); +SprykerInstrumentationBootstrap::register(); diff --git a/composer.json b/composer.json index a42e209..7bf2f12 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,6 @@ "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", @@ -14,7 +12,7 @@ "open-telemetry/sem-conv": "^1.0", "php": ">=8.2", "spryker/kernel": "^3.30.0", - "spryker/monitoring-extension": "^1.0.0", + "spryker/monitoring-extension": "^1.1.0", "spryker/symfony": "^3.0.0" }, "require-dev": { diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php index 8371d87..a4fb592 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/ElasticaInstrumentation.php @@ -68,7 +68,12 @@ class ElasticaInstrumentation */ public static function register(): void { - if (!class_exists(Client::class) || Sdk::isInstrumentationDisabled(static::NAME) === true) { + //BC check + if (class_exists('\Spryker\Service\OtelElasticaInstrumentation\OpenTelemetry\ElasticaInstrumentation')) { + return; + } + + if (Sdk::isInstrumentationDisabled(static::NAME) === true) { return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php index 1b9468a..9637432 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/PropelInstrumentation.php @@ -46,7 +46,12 @@ class PropelInstrumentation */ public static function register(): void { - if (!class_exists(StatementInterface::class) || Sdk::isInstrumentationDisabled(static::NAME) === true) { + //BC check + if (class_exists('\Spryker\Service\OtelPropelInstrumentation\OpenTelemetry\PropelInstrumentation')) { + return; + } + + if (Sdk::isInstrumentationDisabled(static::NAME) === true) { return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php index 58d9ad3..fe2fbbb 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/RabbitMqInstrumentation.php @@ -88,7 +88,12 @@ public static function register(): void */ protected static function registerHook(string $functionName, string $spanName): void { - if (!class_exists(RabbitMqAdapter::class) || Sdk::isInstrumentationDisabled(static::NAME) === true) { + //BC check + if (class_exists('\Spryker\Service\OtelRabbitMqInstrumentation\OpenTelemetry\RabbitMqInstrumentation')) { + return; + } + + if (Sdk::isInstrumentationDisabled(static::NAME) === true) { return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php b/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php index cc2bc17..ff1453d 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/RedisInstrumentation.php @@ -13,6 +13,8 @@ use OpenTelemetry\SDK\Sdk; use OpenTelemetry\SemConv\TraceAttributes; use Redis; +use Spryker\Client\Redis\Adapter\RedisAdapterInterface; +use Spryker\Service\Opentelemetry\Instrumentation\Sampler\CriticalSpanRatioSampler; use Spryker\Service\Opentelemetry\Instrumentation\Sampler\TraceSampleResult; use Spryker\Service\Opentelemetry\Instrumentation\Span\Span; use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; @@ -41,51 +43,16 @@ class RedisInstrumentation */ public static function register(): void { - if (!class_exists(Redis::class) || Sdk::isInstrumentationDisabled(static::NAME) === true) { + if (Sdk::isInstrumentationDisabled(static::NAME) === true) { return; } $instrumentation = CachedInstrumentation::getCachedInstrumentation(); hook( - Redis::class, - 'select', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { - - if (TraceSampleResult::shouldSkipTraceBody()) { - return; - } - $context = Context::getCurrent(); - $span = $instrumentation->tracer() - ->spanBuilder('Redis::select') - ->setSpanKind(SpanKind::KIND_CLIENT) - ->setParent($context) - ->setAttribute(TraceAttributes::DB_NAMESPACE, $params[0]) - ->startSpan(); - - Context::storage()->attach($span->storeInContext($context)); - }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { - if (TraceSampleResult::shouldSkipTraceBody()) { - return; - } - $span = Span::fromContext(Context::getCurrent()); - - if ($exception !== null) { - $span->recordException($exception); - $span->setStatus(StatusCode::STATUS_ERROR); - } else { - $span->setStatus(StatusCode::STATUS_OK); - } - - $span->end(); - }, - ); - - hook( - Redis::class, + RedisAdapterInterface::class, 'get', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { + pre: static function (RedisAdapterInterface $redis, array $params) use ($instrumentation): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; @@ -95,13 +62,13 @@ public static function register(): void ->spanBuilder('Redis::get') ->setSpanKind(SpanKind::KIND_CLIENT) ->setParent($context) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) ->setAttribute(TraceAttributes::DB_QUERY_TEXT, isset($params[0]) ? 'GET ' . $params[0] : 'undefined') - ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) ->startSpan(); Context::storage()->attach($span->storeInContext($context)); }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + post: static function (RedisAdapterInterface $redis, array $params, mixed $ret, ?Throwable $exception): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } @@ -119,25 +86,25 @@ public static function register(): void ); hook( - Redis::class, - 'eval', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { + RedisAdapterInterface::class, + 'mget', + pre: static function (RedisAdapterInterface $redis, array $params) use ($instrumentation): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } $context = Context::getCurrent(); $span = $instrumentation->tracer() - ->spanBuilder('Redis::eval') + ->spanBuilder('Redis::mget') ->setSpanKind(SpanKind::KIND_CLIENT) ->setParent($context) - ->setAttribute(static::PARAM_EVAL_SCRIPT, $params[0] ?? 'undefined') - ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', $params[0])) ->startSpan(); Context::storage()->attach($span->storeInContext($context)); }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + post: static function (RedisAdapterInterface $redis, array $params, mixed $ret, ?Throwable $exception): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } @@ -155,25 +122,25 @@ public static function register(): void ); hook( - Redis::class, - 'exists', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { + RedisAdapterInterface::class, + 'eval', + pre: static function (RedisAdapterInterface $redis, array $params) use ($instrumentation): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } $context = Context::getCurrent(); $span = $instrumentation->tracer() - ->spanBuilder('Redis::exists') + ->spanBuilder('Redis::eval') ->setSpanKind(SpanKind::KIND_CLIENT) ->setParent($context) - ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', $params)) - ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) + ->setAttribute(static::PARAM_EVAL_SCRIPT, $params[0] ?? 'undefined') ->startSpan(); Context::storage()->attach($span->storeInContext($context)); }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + post: static function (RedisAdapterInterface $redis, array $params, mixed $ret, ?Throwable $exception): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } @@ -191,9 +158,9 @@ public static function register(): void ); hook( - Redis::class, + RedisAdapterInterface::class, 'mset', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { + pre: static function (RedisAdapterInterface $redis, array $params) use ($instrumentation): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; @@ -203,13 +170,13 @@ public static function register(): void ->spanBuilder('Redis::mset') ->setSpanKind(SpanKind::KIND_CLIENT) ->setParent($context) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', array_keys($params[0]))) - ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) ->startSpan(); Context::storage()->attach($span->storeInContext($context)); }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + post: static function (RedisAdapterInterface $redis, array $params, mixed $ret, ?Throwable $exception): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } @@ -227,45 +194,9 @@ public static function register(): void ); hook( - Redis::class, - 'msetnx', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { - - if (TraceSampleResult::shouldSkipTraceBody()) { - return; - } - $context = Context::getCurrent(); - $span = $instrumentation->tracer() - ->spanBuilder('Redis::msetnx') - ->setSpanKind(SpanKind::KIND_CLIENT) - ->setParent($context) - ->setAttribute(TraceAttributes::DB_QUERY_TEXT, implode(' ', array_keys($params[0]))) - ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) - ->startSpan(); - - Context::storage()->attach($span->storeInContext($context)); - }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { - if (TraceSampleResult::shouldSkipTraceBody()) { - return; - } - $span = Span::fromContext(Context::getCurrent()); - - if ($exception !== null) { - $span->recordException($exception); - $span->setStatus(StatusCode::STATUS_ERROR); - } else { - $span->setStatus(StatusCode::STATUS_OK); - } - - $span->end(); - }, - ); - - hook( - Redis::class, + RedisAdapterInterface::class, 'set', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { + pre: static function (RedisAdapterInterface $redis, array $params) use ($instrumentation): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; @@ -275,13 +206,13 @@ public static function register(): void ->spanBuilder('Redis::set') ->setSpanKind(SpanKind::KIND_CLIENT) ->setParent($context) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) ->setAttribute(TraceAttributes::DB_QUERY_TEXT, $params[0] ?? 'undefined') - ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) ->startSpan(); Context::storage()->attach($span->storeInContext($context)); }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + post: static function (RedisAdapterInterface $redis, array $params, mixed $ret, ?Throwable $exception): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } @@ -301,7 +232,7 @@ public static function register(): void hook( Redis::class, 'setex', - pre: static function (Redis $redis, array $params) use ($instrumentation): void { + pre: static function (RedisAdapterInterface $redis, array $params) use ($instrumentation): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; @@ -311,6 +242,7 @@ public static function register(): void ->spanBuilder('Redis::set') ->setSpanKind(SpanKind::KIND_CLIENT) ->setParent($context) + ->setAttribute(CriticalSpanRatioSampler::IS_CRITICAL_ATTRIBUTE, true) ->setAttribute(TraceAttributes::DB_QUERY_TEXT, $params[0] ?? 'undefined') ->setAttribute(static::PARAM_EXPIRATION, $params[0] ?? 'undefined') ->setAttribute(TraceAttributes::DB_NAMESPACE, $redis->getDBNum()) @@ -318,7 +250,7 @@ public static function register(): void Context::storage()->attach($span->storeInContext($context)); }, - post: static function (Redis $redis, array $params, mixed $ret, ?Throwable $exception): void { + post: static function (RedisAdapterInterface $redis, array $params, mixed $ret, ?Throwable $exception): void { if (TraceSampleResult::shouldSkipTraceBody()) { return; } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php index dbe6862..d17d1cf 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/Sampler/TraceSampleResult.php @@ -35,6 +35,7 @@ class TraceSampleResult public static function shouldSample(Request $request): int { $route = $request->attributes->get('_route'); + $isCli = (bool)$request->server->get('argv'); if ($request->getMethod() !== Request::METHOD_GET) { static::$result = static::SAMPLING_RESULT_ALLOW_ALL; @@ -48,7 +49,7 @@ public static function shouldSample(Request $request): int return static::$result; } - if (static::decideForRootSpan()) { + if (static::decideForRootSpan($isCli)) { static::$result = static::SAMPLING_RESULT_ALLOW_ROOT_SPAN; return static::$result; @@ -76,10 +77,13 @@ public static function shouldSkipRootSpan(): bool } /** + * @param bool $isCli + * * @return bool */ - protected static function decideForRootSpan(): bool + protected static function decideForRootSpan(bool $isCli): bool { - return (mt_rand() / mt_getrandmax()) >= OpentelemetryInstrumentationConfig::getTraceSamplerProbability(); + $probability = $isCli ? OpentelemetryInstrumentationConfig::getTraceCLISamplerProbability() : OpentelemetryInstrumentationConfig::getTraceSamplerProbability(); + return (mt_rand() / mt_getrandmax()) >= $probability; } } diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 684b650..20b5819 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -35,6 +35,7 @@ use Spryker\Service\Opentelemetry\Instrumentation\Tracer\TracerProvider; use Spryker\Service\Opentelemetry\OpentelemetryInstrumentationConfig; use Spryker\Service\Opentelemetry\Plugin\OpentelemetryMonitoringExtensionPlugin; +use Spryker\Service\Opentelemetry\Storage\CustomEventsStorage; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; use Spryker\Service\Opentelemetry\Storage\ExceptionStorage; use Spryker\Service\Opentelemetry\Storage\ResourceNameStorage; @@ -117,7 +118,7 @@ public static function register(): void ->setPropagator(TraceContextPropagator::getInstance()) ->buildAndRegisterGlobal(); - static::registerRootSpan($serviceName, $request); + static::registerRootSpan($request); ShutdownHandler::register($tracerProvider->shutdown(...)); ShutdownHandler::register([static::class, 'shutdownHandler']); @@ -251,11 +252,11 @@ protected static function resolveServiceName(): string } /** - * @param string $servicedName + * @param Request $request * * @return void */ - protected static function registerRootSpan(string $servicedName, Request $request): void + protected static function registerRootSpan(Request $request): void { $cli = $request->server->get('argv'); if ($cli) { @@ -267,7 +268,7 @@ protected static function registerRootSpan(string $servicedName, Request $reques $instrumentation = CachedInstrumentation::getCachedInstrumentation(); $parent = Context::getCurrent(); $span = $instrumentation->tracer() - ->spanBuilder($servicedName . ' ' . $name) + ->spanBuilder($name) ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->setAttribute(TraceAttributes::URL_QUERY, $request->getQueryString()) @@ -322,6 +323,11 @@ public static function shutdownHandler(): void $span->recordException($exception); } + $events = CustomEventsStorage::getInstance()->getEvents(); + foreach ($events as $eventName => $eventAttributes) { + $span->addEvent($eventName, $eventAttributes); + } + $span->setStatus($exceptions ? StatusCode::STATUS_ERROR : StatusCode::STATUS_OK); $span->setAttributes($customParamsStorage->getAttributes()); diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php index b83c447..6540537 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryInstrumentationConfig.php @@ -74,6 +74,11 @@ class OpentelemetryInstrumentationConfig */ protected const OTEL_TRACE_PROBABILITY = 'OTEL_TRACE_PROBABILITY'; + /** + * @string + */ + protected const OTEL_CLI_TRACE_PROBABILITY = 'OTEL_CLI_TRACE_PROBABILITY'; + /** * Specification: * - The threshold in nanoseconds for the span to be sampled. @@ -84,7 +89,7 @@ class OpentelemetryInstrumentationConfig */ public static function getSamplerThresholdNano(): int { - $multiplicator = getenv(static::OTEL_BSP_MIN_SPAN_DURATION_THRESHOLD) ?: 20; + $multiplicator = getenv(static::OTEL_BSP_MIN_SPAN_DURATION_THRESHOLD) ?: 5; return $multiplicator * 1000000; } @@ -99,7 +104,7 @@ public static function getSamplerThresholdNano(): int */ public static function getSamplerThresholdNanoForCriticalSpan(): int { - $multiplicator = getenv(static::OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD) ?: 10; + $multiplicator = getenv(static::OTEL_BSP_MIN_CRITICAL_SPAN_DURATION_THRESHOLD) ?: 0; return $multiplicator * 1000000; } @@ -190,7 +195,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) ?: 1; return (float)$probability; } @@ -251,7 +256,17 @@ public static function getSpanProcessorMaxBatchSize(): int */ public static function getTraceSamplerProbability(): float { - $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.1; + $probability = getenv(static::OTEL_TRACE_PROBABILITY) ?: 0.3; + + return (float)$probability; + } + + /** + * @return float + */ + public static function getTraceCLISamplerProbability(): float + { + $probability = getenv(static::OTEL_CLI_TRACE_PROBABILITY) ?: 0.5; return (float)$probability; } diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryService.php b/src/Spryker/Service/Opentelemetry/OpentelemetryService.php index df82177..9ec3173 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryService.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryService.php @@ -73,4 +73,19 @@ public function setError(string $message, Throwable $exception): void { $this->getFactory()->createExceptionStorage()->addException($exception); } + + /** + * {@inheritDoc} + * + * @api + * + * @param string $name + * @param array $attributes + * + * @return void + */ + public function addEvent(string $name, array $attributes): void + { + $this->getFactory()->createCustomEventsStorage()->addEvent($name, $attributes); + } } diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php index dc4ee3c..e39427b 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceFactory.php @@ -8,6 +8,8 @@ namespace Spryker\Service\Opentelemetry; use Spryker\Service\Kernel\AbstractServiceFactory; +use Spryker\Service\Opentelemetry\Storage\CustomEventsStorage; +use Spryker\Service\Opentelemetry\Storage\CustomEventsStorageInterface; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorage; use Spryker\Service\Opentelemetry\Storage\CustomParameterStorageInterface; use Spryker\Service\Opentelemetry\Storage\ExceptionStorage; @@ -49,4 +51,12 @@ public function createExceptionStorage(): ExceptionStorageInterface { return ExceptionStorage::getInstance(); } + + /** + * @return \Spryker\Service\Opentelemetry\Storage\CustomEventsStorageInterface + */ + public function createCustomEventsStorage(): CustomEventsStorageInterface + { + return CustomEventsStorage::getInstance(); + } } diff --git a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php index 499b4b2..1ae934d 100644 --- a/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php +++ b/src/Spryker/Service/Opentelemetry/OpentelemetryServiceInterface.php @@ -61,4 +61,17 @@ public function setResourceName(string $name): void; * @return void */ public function setError(string $message, Throwable $exception): void; + + /** + * Specification: + * - Adds a custom event to the root span. + * + * @api + * + * @param string $name + * @param array $attributes + * + * @return void + */ + public function addEvent(string $name, array $attributes): void; } diff --git a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php index 6350084..7da5f96 100644 --- a/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php +++ b/src/Spryker/Service/Opentelemetry/Plugin/OpentelemetryMonitoringExtensionPlugin.php @@ -8,12 +8,13 @@ namespace Spryker\Service\Opentelemetry\Plugin; use Spryker\Service\Kernel\AbstractPlugin; +use Spryker\Service\MonitoringExtension\Dependency\Plugin\CustomEventsMonitoringExtensionPluginInterface; use Spryker\Service\MonitoringExtension\Dependency\Plugin\MonitoringExtensionPluginInterface; /** * @method \Spryker\Service\Opentelemetry\OpentelemetryServiceInterface getService() */ -class OpentelemetryMonitoringExtensionPlugin extends AbstractPlugin implements MonitoringExtensionPluginInterface +class OpentelemetryMonitoringExtensionPlugin extends AbstractPlugin implements MonitoringExtensionPluginInterface, CustomEventsMonitoringExtensionPluginInterface { /** * @var string @@ -152,4 +153,18 @@ public function addCustomTracer(string $tracer): void { return; } + + /** + * Specification: + * - Adds a custom event that will be added to the root span. + * + * @param string $name + * @param array $attributes + * + * @return void + */ + public function addEvent(string $name, array $attributes): void + { + $this->getService()->addEvent($name, $attributes); + } } diff --git a/src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorage.php b/src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorage.php new file mode 100644 index 0000000..cfc2e68 --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorage.php @@ -0,0 +1,53 @@ + + */ + protected array $events = []; + + /** + * @return \Spryker\Service\Opentelemetry\Storage\CustomEventsStorageInterface + */ + public static function getInstance(): CustomEventsStorageInterface + { + if (self::$instance === null) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** + * @param string $name + * @param array $attributes + * + * @return void + */ + public function addEvent(string $name, array $attributes): void + { + $this->events[$name] = $attributes; + } + + /** + * @return array + */ + public function getEvents(): array + { + return $this->events; + } +} diff --git a/src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorageInterface.php b/src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorageInterface.php new file mode 100644 index 0000000..40e7f5c --- /dev/null +++ b/src/Spryker/Service/Opentelemetry/Storage/CustomEventsStorageInterface.php @@ -0,0 +1,29 @@ + Date: Fri, 10 Jan 2025 14:23:32 +0200 Subject: [PATCH 3/5] Reverted extension requirement to test --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7bf2f12..b70979d 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "open-telemetry/sem-conv": "^1.0", "php": ">=8.2", "spryker/kernel": "^3.30.0", - "spryker/monitoring-extension": "^1.1.0", + "spryker/monitoring-extension": "^1.0.0", "spryker/symfony": "^3.0.0" }, "require-dev": { From f795413c2b84b1001359898a05a94df19164310f Mon Sep 17 00:00:00 2001 From: gechetspr Date: Mon, 13 Jan 2025 13:29:18 +0200 Subject: [PATCH 4/5] Process CLI status code --- .../SprykerInstrumentationBootstrap.php | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php index 20b5819..c6c8656 100644 --- a/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php +++ b/src/Spryker/Service/Opentelemetry/Instrumentation/SprykerInstrumentationBootstrap.php @@ -43,7 +43,10 @@ use Spryker\Shared\Opentelemetry\Instrumentation\CachedInstrumentation; use Spryker\Shared\Opentelemetry\Request\RequestProcessor; use Spryker\Zed\Opentelemetry\Business\Generator\HookGenerator; +use Symfony\Component\Console\Application; use Symfony\Component\HttpFoundation\Request; +use Throwable; +use function OpenTelemetry\Instrumentation\hook; /** * @method \Spryker\Service\Opentelemetry\OpentelemetryServiceFactory getFactory() @@ -95,6 +98,11 @@ class SprykerInstrumentationBootstrap */ protected static ?SpanInterface $rootSpan = null; + /** + * @var bool|null + */ + protected static ?bool $cliSuccess = null; + /** * @return void */ @@ -131,6 +139,7 @@ public static function register(): void */ protected static function registerAdditionalHooks(): void { + static::registerConsoleReturnCodeHook(); if (TraceSampleResult::shouldSkipTraceBody()) { putenv('OTEL_PHP_DISABLED_INSTRUMENTATIONS=all'); @@ -155,6 +164,21 @@ protected static function registerAdditionalHooks(): void spl_autoload_register($autoload, true, true); } + /** + * @return void + */ + protected static function registerConsoleReturnCodeHook(): void + { + hook( + Application::class, + 'doRun', + function () {}, + function ($instance, array $params, $returnValue, ?Throwable $exception) { + static::$cliSuccess = $returnValue === 0 || $returnValue === null; + } + ); + } + /** * @param string $serviceName * @@ -328,7 +352,7 @@ public static function shutdownHandler(): void $span->addEvent($eventName, $eventAttributes); } - $span->setStatus($exceptions ? StatusCode::STATUS_ERROR : StatusCode::STATUS_OK); + $span->setStatus($exceptions || static::$cliSuccess === false ? StatusCode::STATUS_ERROR : StatusCode::STATUS_OK); $span->setAttributes($customParamsStorage->getAttributes()); $span->end(); From 68454b88dc7ffe5f2d95a59a55577daa38c9bd36 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Mon, 13 Jan 2025 15:50:49 +0200 Subject: [PATCH 5/5] Updated versions --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b70979d..7bf2f12 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "open-telemetry/sem-conv": "^1.0", "php": ">=8.2", "spryker/kernel": "^3.30.0", - "spryker/monitoring-extension": "^1.0.0", + "spryker/monitoring-extension": "^1.1.0", "spryker/symfony": "^3.0.0" }, "require-dev": {