Skip to content

Commit

Permalink
Merge pull request #481 from esl/start-exometer-via-conf
Browse files Browse the repository at this point in the history
Allow to start exometer graphite reporter using via app.config file
  • Loading branch information
erszcz committed Aug 7, 2015
2 parents 3e095fa + c58779a commit 7d0d73b
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 83 deletions.
9 changes: 1 addition & 8 deletions apps/ejabberd/src/ejabberd_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ start(normal, _Args) ->
maybe_start_alarms(),
connect_nodes(),
{ok, _} = Sup = ejabberd_sup:start_link(),
init_metrics(),
mongoose_metrics:init(),
ejabberd_system_monitor:add_handler(),
ejabberd_rdbms:start(),
ejabberd_auth:start(),
Expand Down Expand Up @@ -240,10 +240,3 @@ load_drivers([Driver | Rest]) ->
[erl_ddll:format_error(Reason)]),
exit({driver_loading_failed, Driver, Reason})
end.

init_metrics() ->
mongoose_metrics:create_global_metrics(),
lists:foreach(
fun(Host) ->
mongoose_metrics:init_predefined_host_metrics(Host)
end, ?MYHOSTS).
86 changes: 33 additions & 53 deletions apps/ejabberd/src/mongoose_metrics.erl
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
-include("ejabberd.hrl").

%% API
-export([update/2,
start_graphite_reporter/1,
start_graphite_reporter/2,
-export([init/0,
update/2,
start_host_metrics_subscriptions/3,
start_vm_metrics_subscriptions/2,
start_global_metrics_subscriptions/2,
Expand All @@ -41,39 +40,40 @@
remove_host_metrics/1,
remove_all_metrics/0]).

-spec init() -> ok.
init() ->
create_global_metrics(),
lists:foreach(
fun(Host) ->
mongoose_metrics:init_predefined_host_metrics(Host)
end, ?MYHOSTS),
Reporters = exometer_report:list_reporters(),
lists:foreach(
fun({Name, _ReporterPid}) ->
Interval = application:get_env(exometer, mongooseim_report_interval, 60000),
subscribe_to_all(Name, Interval)
end, Reporters).

-spec update({term(), term()}, term()) -> no_return().
update(Name, Change) when is_tuple(Name)->
update(tuple_to_list(Name), Change);
update(Name, Change) ->
exometer:update(Name, Change).

start_graphite_reporter(GraphiteHost) ->
start_graphite_reporter(GraphiteHost, []).
start_graphite_reporter(GraphiteHost, Opts) ->
GraphiteOpts = [{prefix, "exometer." ++ atom_to_list(node())},
{host, GraphiteHost}]
++ merge_opts(Opts),
case exometer_report:add_reporter(exometer_report_graphite, GraphiteOpts) of
ok ->
{ok, exometer_report_graphite};
Error ->
Error
end.

start_host_metrics_subscriptions(Reporter, Host, Interval) ->
do_start_metrics_subscriptions(check_reporter(Reporter), Interval, [Host]).
do_start_metrics_subscriptions(Reporter, Interval, [Host]).

start_vm_metrics_subscriptions(Reporter, Interval) ->
do_start_vm_metrics_subscriptions(check_reporter(Reporter), Interval).
do_start_vm_metrics_subscriptions(Reporter, Interval).

start_global_metrics_subscriptions(Reporter, Interval) ->
do_start_global_metrics_subscriptions(check_reporter(Reporter), Interval).
do_start_global_metrics_subscriptions(Reporter, Interval).

start_data_metrics_subscriptions(Reporter, Interval) ->
do_start_metrics_subscriptions(check_reporter(Reporter), Interval, [data]).
do_start_metrics_subscriptions(Reporter, Interval, [data]).

start_backend_metrics_subscriptions(Reporter, Interval) ->
do_start_metrics_subscriptions(check_reporter(Reporter), Interval, [backends]).
do_start_metrics_subscriptions(Reporter, Interval, [backends]).

get_host_metric_names(Host) ->
[MetricName || {[_Host, MetricName | _], _, _} <- exometer:find_entries([Host])].
Expand Down Expand Up @@ -401,34 +401,17 @@ get_vm_stats() ->
get_counters(Host, Counters) ->
[{Host, Counter} || Counter <- Counters].

check_reporter(Reporter) ->
Reporters = exometer_report:list_reporters(),
case lists:keyfind(Reporter, 1, Reporters) of
{Reporter, _} ->
{ok, Reporter};
_ ->
{error, {no_such_reporter}}
end.


do_start_vm_metrics_subscriptions({ok, Reporter}, Interval) ->
do_start_vm_metrics_subscriptions(Reporter, Interval) ->
[exometer_report:subscribe(Reporter, Metric, DataPoints, Interval)
|| {Metric, _, DataPoints} <- get_vm_stats()];
do_start_vm_metrics_subscriptions(Error, _) ->
Error.
|| {Metric, _, DataPoints} <- get_vm_stats()].

do_start_global_metrics_subscriptions({ok, Reporter}, Interval) ->
do_start_global_metrics_subscriptions(Reporter, Interval) ->
[exometer_report:subscribe(Reporter, Metric, default, Interval)
|| {Metric, _} <- ?GLOBAL_COUNTERS];
do_start_global_metrics_subscriptions(Error, _) ->
Error.
|| {Metric, _} <- ?GLOBAL_COUNTERS].

