Skip to content

Commit

Permalink
Merge 6709788 into b0beb37
Browse files Browse the repository at this point in the history
  • Loading branch information
lpgauth committed Nov 6, 2016
2 parents b0beb37 + 6709788 commit 405aa24
Show file tree
Hide file tree
Showing 18 changed files with 425 additions and 163 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ language: erlang
notifications:
email: false
otp_release:
- 19.1
- 18.3
- 17.5
script: "make travis"
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ High Performance Erlang StatsD Client
### Features

* Performance optimized
* Parse transform

## API
<a href="https://github.com/lpgauth/statsderl/blob/master/doc/statsderl.md#index" class="module">Function Index</a>
Expand Down Expand Up @@ -74,6 +75,13 @@ High Performance Erlang StatsD Client
</tr>
</table>

## Parse Transform

`statsderl_transform` is used to pre-compute (at compile time) the scaled sample rate and packet.

```erlang
-compile({parse_transform, statsderl_transform}).
```
## Examples

```erlang
Expand Down Expand Up @@ -120,10 +128,6 @@ ok.
make test
```

### TODOs

* parse transform for type conversion

## License

```license
Expand Down
Binary file modified bin/rebar3
Binary file not shown.
11 changes: 8 additions & 3 deletions include/statsderl.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
-type base_key() :: base_key_part() | [base_key_part()].
-type base_key_part() :: hostname | name | sname | undefined | iodata().
-type key() :: iodata().
-type op_code() :: decrement | gauge | gauge_decrement | gauge_increment |
increment | timing.
-type operation() :: {cast, iodata()} |
{counter, key(), value(), sample_rate()} |
{gauge, key(), value()} |
{gauge_decrement, key(), value()} |
{gauge_increment, key(), value()} |
{timing, key(), value()} |
{timing_now, key(), erlang:timestamp()} |
{timing_now_us, key(), erlang:timestamp()}.
-type sample_rate() :: number().
-type value() :: number().

6 changes: 5 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
{cover_excl_mods, [
statsderl_profile,
statsderl_tests,
statsderl_transform,
statsderl_transform_tests,
statsderl_utils_tests
]}.
{coveralls_coverdata, "_build/test/cover/eunit.coverdata"}.
{coveralls_service_name, "travis-ci"}.

{deps, [
{granderl, ".*",
{git, "https://github.com/tokenrove/granderl.git", {tag, "v0.1.4"}}}
{git, "https://github.com/tokenrove/granderl.git", {tag, "v0.1.4"}}},
{parse_trans, ".*",
{git, "https://github.com/uwiger/parse_trans.git", {tag, "3.0.0"}}}
]}.

{edoc_opts, [
Expand Down
4 changes: 4 additions & 0 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[{<<"granderl">>,
{git,"https://github.com/tokenrove/granderl.git",
{ref,"b44725cdd3ae6d2d4170e0d72ebb2fcad98d5ad2"}},
0},
{<<"parse_trans">>,
{git,"https://github.com/uwiger/parse_trans.git",
{ref,"6f3645afb43c7c57d61b54ef59aecab288ce1013"}},
0}].
86 changes: 20 additions & 66 deletions src/statsderl.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,108 +22,62 @@
-spec counter(key(), value(), sample_rate()) ->
ok.

counter(Key, Value, SampleRate) ->
sample(counter, Key, Value, SampleRate).
counter(Key, Value, Rate) ->
statsderl_pool:sample(Rate, {counter, Key, Value, Rate}).

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

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

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

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

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

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

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

gauge_increment(Key, Value, SampleRate) when Value >= 0 ->
sample(gauge_increment, Key, Value, SampleRate).
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, SampleRate) when Value >= 0 ->
sample(counter, Key, Value, SampleRate).
increment(Key, Value, Rate) when Value >= 0 ->
statsderl_pool:sample(Rate, {counter, Key, Value, Rate}).

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

timing(Key, Value, SampleRate) ->
sample(timing, Key, Value, SampleRate).
timing(Key, Value, Rate) ->
statsderl_pool:sample(Rate, {timing, Key, Value}).

-spec timing_fun(key(), fun(), sample_rate()) ->
ok.

timing_fun(Key, Fun, SampleRate) ->
timing_fun(Key, Fun, Rate) ->
Timestamp = statsderl_utils:timestamp(),
Result = Fun(),
timing_now(Key, Timestamp, SampleRate),
timing_now(Key, Timestamp, Rate),
Result.

-spec timing_now(key(), erlang:timestamp(), sample_rate()) ->
ok.

timing_now(Key, Timestamp, SampleRate) ->
sample(timing_now, Key, Timestamp, SampleRate).
timing_now(Key, Timestamp, Rate) ->
statsderl_pool:sample(Rate, {timing_now, Key, Timestamp}).

-spec timing_now_us(key(), erlang:timestamp(), sample_rate()) ->
ok.

timing_now_us(Key, Timestamp, SampleRate) ->
sample(timing_now_us, Key, Timestamp, SampleRate).

%% private
cast(OpCode, Key, Value, SampleRate, ServerName) ->
Packet = statsderl_protocol:encode(OpCode, Key, Value, SampleRate),
send(ServerName, {cast, Packet}).

operation(OpCode, Key, Value, SampleRate) ->
ServerName = statsderl_utils:random_server(),
operation(OpCode, Key, Value, SampleRate, ServerName).

operation(timing_now, Key, Value, SampleRate, ServerName) ->
cast(timing, Key, timing_now(Value), SampleRate, ServerName);
operation(timing_now_us, Key, Value, SampleRate, ServerName) ->
cast(timing, Key, timing_now_us(Value), SampleRate, ServerName);
operation(OpCode, Key, Value, SampleRate, ServerName) ->
cast(OpCode, Key, Value, SampleRate, ServerName).

sample(OpCode, Key, Value, 1) ->
operation(OpCode, Key, Value, 1);
sample(OpCode, Key, Value, 1.0) ->
operation(OpCode, Key, Value, 1);
sample(OpCode, Key, Value, SampleRate) ->
Rand = statsderl_utils:random(?MAX_UNSIGNED_INT_32),
case Rand =< SampleRate * ?MAX_UNSIGNED_INT_32 of
true ->
N = Rand rem ?POOL_SIZE + 1,
ServerName = statsderl_utils:server_name(N),
operation(OpCode, Key, Value, SampleRate, ServerName);
false ->
ok
end.

send(ServerName, Msg) ->
case whereis(ServerName) of
undefined ->
ok;
Pid ->
Pid ! Msg
end.

timing_now(Timestamp) ->
timing_now_us(Timestamp) div 1000.

timing_now_us(Timestamp) ->
Timestamp2 = statsderl_utils:timestamp(),
timer:now_diff(Timestamp2, Timestamp).
timing_now_us(Key, Timestamp, Rate) ->
statsderl_pool:sample(Rate, {timing_now_us, Key, Timestamp}).
12 changes: 8 additions & 4 deletions src/statsderl_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,27 @@
]).

%% public
-spec start() -> {ok, [atom()]} | {error, term()}.
-spec start() ->
{ok, [atom()]} | {error, term()}.

start() ->
application:ensure_all_started(?APP).

-spec stop() -> ok | {error, {not_started, ?APP}}.
-spec stop() ->
ok | {error, {not_started, ?APP}}.

stop() ->
application:stop(?APP).

%% application callbacks
-spec start(application:start_type(), term()) -> {ok, pid()}.
-spec start(application:start_type(), term()) ->
{ok, pid()}.

start(_StartType, _StartArgs) ->
statsderl_sup:start_link().

-spec stop(term()) -> ok.
-spec stop(term()) ->
ok.

stop(_State) ->
ok.
73 changes: 73 additions & 0 deletions src/statsderl_pool.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
-module(statsderl_pool).
-include("statsderl.hrl").

-compile(inline).
-compile({inline_size, 512}).

-export([
sample/2,
sample_scaled/2,
server_name/1
]).

%% public
-spec sample(sample_rate(), operation()) ->
ok.

sample(1, Operation) ->
operation(Operation);
sample(1.0, Operation) ->
operation(Operation);
sample(Rate, Operation) ->
RateInt = trunc(Rate * ?MAX_UNSIGNED_INT_32),
sample_scaled(RateInt, Operation).

-spec sample_scaled(non_neg_integer(), operation()) ->
ok.

sample_scaled(RateInt, Operation) ->
Rand = granderl:uniform(?MAX_UNSIGNED_INT_32),
case Rand =< RateInt of
true ->
N = Rand rem ?POOL_SIZE + 1,
operation(Operation, server_name(N));
false ->
ok
end.

-spec server_name(1..4) ->
atom().

server_name(1) -> statsderl_1;
server_name(2) -> statsderl_2;
server_name(3) -> statsderl_3;
server_name(4) -> statsderl_4.

%% private
cast({cast, _} = Cast, ServerName) ->
send(ServerName, Cast);
cast(Operation, ServerName) ->
send(ServerName, {cast, statsderl_protocol:encode(Operation)}).

operation(Operation) ->
operation(Operation, random_server()).

operation({timing_now, Key, Value}, ServerName) ->
Value2 = statsderl_utils:timing_now(Value),
cast({timing, Key, Value2}, ServerName);
operation({timing_now_us, Key, Value}, ServerName) ->
Value2 = statsderl_utils:timing_now_us(Value),
cast({timing, Key, Value2}, ServerName);
operation(Operation, ServerName) ->
cast(Operation, ServerName).

random_server() ->
server_name(granderl:uniform(?POOL_SIZE)).

send(ServerName, Msg) ->
try
ServerName ! Msg
catch
_:_ ->
ok
end.
14 changes: 7 additions & 7 deletions src/statsderl_protocol.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
-compile({inline_size, 512}).

-export([
encode/4
encode/1
]).

%% public
-spec encode(op_code(), key(), value(), sample_rate()) -> iodata().
-spec encode(operation()) -> iodata().

encode(counter, Key, Value, SampleRate) ->
encode({counter, Key, Value, SampleRate}) ->
[Key, <<":">>, format_value(Value), <<"|c">>,
format_sample_rate(SampleRate)];
encode(gauge, Key, Value, _SampleRate) ->
encode({gauge, Key, Value}) ->
[Key, <<":">>, format_value(Value), <<"|g">>];
encode(gauge_decrement, Key, Value, _SampleRate) ->
encode({gauge_decrement, Key, Value}) ->
[Key, <<":-">>, format_value(Value), <<"|g">>];
encode(gauge_increment, Key, Value, _SampleRate) ->
encode({gauge_increment, Key, Value}) ->
[Key, <<":+">>, format_value(Value), <<"|g">>];
encode(timing, Key, Value, _SampleRate) ->
encode({timing, Key, Value}) ->
[Key, <<":">>, format_value(Value), <<"|ms">>].

%% private
Expand Down

0 comments on commit 405aa24

Please sign in to comment.