Skip to content

Commit

Permalink
Merge pull request #129 from rkallos/telemetry
Browse files Browse the repository at this point in the history
Integrate with :telemetry
  • Loading branch information
lpgauth authored Jul 29, 2023
2 parents a4f7d82 + 6fdbe40 commit 3d8d7cc
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 107 deletions.
46 changes: 2 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,50 +212,8 @@ shackle_pool:start(pool_name(), client(), client_options(), pool_options())
{ok, <<"bar">>}
```

## Environment variables

<table width="100%">
<theader>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</theader>
<tr>
<td>hooks</td>
<td>[{atom(), {module(), atom()}}]</td>
<td>[]</td>
<td>used to receive events/metrics about your client</td>
</tr>
</table>

## Hooks
Hooks allow you to receive events and metrics about your client. To do so you need to implement the `shackle_hooks` behaviour and then use the `hooks` environment variable.

```erlang
-module(my_client_hooks).

-behaviour(shackle_hooks).
-export([
metrics/4
]).

metrics(Client, counter, Key, Value) ->
statsderl:increment(key(Client, Key), Value, 0.005);
metrics(Client, timing, Key, Value) ->
statsderl:timing(key(Client, Key), Value, 0.005).

key(Client, Key) ->
[<<"shackle.">>, atom_to_binary(Client, latin1), <<".">>, Key].
```

```erlang
{shackle, [
{hooks, [
{metrics {my_client_hooks, metrics}}
]}
]}
```
## Telemetry
Shackle integrates with the backend-agnostic [telemetry](https://hexdocs.pm/telemetry/) library. See `shackle_telemetry` for the list of telemetry events that shackle can emit.

## Tests

Expand Down
2 changes: 0 additions & 2 deletions include/shackle_internal.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
-define(GET_ENV(Key, Default), application:get_env(?APP, Key, Default)).
-define(LOOKUP(Key, List), ?LOOKUP(Key, List, undefined)).
-define(LOOKUP(Key, List, Default), shackle_utils:lookup(Key, List, Default)).
-define(METRICS(Client, Type, Key), shackle_hooks:metrics(Client, Type, Key, 1)).
-define(METRICS(Client, Type, Key, Value), shackle_hooks:metrics(Client, Type, Key, Value)).
-define(MSG_CONNECT, connect).
-define(SERVER, shackle_server).
-define(SUPERVISOR, shackle_sup).
Expand Down
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
{deps, [
{foil, "0.1.3"},
{granderl, {git, "https://github.com/tokenrove/granderl.git", {ref, "baafd1bc825cb1fc022760eae913f774fa6af91b"}}},
{metal, "0.1.1"}
{metal, "0.1.1"},
{telemetry, "1.2.1"}
]}.

{dialyzer, [{plt_extra_apps, [public_key]}]}.
Expand Down
9 changes: 6 additions & 3 deletions rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
{git,"https://github.com/tokenrove/granderl.git",
{ref,"baafd1bc825cb1fc022760eae913f774fa6af91b"}},
0},
{<<"metal">>,{pkg,<<"metal">>,<<"0.1.1">>},0}]}.
{<<"metal">>,{pkg,<<"metal">>,<<"0.1.1">>},0},
{<<"telemetry">>,{pkg,<<"telemetry">>,<<"1.2.1">>},0}]}.
[
{pkg_hash,[
{<<"foil">>, <<"415835CA94A8D0A55AB3D334FE2D1A1DCF36E7A0F69789050765770B6BF5E6E9">>},
{<<"metal">>, <<"5D3D1322DA7BCD34B94FED5486F577973685298883954F7A3E517EF5EF6953F5">>}]},
{<<"metal">>, <<"5D3D1322DA7BCD34B94FED5486F577973685298883954F7A3E517EF5EF6953F5">>},
{<<"telemetry">>, <<"68FDFE8D8F05A8428483A97D7AAB2F268AAFF24B49E0F599FAA091F1D4E7F61C">>}]},
{pkg_hash_ext,[
{<<"foil">>, <<"3A1CC0939075D7E26F8ED9983839E2E9CE4B2AE301110F7DF5A6EDA544FCD125">>},
{<<"metal">>, <<"88B82B634998A1A768DEDCD372C2F7E657B19445325C0AF5CCBAC62C77210F1D">>}]}
{<<"metal">>, <<"88B82B634998A1A768DEDCD372C2F7E657B19445325C0AF5CCBAC62C77210F1D">>},
{<<"telemetry">>, <<"DAD9CE9D8EFFC621708F99EAC538EF1CBE05D6A874DD741DE2E689C47FEAFED5">>}]}
].
2 changes: 1 addition & 1 deletion src/shackle.app.src
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{application, shackle, [
{applications, [kernel, stdlib, granderl, metal, foil, ssl]},
{applications, [kernel, stdlib, granderl, metal, foil, ssl, telemetry]},
{description, "High-Performance Erlang Network Client Framework"},
{env, []},
{licenses, ["MIT"]},
Expand Down
44 changes: 0 additions & 44 deletions src/shackle_hooks.erl

This file was deleted.

6 changes: 3 additions & 3 deletions src/shackle_pool.erl
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ server(_Name, #pool_options {
client = Client
}, 0) ->

?METRICS(Client, counter, <<"no_server">>),
shackle_telemetry:no_server(Client),
{error, no_server};
server(Name, #pool_options {
backlog_size = BacklogSize,
Expand All @@ -157,11 +157,11 @@ server(Name, #pool_options {
true ->
{ok, Client, ServerName};
false ->
?METRICS(Client, counter, <<"backlog_full">>),
shackle_telemetry:backlog_full(Client),
server(Name, Options, N - 1)
end;
false ->
?METRICS(Client, counter, <<"disabled">>),
shackle_telemetry:disabled(Client),
server(Name, Options, N - 1)
end.

Expand Down
16 changes: 8 additions & 8 deletions src/shackle_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ handle_msg({Request, #cast {
{ok, ExtRequestId, Data, ClientState2} ->
case Protocol:send(Socket, Data) of
ok ->
?METRICS(Client, counter, <<"send">>),
shackle_telemetry:send(Client, size(Data)),
case ExtRequestId of
undefined ->
reply(ok, Cast, State);
Expand Down Expand Up @@ -184,7 +184,7 @@ handle_msg({timeout, ExtRequestId}, {#state {
true ->
try Client:handle_timeout(ExtRequestId, ClientState) of
{ok, Reply, ClientState2} ->
?METRICS(Client, counter, <<"handle_timeout">>),
shackle_telemetry:handle_timeout(Client),
process_responses([Reply], State),
{ok, {State, ClientState2}};
{error, Reason, ClientState2} ->
Expand All @@ -201,7 +201,7 @@ handle_msg({timeout, ExtRequestId}, {#state {
false ->
case shackle_queue:remove(Queue, Id, ExtRequestId) of
{ok, Cast, _TimerRef} ->
?METRICS(Client, counter, <<"timeout">>),
shackle_telemetry:timeout(Client),
reply({error, timeout}, Cast, State);
{error, not_found} ->
ok
Expand Down Expand Up @@ -325,7 +325,7 @@ handle_msg_data(Socket, Data, #state {
socket = Socket
} = State, ClientState) ->

?METRICS(Client, counter, <<"recv">>),
shackle_telemetry:recv(Client, size(Data)),
try Client:handle_data(Data, ClientState) of
{ok, Replies, ClientState2} ->
process_responses(Replies, State),
Expand Down Expand Up @@ -364,16 +364,16 @@ process_responses([{ExtRequestId, Reply} | T], #state {
queue = Queue
} = State) ->

?METRICS(Client, counter, <<"replies">>),
shackle_telemetry:replies(Client),
case shackle_queue:remove(Queue, Id, ExtRequestId) of
{ok, #cast {timestamp = Timestamp} = Cast, TimerRef} ->
?METRICS(Client, counter, <<"found">>),
shackle_telemetry:found(Client),
Diff = timer:now_diff(os:timestamp(), Timestamp),
?METRICS(Client, timing, <<"reply">>, Diff),
shackle_telemetry:reply(Client, Diff),
erlang:cancel_timer(TimerRef),
reply(Reply, Cast, State);
{error, not_found} ->
?METRICS(Client, counter, <<"not_found">>, 1),
shackle_telemetry:not_found(Client),
ok
end,
process_responses(T, State).
Expand Down
1 change: 0 additions & 1 deletion src/shackle_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ start_link() ->
{ok, {{one_for_one, 5, 10}, [supervisor:child_spec()]}}.

init([]) ->
shackle_hooks:init(),
shackle_pool:init(),
shackle_status:init(),

Expand Down
85 changes: 85 additions & 0 deletions src/shackle_telemetry.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
-module(shackle_telemetry).
-include("shackle_internal.hrl").

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

-export([
backlog_full/1,
disabled/1,
found/1,
handle_timeout/1,
no_server/1,
not_found/1,
recv/2,
replies/1,
reply/2,
send/2,
timeout/1
]).

-spec backlog_full(client()) -> ok.
backlog_full(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, backlog_full], Measurements, Metadata).

-spec disabled(client()) -> ok.
disabled(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, disabled], Measurements, Metadata).

-spec found(client()) -> ok.
found(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, found], Measurements, Metadata).

-spec handle_timeout(client()) -> ok.
handle_timeout(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, handle_timeout], Measurements, Metadata).

-spec no_server(client()) -> ok.
no_server(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, no_server], Measurements, Metadata).

-spec not_found(client()) -> ok.
not_found(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, not_found], Measurements, Metadata).

-spec recv(client(), non_neg_integer()) -> ok.
recv(Client, NBytes) ->
Measurements = #{count => 1, bytes => NBytes},
Metadata = #{client => Client},
telemetry:execute([shackle, recv], Measurements, Metadata).

-spec replies(client()) -> ok.
replies(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, replies], Measurements, Metadata).

-spec reply(client(), non_neg_integer()) -> ok.
reply(Client, Microseconds) ->
Measurements = #{duration => Microseconds},
Metadata = #{client => Client},
telemetry:execute([shackle, reply], Measurements, Metadata).

-spec send(client(), non_neg_integer()) -> ok.
send(Client, NBytes) ->
Measurements = #{count => 1, bytes => NBytes},
Metadata = #{client => Client},
telemetry:execute([shackle, send], Measurements, Metadata).

-spec timeout(client()) -> ok.
timeout(Client) ->
Measurements = #{count => 1},
Metadata = #{client => Client},
telemetry:execute([shackle, timeout], Measurements, Metadata).

0 comments on commit 3d8d7cc

Please sign in to comment.