Browse Source

Add the possibility of calling the Exometer API for the metrics instead of the Folsom one

* It is still possible to define the callback module. It will expect either the Folsom or the Exometer callbacks depending on the configuration parameter.
Ramon Lastres 11 years ago
parent
commit
06e37a61ba
4 changed files with 51 additions and 9 deletions
  1. 29 1
      src/pooler.erl
  2. 5 1
      src/pooler.hrl
  3. 2 1
      src/pooler_config.erl
  4. 15 6
      src/pooler_sup.erl

+ 29 - 1
src/pooler.erl

@@ -680,7 +680,28 @@ expired_free_members(Members, Now, MaxAge) ->
                   Type  :: metric_type()) -> ok.
 send_metric(#pool{metrics_mod = pooler_no_metrics}, _Label, _Value, _Type) ->
     ok;
-send_metric(#pool{name = PoolName, metrics_mod = MetricsMod}, Label, Value, Type) ->
+send_metric(#pool{name = PoolName, metrics_mod = MetricsMod,
+                  metrics_api = exometer}, Label, {inc, Value}, counter) ->
+    MetricName = pool_metric_exometer(PoolName, Label),
+    MetricsMod:update_or_create(MetricName, Value, counter, []),
+    ok;
+send_metric(#pool{name = PoolName, metrics_mod = MetricsMod,
+                   metrics_api = exometer}, Label, {dec, Value}, counter) ->
+    MetricName = pool_metric_exometer(PoolName, Label),
+    MetricsMod:update_or_create(MetricName, - Value, counter, []),
+    ok;
+% Exometer does not support 'history' type metrics right now.
+send_metric(#pool{name = _PoolName, metrics_mod = _MetricsMod,
+                  metrics_api = exometer}, _Label, _Value, history) ->
+    ok;
+send_metric(#pool{name = PoolName, metrics_mod = MetricsMod,
+                   metrics_api = exometer}, Label, Value, Type) ->
+    MetricName = pool_metric_exometer(PoolName, Label),
+    MetricsMod:update_or_create(MetricName, Value, Type, []),
+    ok;
+%folsom API is the default one.
+send_metric(#pool{name = PoolName, metrics_mod = MetricsMod, metrics_api = folsom},
+                   Label, Value, Type) ->
     MetricName = pool_metric(PoolName, Label),
     MetricsMod:notify(MetricName, Value, Type),
     ok.
@@ -690,6 +711,13 @@ pool_metric(PoolName, Metric) ->
     iolist_to_binary([<<"pooler.">>, atom_to_binary(PoolName, utf8),
                       ".", atom_to_binary(Metric, utf8)]).
 
+%% Exometer metric names are lists, not binaries.
+-spec pool_metric_exometer(atom(), atom()) -> nonempty_list(binary()).
+pool_metric_exometer(PoolName, Metric) ->
+    [<<"pooler">>, atom_to_binary(PoolName, utf8),
+     atom_to_binary(Metric, utf8)].
+
+
 -spec time_as_secs(time_spec()) -> non_neg_integer().
 time_as_secs({Time, Unit}) ->
     time_as_micros({Time, Unit}) div 1000000.

+ 5 - 1
src/pooler.hrl

@@ -74,7 +74,11 @@
           %% 'pooler_no_metrics', then metric sending calls do
           %% nothing. A typical value to actually capture metrics is
           %% folsom_metrics.
-          metrics_mod = pooler_no_metrics :: atom()
+          metrics_mod = pooler_no_metrics :: atom(),
+
+          %% The API used to call the metrics system. It supports both Folsom
+          %% and Exometer format.
+          metrics_api = folsom :: 'folsom' | 'exometer'
          }).
 
 -define(gv(X, Y), proplists:get_value(X, Y)).

+ 2 - 1
src/pooler_config.erl

@@ -20,7 +20,8 @@ list_to_pool(P) ->
        cull_interval     = ?gv(cull_interval, P, ?DEFAULT_CULL_INTERVAL),
        max_age           = ?gv(max_age, P, ?DEFAULT_MAX_AGE),
        member_start_timeout = ?gv(member_start_timeout, P, ?DEFAULT_MEMBER_START_TIMEOUT),
-       metrics_mod       = ?gv(metrics_mod, P, pooler_no_metrics)}.
+       metrics_mod       = ?gv(metrics_mod, P, pooler_no_metrics),
+       metrics_api       = ?gv(metrics_api, P, folsom)}.
 
 %% Return `Value' for `Key' in proplist `P' or crashes with an
 %% informative message if no value is found.

+ 15 - 6
src/pooler_sup.erl

@@ -21,8 +21,10 @@ init([]) ->
                  undefined ->
                      []
              end,
-    MetricsConfig = {metrics_mod, metrics_module()},
-    Pools = [ pooler_config:list_to_pool([MetricsConfig | L]) || L <- Config ],
+    {MetricsApi, MetricsMod} = metrics_module(),
+    MetricsConfig = [{metrics_mod, MetricsMod},
+                     {metrics_api, MetricsApi}],
+    Pools = [ pooler_config:list_to_pool(MetricsConfig ++ L) || L <- Config ],
     PoolSupSpecs = [ pool_sup_spec(Pool) || Pool <- Pools ],
     ets:new(?POOLER_GROUP_TABLE, [set, public, named_table, {write_concurrency, true}]),
     {ok, {{one_for_one, 5, 60}, [starter_sup_spec() | PoolSupSpecs]}}.
@@ -36,8 +38,9 @@ new_pool(PoolConfig) ->
 %% @doc Create a child spec for new pool from proplist pool config `PoolConfig'. The
 %% public API for this functionality is {@link pooler:pool_child_spec/1}.
 pool_child_spec(PoolConfig) ->
-    MetricsConfig = {metrics_mod, metrics_module()},
-    NewPool = pooler_config:list_to_pool([MetricsConfig | PoolConfig]),
+    {MetricsApi, MetricsMod} = metrics_module(),
+    NewPool = pooler_config:list_to_pool([{metrics_mod, MetricsMod},
+                                          {metrics_api, MetricsApi}] ++ PoolConfig),
     pool_sup_spec(NewPool).
 
 %% @doc Shutdown the named pool.
@@ -67,7 +70,13 @@ pool_sup_name(Name) ->
 metrics_module() ->
     case application:get_env(pooler, metrics_module) of
         {ok, Mod} ->
-            Mod;
+            case application:get_env(pooler, metrics_api) of
+                {ok, exometer} ->
+                    {exometer, Mod};
+                % folsom is the default
+                _V ->
+                    {folsom, Mod}
+            end;
         undefined ->
-            pooler_no_metrics
+            {folsom, pooler_no_metrics}
     end.