diff --git a/apps/ejabberd/src/ejabberd_app.erl b/apps/ejabberd/src/ejabberd_app.erl index 9deb3100ed1..11b579d7041 100644 --- a/apps/ejabberd/src/ejabberd_app.erl +++ b/apps/ejabberd/src/ejabberd_app.erl @@ -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(), @@ -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). \ No newline at end of file diff --git a/apps/ejabberd/src/mongoose_metrics.erl b/apps/ejabberd/src/mongoose_metrics.erl index 5a19541233e..84db8a9ddc4 100644 --- a/apps/ejabberd/src/mongoose_metrics.erl +++ b/apps/ejabberd/src/mongoose_metrics.erl @@ -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, @@ -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])]. @@ -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); @@ -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))). \ No newline at end of file +subscribe_to_all(Reporter, Interval) -> + start_global_metrics_subscriptions(Reporter, Interval), + lists:foreach( + fun(Host) -> + start_host_metrics_subscriptions(Reporter, Host, Interval) + end, ?MYHOSTS). diff --git a/doc/README.md b/doc/README.md index db0f73e94cc..43c2c162e62 100644 --- a/doc/README.md +++ b/doc/README.md @@ -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) diff --git a/doc/advanced-configuration/Listener-modules.md b/doc/advanced-configuration/Listener-modules.md index 1a16572019a..f6566384956 100644 --- a/doc/advanced-configuration/Listener-modules.md +++ b/doc/advanced-configuration/Listener-modules.md @@ -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 diff --git a/doc/modules/mod_metrics.md b/doc/modules/mod_metrics.md deleted file mode 100644 index dbd6cebd0cc..00000000000 --- a/doc/modules/mod_metrics.md +++ /dev/null @@ -1,12 +0,0 @@ -### Module Description -Adding this module will enable gathering various XMPP-related statistics. The complete list can be fetched with HTTP GET request to metrics URL (see [`listen` section of `ejabberd.cfg`](wiki/Listener-modules)). They are also listed in `[MongooseIM root]/apps/ejabberd/src/mod_metrics.erl`, line 50. - -Please also check [metrics wiki page](REST-interface-to-folsom-metrics) for more information. - -### Options - -none - -### Example configuration - -` {mod_metrics, []} ` \ No newline at end of file diff --git a/doc/operation-and-maintenance/Logging-&-monitoring.md b/doc/operation-and-maintenance/Logging-&-monitoring.md index cb50a2f7afa..dbce87e664a 100644 --- a/doc/operation-and-maintenance/Logging-&-monitoring.md +++ b/doc/operation-and-maintenance/Logging-&-monitoring.md @@ -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 @@ -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 \ No newline at end of file +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, ""} + ]} + ]} + ]} + ]} +... +``` diff --git a/mkdocs.yml b/mkdocs.yml index dc2cada8d9b..f9b4361d1cb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -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' diff --git a/rel/files/app.config b/rel/files/app.config index 33fec097cdc..402a576c4f8 100644 --- a/rel/files/app.config +++ b/rel/files/app.config @@ -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