Current section
Files
Jump to
Current section
Files
src/otel_propagator_text_map_composite.erl
%%%------------------------------------------------------------------------
%% Copyright 2020, OpenTelemetry Authors
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% @doc A Composite TextMap Propagator is a Propagator that performs run
%% multiple TextMap Propagators in a specified order.
%%
%% An example of creating a Composite TextMap Propagator to inject and
%% extract Baggage and TraceContext:
%%
%% ```
%% Propagator = otel_propagator_text_map_composite:create([trace_context, baggage]),
%% otel_propagator_text_map:extract(Propagator, Carrier)
%% '''
%% @end
%%%-------------------------------------------------------------------------
-module(otel_propagator_text_map_composite).
-behaviour(otel_propagator_text_map).
-export([create/1,
fields/1,
inject/4,
extract/5,
report_cb/1]).
-include_lib("kernel/include/logger.hrl").
%% @doc Create a new Composite TextMap Propagator.
%%
%% The `Propagators' list is a list of atoms that represent the <i>suffix</i>
%% of the module name of the TextMap Propagator to be used.
-spec create([otel_propagator:builtin()]) -> otel_propagator:t().
create(Propagators) ->
{?MODULE, otel_propagator:builtins_to_modules(Propagators)}.
%% @private
fields(Propagators) ->
lists:flatmap(fun(Propagator) ->
otel_propagator_text_map:fields(Propagator)
end, Propagators).
%% @private
-spec inject(Context, Carrier, CarrierSetFun, Injectors) -> Carrier
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierSetFun :: otel_propagator_text_map:carrier_set(),
Injectors :: [otel_propagator_text_map:t()].
inject(Context, Carrier, CarrierSetFun, Injectors) ->
run_injectors(Context, Injectors, Carrier, CarrierSetFun).
%% @private
-spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Extractors) -> Context
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierKeysFun :: otel_propagator_text_map:carrier_keys(),
CarrierGetFun :: otel_propagator_text_map:carrier_get(),
Extractors :: [otel_propagator_text_map:t()].
extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Extractors) ->
run_extractors(Context, Extractors, Carrier, CarrierKeysFun, CarrierGetFun).
run_extractors(Context, Extractors, Carrier, CarrierKeysFun, CarrierGetFun) when is_list(Extractors) ->
lists:foldl(fun(Propagator, ContextAcc) ->
try otel_propagator_text_map:extract_to(ContextAcc, Propagator, Carrier, CarrierKeysFun, CarrierGetFun)
catch
C:E:S ->
?LOG_INFO(#{extractor => Propagator, carrier => Carrier,
class => C, exception => E, stacktrace => S},
#{report_cb => fun ?MODULE:report_cb/1}),
ContextAcc
end
end, Context, otel_propagator:builtins_to_modules(Extractors)).
run_injectors(Context, Injectors, Carrier, Setter) when is_list(Injectors) ->
lists:foldl(fun(Propagator, CarrierAcc) ->
try otel_propagator_text_map:inject_from(Context, Propagator, CarrierAcc, Setter)
catch
C:E:S ->
?LOG_INFO(#{injector => Propagator, carrier => CarrierAcc,
class => C, exception => E, stacktrace => S},
#{report_cb => fun ?MODULE:report_cb/1}),
CarrierAcc
end
end, Carrier, otel_propagator:builtins_to_modules(Injectors)).
%% @private
report_cb(#{extractor := Propagator, carrier := _Carrier,
class := Class, exception := Exception, stacktrace := StackTrace}) ->
{"text map propagator failed to extract from carrier: propagator=~ts exception=~ts",
[Propagator, otel_utils:format_exception(Class, Exception, StackTrace)]};
report_cb(#{injector := Propagator, carrier := _Carrier,
class := Class, exception := Exception, stacktrace := StackTrace}) ->
{"text map propagator failed to inject to carrier: propagator=~ts exception=~ts",
[Propagator, otel_utils:format_exception(Class, Exception, StackTrace)]}.