do_start_metrics_subscriptions({ok, Reporter}, Interval, MetricPrefix) ->
do_start_metrics_subscriptions(Reporter, Interval, MetricPrefix) ->
[subscribe_metric(Reporter, Metric, Interval)
|| Metric <- exometer:find_entries(MetricPrefix)];
do_start_metrics_subscriptions(Error, _, _) ->
Error.

|| Metric <- exometer:find_entries(MetricPrefix)].

subscribe_metric(Reporter, {Name, counter, _}, Interval) ->
exometer_report:subscribe(Reporter, Name, [value], Interval);
Expand All @@ -437,12 +420,9 @@ subscribe_metric(Reporter, {Name, histogram, _}, Interval) ->
subscribe_metric(Reporter, {Name, _, _}, Interval) ->
exometer_report:subscribe(Reporter, Name, default, Interval).

merge_opts(Opts) ->
Defaults = [{connect_timeout, 5000},
{port, 2003},
{api_key, ""}],

MergeFun = fun(_, _, V2) -> V2 end,
orddict:to_list(orddict:merge(MergeFun,
orddict:from_list(Defaults),
orddict:from_list(Opts))).
subscribe_to_all(Reporter, Interval) ->
start_global_metrics_subscriptions(Reporter, Interval),
lists:foreach(
fun(Host) ->
start_host_metrics_subscriptions(Reporter, Host, Interval)
end, ?MYHOSTS).
2 changes: 1 addition & 1 deletion doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
* [Reloading configuration on a running system](operation-and-maintenance/Reloading-configuration-on-a-running-system.md)
* For developers
* [Hooks and handlers](developers-guide/Hooks-and-handlers.md)
* [Folsom Metrics](developers-guide/REST-interface-to-metrics.md)
* [REST Interface to Metrics](developers-guide/REST-interface-to-metrics.md)
* [mod_amp developer's guide](developers-guide/mod_amp_developers_guide.md)

2 changes: 1 addition & 1 deletion doc/advanced-configuration/Listener-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Currently it is not possible to use different ports e.g. for BOSH and Websockets
* `modules` (list of tuples: `{Host, Path, Modules}`) - List of enabled HTTP-based modules. `"_"` equals any host.
* `mod_bosh` - BOSH connections handler. Default declaration: `{"_", "/http-bind", mod_bosh}`
* `mod_websockets` - Websocket connections, both [old](http://xmpp.org/extensions/xep-0206.html) and [new](http://datatracker.ietf.org/doc/draft-ietf-xmpp-websocket/?include_text=1) type. Default declaration: `{"_", "/ws-xmpp", mod_websockets}`
* `mod_metrics` - REST API for accessing internal MongooseIM metrics. Please refer to [REST interface to metrics](../developers-guide/REST-interface-to-metrics.md) for more information. Default declaration: `{"localhost", "/metrics", mod_metrics}`.
* `mongoose_api` - REST API for accessing internal MongooseIM metrics. Please refer to [REST interface to metrics](../developers-guide/REST-interface-to-metrics.md) for more information. Default declaration: `{"localhost", "/api", mongoose_api, [{handlers, [mongoose_api_metrics]}]}`.

## ejabberd_s2s_in

Expand Down
12 changes: 0 additions & 12 deletions doc/modules/mod_metrics.md

This file was deleted.

56 changes: 49 additions & 7 deletions doc/operation-and-maintenance/Logging-&-monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ Logs
---

It is a good idea to store logs in one centralized place when working in a clustered environment.
MongooseIM uses Lager - the logging framework. Its backend can be easy replaced.
MongooseIM uses Lager - the logging framework. Its backend can be easily replaced.
Some of the recommended backends are:

- https://github.com/basho/lager_syslog to use syslog and
- https://github.com/basho/lager_syslog to use syslog and
- https://github.com/mhald/lager_logstash_backend for logstash (http://logstash.net/).

To change the backend you have to edit `rel/files/app.config`. Before that you need
Expand Down Expand Up @@ -33,17 +33,59 @@ To monitor MongooseIM during load testing we recommend the following open source
- Graphite (http://graphite.wikidot.com/) is used for data presentation
- collectd (http://collectd.org/) is a daemon running on monitored nodes capturing data related to CPU and Memory usage, IO etc.

### mod_metrics
### mod_api_metrics

It provides REST interface for Mongoose's metrics, so it can be easily integrated
with other services.

You can read more about it here:

https://github.com/esl/MongooseIM/wiki/REST-interface-to-folsom-metrics
You can read more about it here: [REST interface to metrics](/developers-guide/REST-interface-to-metrics)

### Wombat OAM

WombatOAM is an operations and maintenance framework for Erlang based systems. Its Web Dashboard displays this data in an aggregated manner and provides interfaces to feed the data to other OAM tools such as Graphite, Nagios or Zabbix.

For more information see:
https://www.erlang-solutions.com/products/wombat
https://www.erlang-solutions.com/products/wombat

### Built-in Exometer reporters

MongooseIM uses the Exometer libary for collecting the metrics. Exometer has many
build-in reporters that can send metrics to external services like:

* graphite
* amqp
* statsd
* snmp
* opentsdb

It is possible to enable them in Moongoose via the `app.config` file. The file sits next
to the `ejabberd.cfg` file and both files are located in the `rel/files` and `_REL_DIR_/etc` directories.
For more details, please visit the Exometer's project page: [ExometerProject](https://github.com/Feuerlabs/exometer).

**Note that we are using the 1.1 version.**

Below you can find sample configuration, it setups graphite reporter which connects
to graphite running on localhost.

You can see an additional option not listed in the Exometer docs - `mongooseim_report_interval`.
That option sets metrics resolution - in other words: how often Exometer gathers and sends metrics
through reporters. By default that is 60 seconds.

```erl
...
{exometer, [
{mongooseim_report_interval, 60000}, %% 60 seconds
{report, [
{reporters, [
{exometer_report_graphite, [
{prefix, "mongooseim"},
{connect_timeout, 5000},
{host, "127.0.0.1"},
{port, 2003},
{api_key, ""}
]}
]}
]}
]}
...
```
1 change: 0 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ pages:
- 'mod_disco': 'modules/mod_disco.md'
- 'mod_last': 'modules/mod_last.md'
- 'mod_mam': 'modules/mod_mam.md'
- 'mod_metrics': 'modules/mod_metrics.md'
- 'mod_muc': 'modules/mod_muc.md'
- 'mod_muc_log': 'modules/mod_muc_log.md'
- 'mod_offline': 'modules/mod_offline.md'
Expand Down
14 changes: 14 additions & 0 deletions rel/files/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@
{lager_file_backend, [{file, "log/ejabberd.log"}, {level, info}, {size, 2097152}, {date, "$D0"}, {count, 5}]}
]}
]}
%{exometer, [
% {mongooseim_report_interval, 60000}, %% 60 seconds
% {report, [
% {reporters, [
% {exometer_report_graphite, [
% {prefix, "mongooseim"},
% {connect_timeout, 5000},
% {host, "127.0.0.1"},
% {port, 2003},
% {api_key, ""}
% ]}
% ]}
% ]}
% ]}
].

%% vim: filetype=erlang

0 comments on commit 7d0d73b

Please sign in to comment.