-module(otel_propagator_instana). -behaviour(otel_propagator_text_map). -export([fields/1, inject/4, extract/5]). -include_lib("opentelemetry_api/include/opentelemetry.hrl"). -define(TRACE_ID_KEY, <<"X-INSTANA-T">>). -define(SPAN_ID_KEY, <<"X-INSTANA-S">>). -define(TRACE_LEVEL_KEY, <<"X-INSTANA-L">>). fields(_) -> [?TRACE_ID_KEY, ?SPAN_ID_KEY, ?TRACE_LEVEL_KEY]. -spec inject(Context, Carrier, CarrierSetFun, Options) -> Carrier when Context :: otel_ctx:t(), Carrier :: otel_propagator:carrier(), CarrierSetFun :: otel_propagator_text_map:carrier_set(), Options :: otel_propagator_text_map:propagator_options(). inject(Ctx, Carrier, CarrierSet, _Options) -> case otel_tracer:current_span_ctx(Ctx) of #span_ctx{trace_id=TraceId, span_id=SpanId, trace_flags=TraceFlags} when TraceId =/= 0 andalso SpanId =/= 0 -> TraceIdB = integer_to_binary(TraceId, 16), SpanIdB = integer_to_binary(SpanId, 16), TraceFlagsB = integer_to_binary(TraceFlags, 16), Carrier1 = CarrierSet(?TRACE_ID_KEY, TraceIdB, Carrier), Carrier2 = CarrierSet(?SPAN_ID_KEY, SpanIdB, Carrier1), CarrierSet(?TRACE_LEVEL_KEY, TraceFlagsB, Carrier2); _ -> Carrier end. -spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Options) -> Context when Context :: otel_ctx:t(), Carrier :: otel_propagator:carrier(), CarrierKeysFun :: otel_propagator_text_map:carrier_keys(), CarrierGetFun :: otel_propagator_text_map:carrier_get(), Options :: otel_propagator_text_map:propagator_options(). extract(Ctx, Carrier, _CarrierKeysFun, CarrierGet, _Options) -> try extract1(Ctx, Carrier, _CarrierKeysFun, CarrierGet, _Options) of {TraceId, SpanId, TraceLevel} -> SpanCtx = otel_tracer:from_remote_span(TraceId, SpanId, TraceLevel), otel_tracer:set_current_span(Ctx, SpanCtx) catch _:_ -> Ctx end. extract1(_Ctx, Carrier, _CarrierKeysFun, CarrierGet, _Options) -> TraceId = binary_to_integer(CarrierGet(?TRACE_ID_KEY, Carrier), 16), SpanId = binary_to_integer(CarrierGet(?SPAN_ID_KEY, Carrier), 16), TraceLevel = binary_to_integer(CarrierGet(?TRACE_LEVEL_KEY, Carrier), 16), if (TraceId > 1) and (SpanId > 1) and (TraceLevel >= 0) and (TraceLevel =< 1) -> {TraceId, SpanId, TraceLevel}; true -> exit("") end.