Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x

SpanConverter.php

Namespace

OpenTelemetry\Contrib\Otlp

File

vendor/open-telemetry/exporter-otlp/SpanConverter.php

View source
<?php

declare (strict_types=1);
namespace OpenTelemetry\Contrib\Otlp;

use OpenTelemetry\API\Trace as API;
use OpenTelemetry\API\Trace\SpanContextInterface;
use Opentelemetry\Proto\Collector\Trace\V1\ExportTraceServiceRequest;
use Opentelemetry\Proto\Common\V1\InstrumentationScope;
use Opentelemetry\Proto\Common\V1\KeyValue;
use Opentelemetry\Proto\Resource\V1\Resource as Resource_;
use Opentelemetry\Proto\Trace\V1\ResourceSpans;
use Opentelemetry\Proto\Trace\V1\ScopeSpans;
use Opentelemetry\Proto\Trace\V1\Span;
use Opentelemetry\Proto\Trace\V1\Span\Event;
use Opentelemetry\Proto\Trace\V1\Span\Link;
use Opentelemetry\Proto\Trace\V1\Span\SpanKind;
use Opentelemetry\Proto\Trace\V1\SpanFlags;
use Opentelemetry\Proto\Trace\V1\Status;
use Opentelemetry\Proto\Trace\V1\Status\StatusCode;
use OpenTelemetry\SDK\Common\Attribute\AttributesInterface;
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SDK\Trace\SpanDataInterface;
use function serialize;
use function spl_object_id;
final class SpanConverter {
    private readonly ProtobufSerializer $serializer;
    public function __construct(?ProtobufSerializer $serializer = null) {
        $this->serializer = $serializer ?? ProtobufSerializer::getDefault();
    }
    public function convert(iterable $spans) : ExportTraceServiceRequest {
        $pExportTraceServiceRequest = new ExportTraceServiceRequest();
        $resourceSpans = [];
        $resourceCache = [];
        $scopeSpans = [];
        $scopeCache = [];
        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;
    }
    private 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;
    }
    private 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
     */
    private 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());
    }
    private 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,
        
        };
    }
    private 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;
    }
    private function convertSpan(SpanDataInterface $span) : Span {
        $pSpan = new Span();
        $pSpan->setTraceId($this->serializer
            ->serializeTraceId($span->getContext()
            ->getTraceIdBinary()));
        $pSpan->setSpanId($this->serializer
            ->serializeSpanId($span->getContext()
            ->getSpanIdBinary()));
        $pSpan->setFlags(self::traceFlags($span->getContext()));
        $pSpan->setTraceState((string) $span->getContext()
            ->getTraceState());
        if ($span->getParentContext()
            ->isValid()) {
            $pSpan->setParentSpanId($this->serializer
                ->serializeSpanId($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($this->serializer
                ->serializeTraceId($link->getSpanContext()
                ->getTraceIdBinary()));
            $pLink->setSpanId($this->serializer
                ->serializeSpanId($link->getSpanContext()
                ->getSpanIdBinary()));
            $pLink->setFlags(self::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;
    }
    private 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;
    }

}

Classes

Title Deprecated Summary
SpanConverter

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal