public Span startSpan()

in apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/main/java/co/elastic/apm/agent/opentelemetry/tracing/OTelSpanBuilder.java [149:209]


    public Span startSpan() {
        AbstractSpanImpl<?> span;

        BaggageImpl parentBaggage;
        AbstractSpanImpl<?> parentSpan = null;
        Context remoteContext = null;

        if (parent != null) {
            Span parentOtelSpan = Span.fromContext(parent);
            if (parentOtelSpan.getSpanContext().isRemote()) {
                remoteContext = parent;
            } else if (parentOtelSpan instanceof OTelSpan) {
                parentSpan = ((OTelSpan) parentOtelSpan).getInternalSpan();
            }
            parentBaggage = OtelBaggage.toElasticBaggage(io.opentelemetry.api.baggage.Baggage.fromContext(parent));
        } else {
            // when parent is not explicitly set, the currently active parent is used as fallback
            parentSpan = elasticApmTracer.currentContext().getSpan();
            parentBaggage = elasticApmTracer.currentContext().getBaggage();
        }

        if (remoteContext != null) {
            PotentiallyMultiValuedMap headers = new PotentiallyMultiValuedMap(2);
            W3CTraceContextPropagator.getInstance().inject(remoteContext, headers, PotentiallyMultiValuedMap::add);
            span = elasticApmTracer.startChildTransaction(headers, MultiValueMapAccessor.INSTANCE, PrivilegedActionUtils.getClassLoader(getClass()), parentBaggage, epochMicros);
        } else if (parentSpan == null) {
            span = elasticApmTracer.startRootTransaction(PrivilegedActionUtils.getClassLoader(getClass()), parentBaggage, epochMicros);
        } else {
            span = elasticApmTracer.startSpan(parentSpan, parentBaggage, epochMicros);
        }
        if (span == null) {
            return Span.getInvalid();
        }
        span.withName(spanName);

        if (span instanceof TransactionImpl) {
            TransactionImpl t = ((TransactionImpl) span);
            t.setFrameworkName("OpenTelemetry API");

            String otelVersion = VersionUtils.getVersion(OpenTelemetry.class, "io.opentelemetry", "opentelemetry-api");
            if (otelVersion != null) {
                t.setFrameworkVersion(otelVersion);
            }
        }

        span.withOtelKind(OTelHelper.map(kind));

        // With OTel API, the status (bridged to outcome) should only be explicitly set, thus we have to set and use
        // user outcome to provide higher priority and avoid inferring outcome from any reported exception
        span.withUserOutcome(Outcome.UNKNOWN);

        // Add the links to the span
        for (int i = 0; i < links.size(); i++) {
            span.addSpanLink(TraceContextImpl.fromParentContext(), ((OTelSpanContext) links.get(i)).getElasticTraceContext());

        }

        OTelSpan otelSpan = new OTelSpan(span);
        attributes.forEach((AttributeKey<?> k, Object v) -> otelSpan.setAttribute((AttributeKey<? super Object>) k, (Object) v));
        return otelSpan;
    }