Skip to content

Commit

Permalink
Merge pull request #328 from tsloughter/app-env-config
Browse files Browse the repository at this point in the history
move the rest of application env vars to configuration map
  • Loading branch information
tsloughter authored Dec 16, 2021
2 parents 70681ed + c9e0e54 commit 3d56c11
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 121 deletions.
172 changes: 93 additions & 79 deletions apps/opentelemetry/src/otel_configuration.erl
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,45 @@
%% using a map instead of a record because there can be more values
-type t() :: #{log_level := atom(),
register_loaded_applications := boolean(),
id_generator := module(),
deny_list := [atom()],
resource_detectors => [module()],
resource_detector_timeout => integer(),
text_map_propagators := [atom()],
traces_exporter := {atom(), term()},
processors := list(),
sampler := {atom(), term()},
sweeper := #{interval => integer() | infinity,
strategy => atom() | fun(),
span_ttl => integer() | infinity,
storage_size => integer() | infinity},
attribute_count_limit := integer(),
attribute_value_length_limit := integer() | infinity,
event_count_limit := integer(),
link_count_limit := integer(),
attribute_per_event_limit := integer(),
attribute_per_link_limit := integer()}.

-spec new() -> t().
new() ->
#{log_level => info,
register_loaded_applications => true,
id_generator => otel_id_generator,
deny_list => [],
resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 5000,
text_map_propagators => [trace_context, baggage],
traces_exporter => {opentelemetry_exporter, #{}},
processors => [{otel_batch_processor, #{scheduled_delay_ms => 5000,
exporting_timeout_ms => 30000,
max_queue_size => 2048,
exporter => {opentelemetry_exporter, #{}}}}],
sampler => {parent_based, #{root => always_on}},
sweeper => #{interval => timer:minutes(10),
strategy => drop,
span_ttl => timer:minutes(30),
storage_size => infinity},
attribute_count_limit => 128,
attribute_value_length_limit => infinity,
event_count_limit => 128,
Expand All @@ -65,7 +84,8 @@ merge_with_os(AppEnv) ->
end, ConfigMap, [fun span_limits/2,
fun general/2,
fun sampler/2,
fun processors/2]).
fun processors/2,
fun sweeper/2]).

-spec span_limits(list(), t()) -> t().
span_limits(AppEnv, ConfigMap) ->
Expand All @@ -75,6 +95,16 @@ span_limits(AppEnv, ConfigMap) ->
general(AppEnv, ConfigMap) ->
merge_list_with_environment(config_mappings(general_sdk), AppEnv, ConfigMap).

-spec sweeper(list(), t()) -> t().
sweeper(AppEnv, ConfigMap=#{sweeper := DefaultSweeperConfig}) ->
AppEnvSweeper = proplists:get_value(sweeper, AppEnv, #{}),

%% convert sweeper config to a list to utilize the merge_list_with_environment function
SweeperConfig = merge_list_with_environment(config_mappings(sweeper),
maps:to_list(AppEnvSweeper),
DefaultSweeperConfig),
ConfigMap#{sweeper => SweeperConfig}.

-spec processors(list(), t()) -> t().
processors(AppEnv, ConfigMap) ->
%% builtin processors have OS environment configuration per type of processor
Expand All @@ -83,7 +113,7 @@ processors(AppEnv, ConfigMap) ->
Processors = proplists:get_value(processors, AppEnv, maps:get(processors, ConfigMap)),

ProcessorsConfig = lists:map(fun({Name, Opts}) ->
{Name, merge_with_environment(config_mappings(Name), Opts)}
{Name, merge_with_os_environment(config_mappings(Name), Opts)}
end, Processors),

ConfigMap#{processors := ProcessorsConfig}.
Expand All @@ -92,106 +122,74 @@ processors(AppEnv, ConfigMap) ->
%% sub-configuration of the sampler config, and isn't a list.
-spec sampler(list(), t()) -> t().
sampler(AppEnv, ConfigMap) ->
OSVar = "OTEL_TRACES_SAMPLER",
Key = sampler,
Transform = sampler,
case os:getenv("OTEL_TRACES_SAMPLER") of
false ->
case proplists:get_value(sampler, AppEnv) of
case proplists:get_value(Key, AppEnv) of
undefined ->
ConfigMap;
Sampler ->
try transform(sampler, Sampler) of
TransformedSampler ->
ConfigMap#{sampler := TransformedSampler}
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => transform,
kind => Kind,
reason => Reason,
os_var => "OTEL_TRACES_SAMPLER",
key => sampler,
transform => sampler,
value => Sampler,
stacktrace => StackTrace},
#{report_cb => fun ?MODULE:report_cb/1}),
ConfigMap
end
update_config_map(OSVar, Key, Transform, Sampler, ConfigMap)
end;
OSEnvSampler->
SamplerTuple = {OSEnvSampler, os:getenv("OTEL_TRACES_SAMPLER_ARG")},
try transform(sampler, SamplerTuple) of
TransformedSampler ->
ConfigMap#{sampler := TransformedSampler}
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => transform,
kind => Kind,
reason => Reason,
os_var => "OTEL_TRACES_SAMPLER",
key => sampler,
transform => sampler,
value => SamplerTuple,
stacktrace => StackTrace},
#{report_cb => fun ?MODULE:report_cb/1}),
ConfigMap
end
update_config_map(OSVar, Key, Transform, SamplerTuple, ConfigMap)
end.

-spec merge_list_with_environment([{OSVar, Key, Transform}], list(), map()) -> map()
%% requires `ConfigMap' contains every key and its default
%% will replace the defaults with the value from either the OS environment or application
%% environment, with the OS environment taking precedence.
-spec merge_list_with_environment([{OSVar, Key, Transform}], AppEnv, ConfigMap) -> ConfigMap
when OSVar :: string(),
Key :: atom(),
Transform :: atom().
Transform :: atom(),
AppEnv :: [{atom(), term()}],
ConfigMap :: map().
merge_list_with_environment(ConfigMappings, AppEnv, ConfigMap) ->
lists:foldl(fun({OSVar, Key, Transform}, Acc) ->
case os:getenv(OSVar) of
false ->
%% not in the OS environment so check application environment
case lists:keyfind(Key, 1, AppEnv) of
false ->
%% not in the application env so leave default
Acc;
{_, Value} ->
%% transform even the value from the
%% application environment to ensure it
%% is of the right type/format
try transform(Transform, Value) of
TransformedValue ->
Acc#{Key := TransformedValue}
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => transform,
kind => Kind,
reason => Reason,
os_var => OSVar,
key => Key,
transform => Transform,
value => Value,
stacktrace => StackTrace},
#{report_cb => fun ?MODULE:report_cb/1}),
Acc
end
update_config_map(OSVar, Key, Transform, Value, Acc)
end;
OSVal ->
try transform(Transform, OSVal) of
TransformedValue ->
Acc#{Key := TransformedValue}
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => transform,
kind => Kind,
reason => Reason,
os_var => OSVar,
key => Key,
transform => Transform,
value => OSVal,
stacktrace => StackTrace},
#{report_cb => fun ?MODULE:report_cb/1}),
Acc
end
update_config_map(OSVar, Key, Transform, OSVal, Acc)
end
end, ConfigMap, ConfigMappings).

-spec merge_with_environment([{OSVar, Key, Transform}], map()) -> map()
update_config_map(OSVar, Key, Transform, Value, ConfigMap) ->
try transform(Transform, Value) of
TransformedValue ->
ConfigMap#{Key := TransformedValue}
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => transform,
kind => Kind,
reason => Reason,
os_var => OSVar,
key => Key,
transform => Transform,
value => Value,
stacktrace => StackTrace},
#{report_cb => fun ?MODULE:report_cb/1}),
ConfigMap
end.

-spec merge_with_os_environment([{OSVar, Key, Transform}], map()) -> map()
when OSVar :: string(),
Key :: atom(),
Transform :: atom().
merge_with_environment(ConfigMappings, Opts) ->
merge_with_os_environment(ConfigMappings, Opts) ->
lists:foldl(fun({OSVar, Key, Transform}, Acc) ->
case os:getenv(OSVar) of
false ->
Expand Down Expand Up @@ -234,17 +232,21 @@ report_cb(#{source := transform,
config_mappings(general_sdk) ->
[{"OTEL_LOG_LEVEL", log_level, existing_atom},
{"OTEL_REGISTER_LOADED_APPLICATIONS", register_loaded_applications, boolean},
{"OTEL_ID_GENERATOR", id_generator, existing_atom},
{"OTEL_DENY_LIST", deny_list, list},
{"OTEL_PROPAGATORS", text_map_propagators, propagators},
{"OTEL_TRACES_EXPORTER", traces_exporter, exporter},
{"OTEL_METRICS_EXPORTER", metrics_exporter, exporter}];
{"OTEL_METRICS_EXPORTER", metrics_exporter, exporter},
{"OTEL_RESOURCE_DETECTORS", resource_detectors, kvlist_value},
{"OTEL_RESOURCE_DETECTOR_TIMEOUT", resource_detector_timeout, integer}];
config_mappings(otel_batch_processor) ->
[{"OTEL_BSP_SCHEDULE_DELAY_MILLIS", scheduled_delay_ms, integer}, %% 5000,
{"OTEL_BSP_EXPORT_TIMEOUT_MILLIS", exporting_timeout_ms, integer}, %% 30000,
{"OTEL_BSP_MAX_QUEUE_SIZE", max_queue_size, integer}, %% 2048,
[{"OTEL_BSP_SCHEDULE_DELAY_MILLIS", scheduled_delay_ms, integer},
{"OTEL_BSP_EXPORT_TIMEOUT_MILLIS", exporting_timeout_ms, integer},
{"OTEL_BSP_MAX_QUEUE_SIZE", max_queue_size, integer},
%% a second usage of OTEL_TRACES_EXPORTER to set the exporter used by batch processor
{"OTEL_TRACES_EXPORTER", exporter, exporter} %% "otlp",
{"OTEL_TRACES_EXPORTER", exporter, exporter}
%% the following are not supported yet
%% {"OTEL_BSP_MAX_EXPORT_BATCH_SIZE", max_export_batch_size, 512}
%% {"OTEL_BSP_MAX_EXPORT_BATCH_SIZE", max_export_batch_size, integer}
];
config_mappings(span_limits) ->
[{"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", attribute_count_limit, integer},
Expand All @@ -253,8 +255,14 @@ config_mappings(span_limits) ->
{"OTEL_SPAN_LINK_COUNT_LIMIT", link_count_limit, integer},
{"OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", attribute_per_event_limit, integer},
{"OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", attribute_per_link_limit, integer}%% ,
%% {"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", attribute_value_length_limit, 128, integer},
%% {"OTEL_ATTRIBUTE_COUNT_LIMIT", attribute_per_link_limit, 128, integer}
%% {"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", attribute_value_length_limit, integer},
%% {"OTEL_ATTRIBUTE_COUNT_LIMIT", attribute_per_link_limit, integer}
];
config_mappings(sweeper) ->
[{"OTEL_SPAN_SWEEPER_INTERVAL", interval, integer_infinity},
{"OTEL_SPAN_SWEEPER_STRATEGY", strategy, atom_or_fun},
{"OTEL_SPAN_SWEEPER_SPAN_TTL", span_ttl, integer_infinity},
{"OTEL_SPAN_SWEEPER_STORAGE_SIZE", storage_size, integer_infinity}
];
config_mappings(_) ->
[].
Expand Down Expand Up @@ -289,6 +297,12 @@ transform(existing_atom, Value) when is_atom(Value) ->
Value;
transform(existing_atom, Value) when is_list(Value) ->
list_to_existing_atom(Value);
transform(atom_or_fun, Value) when is_list(Value) ->
list_to_existing_atom(Value);
transform(atom_or_fun, Value) when is_atom(Value) ->
Value;
transform(atom_or_fun, Value) when is_function(Value) ->
Value;
transform(boolean, Value) when is_boolean(Value) ->
Value;
transform(boolean, "true") ->
Expand Down
13 changes: 7 additions & 6 deletions apps/opentelemetry/src/otel_resource_detector.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@
detectors :: [detector()],
detector_timeout :: integer()}).

start_link(Opts) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
-spec start_link(Config) -> {ok, pid()} | ignore | {error, term()} when
Config :: #{resource_detectors := [module()],
resource_detector_timeout := integer()}.
start_link(Config) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Config], []).

get_resource() ->
get_resource(6000).
Expand All @@ -66,12 +69,10 @@ get_resource(Timeout) ->
otel_resource:create([])
end.

init([_Opts]) ->
init([#{resource_detectors := Detectors,
resource_detector_timeout := DetectorTimeout}]) ->
process_flag(trap_exit, true),

Detectors = application:get_env(opentelemetry, resource_detectors, []),
DetectorTimeout = application:get_env(opentelemetry, resource_detectors_timeout, 5000),

{ok, collecting, #data{resource=otel_resource:create([]),
detectors=Detectors,
detector_timeout=DetectorTimeout},
Expand Down
10 changes: 5 additions & 5 deletions apps/opentelemetry/src/otel_span_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@

-define(SERVER, ?MODULE).

start_link(Opts) ->
supervisor:start_link({local, ?SERVER}, ?MODULE, [Opts]).
start_link(Config) ->
supervisor:start_link({local, ?SERVER}, ?MODULE, [Config]).

start_child(ChildSpec) ->
supervisor:start_child(?SERVER, ChildSpec).

init([_Opts]) ->
init([Config]) ->
SupFlags = #{strategy => one_for_one,
intensity => 1,
period => 5},

SweeperOpts = application:get_env(opentelemetry, sweeper, #{}),
SweeperConfig = maps:get(sweeper, Config),
Sweeper = #{id => otel_span_sweeper,
start => {otel_span_sweeper, start_link, [SweeperOpts]},
start => {otel_span_sweeper, start_link, [SweeperConfig]},
restart => permanent,
shutdown => 5000,
type => worker,
Expand Down
15 changes: 7 additions & 8 deletions apps/opentelemetry/src/otel_span_sweeper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@
storage_size() ->
{ets:info(?SPAN_TAB, size), ets:info(?SPAN_TAB, memory) * erlang:system_info({wordsize, external})}.

start_link(Opts) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Opts], []).

init([SweeperConfig]) ->
Interval = maps:get(interval, SweeperConfig, timer:minutes(10)),
Strategy = maps:get(strategy, SweeperConfig, drop),
TTL = maps:get(span_ttl, SweeperConfig, timer:minutes(30)),
StorageSize = maps:get(storage_size, SweeperConfig, infinity),
start_link(Config) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Config], []).

init([#{interval := Interval,
strategy := Strategy,
span_ttl := TTL,
storage_size := StorageSize}]) ->
{ok, ready, #data{interval=Interval,
strategy=Strategy,
ttl=maybe_convert_time_unit(TTL),
Expand Down
17 changes: 8 additions & 9 deletions apps/opentelemetry/src/otel_tracer_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,17 @@
telemetry_library :: telemetry_library()
}).

start_link(Opts) ->
gen_server:start_link({local, otel_tracer_provider}, ?MODULE, Opts, []).

init(Opts) ->
-spec start_link(otel_configuration:t()) -> {ok, pid()} | ignore | {error, term()}.
start_link(Config) ->
gen_server:start_link({local, otel_tracer_provider}, ?MODULE, Config, []).

init(#{id_generator := IdGeneratorModule,
sampler := SamplerSpec,
processors := Processors,
deny_list := DenyList}) ->
Resource = otel_resource_detector:get_resource(),

IdGeneratorModule = application:get_env(opentelemetry, id_generator, otel_id_generator),

SamplerSpec = maps:get(sampler, Opts),
Sampler = otel_sampler:new(SamplerSpec),
Processors = maps:get(processors, Opts),
DenyList = application:get_env(opentelemetry, deny_list, []),

{ok, LibraryVsn} = application:get_key(opentelemetry, vsn),
LibraryName = <<"opentelemetry">>,
Expand Down
Loading

0 comments on commit 3d56c11

Please sign in to comment.