Skip to content

Commit

Permalink
Re-add incr + decr counter
Browse files Browse the repository at this point in the history
  • Loading branch information
lpgauth committed Nov 5, 2016
1 parent 62ad691 commit 258b9e3
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 56 deletions.
13 changes: 13 additions & 0 deletions src/statsderl.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
%% public
-export([
counter/3,
decrement/3,
gauge/3,
gauge_decrement/3,
gauge_increment/3,
increment/3,
timing/3,
timing_fun/3,
timing_now/3,
Expand All @@ -23,6 +25,12 @@
counter(Key, Value, Rate) ->
statsderl_pool:sample(Rate, {counter, Key, Value, Rate}).

-spec decrement(key(), value(), sample_rate()) ->
ok.

decrement(Key, Value, Rate) when Value >= 0 ->
statsderl_pool:sample(Rate, {counter, Key, -Value, Rate}).

-spec gauge(key(), value(), sample_rate()) ->
ok.

Expand All @@ -41,6 +49,11 @@ gauge_decrement(Key, Value, Rate) when Value >= 0 ->
gauge_increment(Key, Value, Rate) when Value >= 0 ->
statsderl_pool:sample(Rate, {gauge_increment, Key, Value}).

-spec increment(key(), value(), sample_rate()) ->
ok.

increment(Key, Value, Rate) when Value >= 0 ->
statsderl_pool:sample(Rate, {counter, Key, Value, Rate}).

-spec timing(key(), value(), sample_rate()) ->
ok.
Expand Down
2 changes: 1 addition & 1 deletion src/statsderl_debug.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test() ->
B = 10,
C = 0.666,

statsderl:counter(["hello", <<"world">>], 1, 0.5),
statsderl:counter(["hello", <<"world">>], -1, 0.5),
statsderl:counter(["hello", A], 1, 0.5),
statsderl:counter(["hello", <<"world">>], B, 0.5),
statsderl:counter(["hello", <<"world">>], 1, C),
Expand Down
120 changes: 73 additions & 47 deletions src/statsderl_transform.erl
Original file line number Diff line number Diff line change
Expand Up @@ -13,84 +13,110 @@
parse_transform(Forms, _Options) ->
parse_trans:plain_transform(fun do_transform/1, Forms).

do_transform({call, _, {_, _, {_, _, ?APP}, {_, _, timing_fun}}, _} = F) ->
F;
do_transform({call, Line, {_, _, {_, _, ?APP}, {_, _, OpCode}}, Args} = F) ->
[Key, Value, Rate] = Args,
RateScaled = rate_scaled(Rate),
Packet = packet(OpCode, Key, Value, Rate),

case {RateScaled, Packet} of
{undefined, undefined} ->
F;
{_, undefined} ->
{call, Line, {remote, Line,
{atom, Line, statsderl_pool},
{atom, Line, sample_scaled}}, [
{integer, Line, RateScaled},
{tuple, Line, [{atom, Line, OpCode}, Key, Value, Rate]}
]};
{undefined, _} ->
Packet2 = erl_syntax:revert(erl_syntax:binary(
[erl_syntax:binary_field(erl_syntax:string(Packet))])),

{call, Line, {remote, Line,
{atom, Line, statsderl_pool},
{atom, Line, sample}}, [
Rate,
{tuple, Line, [{atom, Line, cast}, Packet2]}
]};
_ ->
Packet2 = erl_syntax:revert(erl_syntax:binary(
[erl_syntax:binary_field(erl_syntax:string(Packet))])),

{call, Line, {remote, Line,
{atom, Line, statsderl_pool},
{atom, Line, sample_scaled}}, [
{integer, Line, RateScaled},
{tuple, Line, [{atom, Line, cast}, Packet2]}
]}
end;
do_transform({call, _, {_, _, {_, _, ?APP}, Function}, _} = F) ->
replace(safe_normalize(Function), F);
do_transform(_Form) ->
continue.

%% private
encode(Op) ->
Proto = statsderl_protocol:encode(Op),
binary_to_list(iolist_to_binary(Proto)).

not_undefined([]) ->
true;
not_undefined([undefined | _]) ->
false;
not_undefined([_ | T]) ->
not_undefined(T).

op_code(increment) ->
counter;
op_code(decrement) ->
counter;
op_code(Function) ->
Function.

packet(counter, Key, Value, Rate) ->
Key2 = safe_normalize(Key),
Value2 = safe_normalize(Value),
Rate2 = safe_normalize(Rate),

case Key2 /= undefined andalso Value2 /= undefined
andalso Rate2 /= undefined of

case not_undefined([Key2, Value2, Rate2]) of
true ->
Proto = statsderl_protocol:encode({counter, Key2, Value2, Rate2}),
binary_to_list(iolist_to_binary(Proto));
encode({counter, Key2, Value2, Rate2});
false ->
undefined
end;
packet(OpCode, Key, Value, _Rate) ->
Key2 = safe_normalize(Key),
Value2 = safe_normalize(Value),

case Key2 /= undefined andalso Value2 /= undefined of
case not_undefined([Key2, Value2]) of
true ->
Proto = statsderl_protocol:encode({OpCode, Key2, Value2}),
binary_to_list(iolist_to_binary(Proto));
encode({OpCode, Key2, Value2});
false ->
undefined
end.

rate_scaled({float, _, RateValue}) ->
trunc(RateValue * ?MAX_UNSIGNED_INT_32);
rate_scaled({integer, _, RateValue}) ->
trunc(RateValue * ?MAX_UNSIGNED_INT_32);
trunc(RateValue * ?MAX_UNSIGNED_INT_32);
rate_scaled(_) ->
undefined.

replace(timing_fun, F) ->
F;
replace(Function, F) ->
{call, _, {_, _, _, _}, [Key, Value, Rate]} = F,


OpCode = op_code(Function),
RateScaled = rate_scaled(Rate),
Value2 = value(Function, Value),
Packet = packet(OpCode, Key, Value2, Rate),

case {RateScaled, Packet} of
{undefined, undefined} ->
F;
{_, undefined} ->
{call, 0, {remote, 0,
{atom, 0, statsderl_pool},
{atom, 0, sample_scaled}}, [
{integer, 0, RateScaled},
{tuple, 0, [{atom, 0, OpCode}, Key, Value2, Rate]}
]};
{undefined, _} ->
Packet2 = erl_syntax:revert(erl_syntax:binary(
[erl_syntax:binary_field(erl_syntax:string(Packet))])),

{call, 0, {remote, 0,
{atom, 0, statsderl_pool},
{atom, 0, sample}}, [
Rate,
{tuple, 0, [{atom, 0, cast}, Packet2]}
]};
_ ->
Packet2 = erl_syntax:revert(erl_syntax:binary(
[erl_syntax:binary_field(erl_syntax:string(Packet))])),

{call, 0, {remote, 0,
{atom, 0, statsderl_pool},
{atom, 0, sample_scaled}}, [
{integer, 0, RateScaled},
{tuple, 0, [{atom, 0, cast}, Packet2]}
]}
end.

safe_normalize(AbsTerm) ->
try erl_parse:normalise(AbsTerm)
catch
_:_ ->
undefined
end.

value(decrement, Value) ->
{op, 0, '-', Value};
value(_, Value) ->
Value.
21 changes: 13 additions & 8 deletions test/statsderl_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,26 @@ statsderl_test_() ->
fun () -> setup() end,
fun (Socket) -> cleanup(Socket) end,
{with, [
fun counter_decrement_subtest/1,
fun counter_increment_subtest/1,
fun counter_subtest/1,
fun decrement_subtest/1,
fun gauge_decrement_subtest/1,
fun gauge_increment_subtest/1,
fun gauge_subtest/1,
fun increment_subtest/1,
fun sampling_rate_subtest/1,
fun timing_fun_subtest/1,
fun timing_subtest/1
]}
}.

%% subtests
counter_decrement_subtest(Socket) ->
statsderl:counter("test", -1, 1.0),
assert_packet(Socket, <<"test:-1|c">>).
counter_subtest(Socket) ->
statsderl:counter("test", 1.123, 1),
assert_packet(Socket, <<"test:1.12|c">>).

counter_increment_subtest(Socket) ->
statsderl:counter("test", 1, 1),
assert_packet(Socket, <<"test:1|c">>).
decrement_subtest(Socket) ->
statsderl:decrement("test", 1, 1.0),
assert_packet(Socket, <<"test:-1|c">>).

gauge_subtest(Socket) ->
statsderl:gauge("test", 1, 1),
Expand All @@ -59,6 +60,10 @@ gauge_increment_subtest(Socket) ->
statsderl:gauge_increment("test", 1, 1),
assert_packet(Socket, <<"test:+1|g">>).

increment_subtest(Socket) ->
statsderl:increment("test", 1, 1),
assert_packet(Socket, <<"test:1|c">>).

sampling_rate_subtest(Socket) ->
meck:new(statsderl_utils, [passthrough, no_history]),
meck:expect(statsderl_utils, random, fun (?MAX_UNSIGNED_INT_32) -> 1 end),
Expand Down

0 comments on commit 258b9e3

Please sign in to comment.