Current section
Files
Jump to
Current section
Files
src/dogstatsd_app.erl
-module(dogstatsd_app).
-behavior(application).
-export([start/2, stop/1]).
start(_Type, _Args) ->
configure(),
dogstatsd_sup:start_link().
stop(_State) ->
ok.
configure() ->
Config = [
{agent_address, "AGENT_ADDRESS", [{default, "localhost"}]}
,{agent_port, "AGENT_PORT", [{default, 8125}, {transform, integer}]}
,{global_prefix, "GLOBAL_PREFIX", [{default, ""}]}
,{global_tags, "GLOBAL_TAGS", [{default, #{}}, {transform, fun transform_map/1}]}
,{send_metrics, "SEND_METRICS", [{default, true}, {transform, fun transform_boolean/1}]}
,{vm_stats, "VM_STATS", [{default, true}, {transform, fun transform_boolean/1}]}
,{vm_stats_delay, "VM_STATS_DELAY", [{default, 60000}, {transform, integer}]}
,{vm_stats_scheduler, "VM_STATS_SCHEDULER", [{default, true}, {transform, fun transform_boolean/1}]}
,{vm_stats_base_key, "VM_STATS_BASE_KEY", [{default, "erlang.vm"}]}
],
Config1 = read_app_config(Config),
ok = stillir:set_config(dogstatsd, Config1).
read_app_config(Config) ->
lists:map(fun ({AppVar, EnvVar, Opts0}) ->
Opts1 = case application:get_env(dogstatsd, AppVar) of
{ok, Value} ->
lists:keystore(default, 1, Opts0, {default, Value});
undefined ->
Opts0
end,
{AppVar, EnvVar, Opts1}
end,
Config).
transform_map(String) ->
CompressedString = re:replace(String, <<" ">>, <<>>, [global]),
TrimmedString = case re:run(CompressedString, <<"#{(.*)}">>, [{capture, all_but_first, list}]) of
nomatch ->
CompressedString;
{match, [Inner]} ->
Inner
end,
lists:foldl(fun (<<>>, Acc) ->
Acc;
(El, Acc) ->
io:format("El=~p", [El]),
case re:split(El, <<"=>?">>, [{return, binary}]) of
[Key, Value] ->
maps:put(Key, Value, Acc);
Other ->
erlang:error({cannot_parse_kv_pair, Other})
end
end,
#{},
re:split(TrimmedString, <<$,>>, [{return, binary}])).
transform_boolean(String) ->
case string:to_lower(string:strip(String)) of
"true" ->
true;
"yes" ->
true;
"1" ->
true;
"false" ->
false;
"no" ->
false;
"0" ->
false;
_ ->
erlang:error({not_a_boolean, String})
end.
%%% Tests
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
transform_boolean_test_() -> [
?_assert(transform_boolean("true"))
,?_assert(transform_boolean("TRUE"))
,?_assert(transform_boolean("True"))
,?_assert(transform_boolean("Yes"))
,?_assert(transform_boolean("1"))
,?_assertNot(transform_boolean("0"))
,?_assertNot(transform_boolean("NO"))
,?_assertNot(transform_boolean("false"))
,?_assertNot(transform_boolean("FALSE"))
,?_assertError({not_a_boolean, "nope"}, transform_boolean("nope"))
,?_assertError({not_a_boolean, ""}, transform_boolean(""))
,?_assertError(function_clause, transform_boolean(0))
].
transform_map_test_() -> [
?_assertEqual(#{<<"hello">> => <<"world">>}, transform_map("#{hello=>world}"))
,?_assertEqual(#{<<"hello">> => <<"world">>}, transform_map("hello=world"))
,?_assertEqual(#{<<"hello">> => <<"world">>}, transform_map("hello = world"))
,?_assertEqual(#{<<"hello">> => <<"world">>}, transform_map("hello=> world"))
,?_assertEqual(#{<<"a">> => <<"1">>, <<"b">> => <<"2">>, <<"c">> => <<"3">>},
transform_map("#{a=>1,b=>2,c=>3}"))
,?_assertEqual(#{<<"hello">> => <<"world">>}, transform_map("#{ hello => world }"))
,?_assertEqual(#{}, transform_map(""))
,?_assertError({cannot_parse_kv_pair, _}, transform_map("hello"))
,?_assertError({cannot_parse_kv_pair, _}, transform_map("#{hello}"))
,?_assertError({cannot_parse_kv_pair, _}, transform_map("#{hello,world}"))
].
supervisor_test_() ->
{setup,
fun () ->
application:ensure_all_started(worker_pool),
configure()
end,
fun (_) ->
application:stop(worker_pool)
end,
[
?_assertMatch({ok,_Pid}, dogstatsd_sup:start_link())
]}.
application_test_() ->
{setup,
fun () ->
meck:new(gen_udp, [unstick]),
meck:expect(gen_udp, send, fun (_Socket, _Address, _Port, _Packet) -> ok end),
meck:expect(gen_udp, open, fun (_Port) -> {ok, fake_socket} end),
application:ensure_all_started(dogstatsd)
end,
fun (_) ->
meck:unload(gen_udp),
application:stop(worker_pool)
end,
[
?_assertMatch(ok, dogstatsd:gauge("test", 1))
,?_assert(meck:validate(gen_udp))
,?_assert(meck:called(gen_udp, send, '_'))
]}.
-endif.