diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..532361d --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,22 @@ +name: Exometer CI + +on: [pull_request, push] + +jobs: + linux: + name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + strategy: + matrix: + otp_version: [24, 25, 26] + os: [ubuntu-latest] + + container: + image: erlang:${{ matrix.otp_version }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: CI tests + run: make ci diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 90e9ef0..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -sudo: false -language: erlang -script: - - wget -c https://github.com/erlang/rebar3/releases/download/3.12.0/rebar3 - - chmod +x rebar3 - - REBAR3=./rebar3 make ci -otp_release: - - 24.0.5 - - 23.2.7 - - 22.1 - - 21.3 - - 20.3 -after_failure: "echo 'logs/raw.log\n'; cat logs/raw.log; for f in `find logs/ct_run*/log*/ -type f`; do echo \"\n$f\n\" ; cat $f; done" diff --git a/README.md b/README.md index 4d45bda..c0d7d4e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved. -__Version:__ Oct 30 2018 13:49:09 +__Version:__ Feb 16 2024 16:48:36 __Authors:__ Ulf Wiger ([`ulf.wiger@feuerlabs.com`](mailto:ulf.wiger@feuerlabs.com)), Magnus Feuer ([`magnus.feuer@feuerlabs.com`](mailto:magnus.feuer@feuerlabs.com)). @@ -48,8 +48,7 @@ optional packages, both users and developers. 4. [exometer_histogram (probe)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_histogram_(probe)) 5. [exometer_uniform (probe)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_uniform_(probe)) 6. [exometer_spiral (probe)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_spiral_(probe)) - 7. [exometer_folsom [entry]](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_folsom_[entry]) - 8. [exometer_function [entry]](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_function_[entry]) + 7. [exometer_function [entry]](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_function_[entry]) 3. [Built in Reporters](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Built_in_Reporters) 1. [exometer_report_tty](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_report_tty) 4. [Instrumenting Erlang code](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Instrumenting_Erlang_code) @@ -137,10 +136,6 @@ as a uniform distribution or a regular histogram. The various outputs from these entries are reported as data points under the given metric. -An entry can also interface external analytics packages. -`exometer_folsom`, for example, integrates with the -`folsom_metrics` package found at [`https://github.com/boundary/folsom`](https://github.com/boundary/folsom). - #### Probe #### @@ -292,17 +287,6 @@ The grand total of all values received during the lifetime of the probe is also available. -#### exometer_folsom [entry] #### - -The folsom entry integrates with the folsom metrics package provided -by the boundary repo at github. Updated values sent to the folsom entry -can be forwarded to folsom's counter, histogram, duration, meter, -and spiral. - -Folsom integration is provided as a backup. New code using Exometer Core -should use the native probes that duplicate folsom. - - #### exometer_function [entry] #### The function entry allows for a simple caller-supplied function to be @@ -350,10 +334,6 @@ Note that dependent applications need to be started first. On newer OTP versions For testing, you can also use [`exometer:start/0`](https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer.md#start-0). -If you make use of e.g. folsom metrics, you also need to start `folsom`. -Exometer Core will not do that automatically, nor does it contain an -application dependency for it. - See [Configuring Exometer Core](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_Exometer_Core) for details on configuration data format. @@ -521,10 +501,7 @@ Below is an example, from `exometer_core/priv/app.config`: {['_'], function , [{module, exometer_function}]}, {['_'], counter , [{module, exometer}]}, {['_'], histogram, [{module, exometer_histogram}]}, - {['_'], spiral , [{module, exometer_spiral}]}, - {['_'], duration , [{module, exometer_folsom}]}, - {['_'], meter , [{module, exometer_folsom}]}, - {['_'], gauge , [{module, exometer_folsom}]} + {['_'], spiral , [{module, exometer_spiral}]} ]} ]} ``` @@ -539,9 +516,6 @@ exometer.template.function.module = exometer_function exometer.template.counter.module = exometer exometer.template.histogram.module = exometer_histogram exometer.template.spiral.module = exometer_spiral -exometer.template.duration.module = exometer_folsom -exometer.template.meter.module = exometer_folsom -exometer.template.gauge.module = exometer_folsom ``` @@ -728,7 +702,6 @@ processing is complete. - @@ -736,11 +709,8 @@ processing is complete. - - - diff --git a/doc/README.md b/doc/README.md index cc5add8..067eb10 100644 --- a/doc/README.md +++ b/doc/README.md @@ -4,7 +4,7 @@ Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved. -__Version:__ Oct 30 2018 13:49:09 +__Version:__ Feb 16 2024 16:48:36 __Authors:__ Ulf Wiger ([`ulf.wiger@feuerlabs.com`](mailto:ulf.wiger@feuerlabs.com)), Magnus Feuer ([`magnus.feuer@feuerlabs.com`](mailto:magnus.feuer@feuerlabs.com)). @@ -48,8 +48,7 @@ optional packages, both users and developers. 4. [exometer_histogram (probe)](#exometer_histogram_(probe)) 5. [exometer_uniform (probe)](#exometer_uniform_(probe)) 6. [exometer_spiral (probe)](#exometer_spiral_(probe)) - 7. [exometer_folsom [entry]](#exometer_folsom_[entry]) - 8. [exometer_function [entry]](#exometer_function_[entry]) + 7. [exometer_function [entry]](#exometer_function_[entry]) 3. [Built in Reporters](#Built_in_Reporters) 1. [exometer_report_tty](#exometer_report_tty) 4. [Instrumenting Erlang code](#Instrumenting_Erlang_code) @@ -137,10 +136,6 @@ as a uniform distribution or a regular histogram. The various outputs from these entries are reported as data points under the given metric. -An entry can also interface external analytics packages. -`exometer_folsom`, for example, integrates with the -`folsom_metrics` package found at [`https://github.com/boundary/folsom`](https://github.com/boundary/folsom). - #### Probe #### @@ -291,20 +286,6 @@ values reported during the last minute. The grand total of all values received during the lifetime of the probe is also available. -The available data points under a metric using the spiral entry -are `count` (grand total) and `one` (sum for the last time span). - - -#### exometer_folsom [entry] #### - -The folsom entry integrates with the folsom metrics package provided -by the boundary repo at github. Updated values sent to the folsom entry -can be forwarded to folsom's counter, histogram, duration, meter, -and spiral. - -Folsom integration is provided as a backup. New code using Exometer Core -should use the native probes that duplicate folsom. - #### exometer_function [entry] #### @@ -353,10 +334,6 @@ Note that dependent applications need to be started first. On newer OTP versions For testing, you can also use [`exometer:start/0`](exometer.md#start-0). -If you make use of e.g. folsom metrics, you also need to start `folsom`. -Exometer Core will not do that automatically, nor does it contain an -application dependency for it. - See [Configuring Exometer Core](#Configuring_Exometer_Core) for details on configuration data format. @@ -524,10 +501,7 @@ Below is an example, from `exometer_core/priv/app.config`: {['_'], function , [{module, exometer_function}]}, {['_'], counter , [{module, exometer}]}, {['_'], histogram, [{module, exometer_histogram}]}, - {['_'], spiral , [{module, exometer_spiral}]}, - {['_'], duration , [{module, exometer_folsom}]}, - {['_'], meter , [{module, exometer_folsom}]}, - {['_'], gauge , [{module, exometer_folsom}]} + {['_'], spiral , [{module, exometer_spiral}]} ]} ]} ``` @@ -542,9 +516,6 @@ exometer.template.function.module = exometer_function exometer.template.counter.module = exometer exometer.template.histogram.module = exometer_histogram exometer.template.spiral.module = exometer_spiral -exometer.template.duration.module = exometer_folsom -exometer.template.meter.module = exometer_folsom -exometer.template.gauge.module = exometer_folsom ``` @@ -731,7 +702,6 @@ processing is complete.
exo_montest
exometer
exometer_admin
exometer_alias
exometer_cpu
exometer_duration
exometer_entry
exometer_folsom
exometer_folsom_monitor
exometer_function
exometer_histogram
exometer_igor
exometer_info
exometer_probe
exometer_proc
- @@ -739,11 +709,8 @@ processing is complete. - - - diff --git a/doc/edoc-info b/doc/edoc-info index d8a43fc..2b76fab 100644 --- a/doc/edoc-info +++ b/doc/edoc-info @@ -1,9 +1,8 @@ %% encoding: UTF-8 {application,exometer_core}. -{modules,[exo_montest,exometer,exometer_admin,exometer_alias,exometer_cache, - exometer_cpu,exometer_duration,exometer_entry,exometer_folsom, - exometer_folsom_monitor,exometer_function,exometer_histogram, - exometer_igor,exometer_info,exometer_probe,exometer_proc, +{modules,[exometer,exometer_admin,exometer_alias,exometer_cache,exometer_cpu, + exometer_duration,exometer_entry,exometer_function, + exometer_histogram,exometer_info,exometer_probe,exometer_proc, exometer_report,exometer_report_logger,exometer_report_tty, exometer_shallowtree,exometer_slide,exometer_slot_slide, exometer_spiral,exometer_uniform,exometer_util]}. diff --git a/doc/exo_montest.md b/doc/exo_montest.md deleted file mode 100644 index 3e61fb5..0000000 --- a/doc/exo_montest.md +++ /dev/null @@ -1,86 +0,0 @@ - - -# Module exo_montest # -* [Description](#description) -* [Function Index](#index) -* [Function Details](#functions) - -Demo module for `exometer_folsom_monitor` behaviours. - -__Behaviours:__ [`exometer_entry`](exometer_entry.md), [`exometer_folsom_monitor`](exometer_folsom_monitor.md). - - - -## Description ## -This module simply - -## Function Index ## - - -
exo_montest
exometer
exometer_admin
exometer_alias
exometer_cpu
exometer_duration
exometer_entry
exometer_folsom
exometer_folsom_monitor
exometer_function
exometer_histogram
exometer_igor
exometer_info
exometer_probe
exometer_proc
behaviour/0
copy_folsom/3
delete/3
get_datapoints/3
get_value/4
new/3
reset/3
sample/3
setopts/3
update/4
- - - - -## Function Details ## - - - -### behaviour/0 ### - -`behaviour() -> any()` - - - -### copy_folsom/3 ### - -`copy_folsom(Name, Type, Opts) -> any()` - - - -### delete/3 ### - -`delete(X1, X2, X3) -> any()` - - - -### get_datapoints/3 ### - -`get_datapoints(Name, Type, X3) -> any()` - - - -### get_value/4 ### - -`get_value(X1, Type, X3, DPs) -> any()` - - - -### new/3 ### - -`new(N, X2, Opts) -> any()` - - - -### reset/3 ### - -`reset(X1, X2, X3) -> any()` - - - -### sample/3 ### - -`sample(X1, X2, X3) -> any()` - - - -### setopts/3 ### - -`setopts(X1, X2, X3) -> any()` - - - -### update/4 ### - -`update(X1, Value, Type, X4) -> any()` - diff --git a/doc/exometer.md b/doc/exometer.md index 781469d..9293c26 100644 --- a/doc/exometer.md +++ b/doc/exometer.md @@ -28,9 +28,7 @@ Example: Putting the following in a sys.config file, {['_'], fast_counter, [{module, exometer}]}, {['_'], gauge , [{module, exometer}]}, {['_'], histogram , [{module, exometer_histogram}]}, - {['_'], spiral , [{module, exometer_spiral}]}, - {['_'], duration , [{module, exometer_folsom}]}, - {['_'], meter , [{module, exometer_folsom}]}, + {['_'], spiral , [{module, exometer_spiral}]} ]} ]} ``` @@ -151,7 +149,7 @@ value() = any() ## Function Index ## -
aggregate/2Aggregate datapoints of matching entries.
create_entry/1
delete/1Delete the metric.
ensure/3Ensure that metric exists and is of given type.
find_entries/1Find metrics based on a name prefix pattern.
get_value/1Fetch the current value of the metric.
get_value/2
get_values/1
global_status/1
info/1Returns a list of info items for Metric, see info/2.
info/2Retrieves information about a metric.
new/2Equivalent to new(Name, Type, []).
new/3Create a new metrics entry.
propose/3Propose a new exometer entry (no entry actually created).
re_register/3Create a new metrics entry, overwrite any old entry.
register_application/0Equivalent to register_application(current_application()).
register_application/1Registers statically defined entries with exometer.
repair/1Delete and re-create an entry.
reset/1Reset the metric.
sample/1Tells the metric (mainly probes) to take a sample.
select/1Perform an ets:select() on the set of metrics.
select/2Perform an ets:select() with a Limit on the set of metrics.
select_cont/1Equivalent to ets:select(Cont).
select_count/1Corresponds to ets:select_count/1.
setopts/2Change options for the metric.
start/0Start exometer and dependent apps (for testing).
stop/0Stop exometer and dependent apps (for testing).
update/2Update the given metric with Value.
update_or_create/2Update existing metric, or create+update according to template.
update_or_create/4
+
aggregate/2Aggregate datapoints of matching entries.
create_entry/1
delete/1Delete the metric.
ensure/3Ensure that metric exists and is of given type.
find_entries/1Find metrics based on a name prefix pattern.
get_value/1Fetch the current value of the metric.
get_value/2
get_values/1
global_status/1
info/1Returns a list of info items for Metric, see info/2.
info/2Retrieves information about a metric.
new/2Equivalent to new(Name, Type, []).
new/3Create a new metrics entry.
propose/3Propose a new exometer entry (no entry actually created).
re_register/3Create a new metrics entry, overwrite any old entry.
register_application/0Equivalent to register_application(current_application()).
register_application/1Registers statically defined entries with exometer.
repair/1Delete and re-create an entry.
reset/1Reset the metric.
sample/1Tells the metric (mainly probes) to take a sample.
select/1Perform an ets:select() on the set of metrics.
select/2Perform an ets:select() with a Limit on the set of metrics.
select_cont/1Equivalent to ets:select(Cont).
select_count/1Corresponds to ets:select_count/1.
setopts/2Change options for the metric.
start/0Start exometer and dependent apps (for testing).
stop/0Stop exometer and dependent apps (for testing).
update/2Update the given metric with Value.
update_or_create/2Update existing metric, or create+update according to template.
update_or_create/4
@@ -163,7 +161,7 @@ value() = any() ### aggregate/2 ###

-aggregate(Pattern::ets:match_spec(), DataPoints::[datapoint()]) -> list()
+aggregate(Pattern::ets:match_spec(), DataPoints::[datapoint()]) -> list()
 

@@ -294,7 +292,7 @@ get_value(Name::name(), DataPoint::name()) -> [{info(), any()}] +info(Name::name()) -> [{info(), any()}] | undefined
@@ -390,7 +388,7 @@ the counter value). ### propose/3 ###

-propose(Name::name(), Type::type(), Opts::options()) -> exometer_info:pp() | error()
+propose(Name::name(), Type::type(), Opts::options()) -> exometer_info:pp() | error()
 

@@ -500,7 +498,7 @@ operation likely has no effect, and will return `ok`. ### select/1 ###

-select(Pattern::ets:match_spec()) -> list()
+select(Pattern::ets:match_spec()) -> list()
 

@@ -515,7 +513,7 @@ metrics is `{Name, Type, Status}`. ### select/2 ###

-select(Pattern::ets:match_spec(), Limit::pos_integer() | infinity) -> {list(), _Cont}
+select(Pattern::ets:match_spec(), Limit::pos_integer() | infinity) -> {list(), _Cont}
 

@@ -541,7 +539,7 @@ Equivalent to [`ets:select(Cont)`](ets.md#select-1). ### select_count/1 ###

-select_count(Pattern::ets:match_spec()) -> non_neg_integer()
+select_count(Pattern::ets:match_spec()) -> non_neg_integer()
 

diff --git a/doc/exometer_admin.md b/doc/exometer_admin.md index 4852f5d..c9438c9 100644 --- a/doc/exometer_admin.md +++ b/doc/exometer_admin.md @@ -54,7 +54,7 @@ __Behaviours:__ [`gen_server`](gen_server.md). ### find_auto_template/1 ###

-find_auto_template(Name::exometer:name()) -> #exometer_entry{} | false
+find_auto_template(Name::exometer:name()) -> #exometer_entry{} | false
 

diff --git a/doc/exometer_alias.md b/doc/exometer_alias.md index 3d41f9d..a4a9930 100644 --- a/doc/exometer_alias.md +++ b/doc/exometer_alias.md @@ -53,7 +53,7 @@ alias() = atom() | binary()

-dp() = exometer:datapoint()
+dp() = exometer:datapoint()
 
@@ -69,11 +69,21 @@ fold_fun() = fun((alias(), name() +### mp() ### + + +

+mp() = {re_pattern, term(), term(), term(), term()}
+
+ + + + ### name() ###

-name() = exometer:name()
+name() = exometer:name()
 
@@ -93,7 +103,7 @@ reason() = any()

-regexp() = iodata() | re:mp()
+regexp() = iodata() | mp()
 
diff --git a/doc/exometer_cpu.md b/doc/exometer_cpu.md index c2502db..dc484a8 100644 --- a/doc/exometer_cpu.md +++ b/doc/exometer_cpu.md @@ -23,7 +23,7 @@ __Behaviours:__ [`exometer_probe`](exometer_probe.md). ### behaviour/0 ###

-behaviour() -> exometer:behaviour()
+behaviour() -> exometer:behaviour()
 

diff --git a/doc/exometer_entry.md b/doc/exometer_entry.md index 3142403..caefb7a 100644 --- a/doc/exometer_entry.md +++ b/doc/exometer_entry.md @@ -303,7 +303,7 @@ options.

-datapoint() = exometer:datapoint()
+datapoint() = exometer:datapoint()
 
diff --git a/doc/exometer_folsom.md b/doc/exometer_folsom.md deleted file mode 100644 index b83e8e9..0000000 --- a/doc/exometer_folsom.md +++ /dev/null @@ -1,77 +0,0 @@ - - -# Module exometer_folsom # -* [Function Index](#index) -* [Function Details](#functions) - -__Behaviours:__ [`exometer_entry`](exometer_entry.md). - - - -## Function Index ## - - -
behaviour/0
delete/3
get_datapoints/3
get_value/4
new/3
reset/3
sample/3
setopts/3
update/4
- - - - -## Function Details ## - - - -### behaviour/0 ### - -

-behaviour() -> exometer:behaviour()
-
-
- - - -### delete/3 ### - -`delete(Name, Type, Ref) -> any()` - - - -### get_datapoints/3 ### - -`get_datapoints(Name, Type, Ref) -> any()` - - - -### get_value/4 ### - -`get_value(Name, Type, Ref, DataPoints0) -> any()` - - - -### new/3 ### - -`new(Name, X2, Opts) -> any()` - - - -### reset/3 ### - -`reset(Name, X2, Ref) -> any()` - - - -### sample/3 ### - -`sample(Name, Type, Ref) -> any()` - - - -### setopts/3 ### - -`setopts(Entry, Options, Status) -> any()` - - - -### update/4 ### - -`update(Name, Value, Type, Ref) -> any()` - diff --git a/doc/exometer_folsom_monitor.md b/doc/exometer_folsom_monitor.md deleted file mode 100644 index bc0b5a8..0000000 --- a/doc/exometer_folsom_monitor.md +++ /dev/null @@ -1,67 +0,0 @@ - - -# Module exometer_folsom_monitor # -* [Description](#description) -* [Function Index](#index) -* [Function Details](#functions) - -Hook API for following folsom-based legacy code with exometer. - -__Behaviours:__ [`gen_server`](gen_server.md). - -__This module defines the `exometer_folsom_monitor` behaviour.__
Required callback functions: `copy_folsom/3`. - - - -## Description ## - -This module installs hooks into folsom, allowing subscribers to trap -the creation of metrics using the folsom API, and instruct exometer -to create matching metrics entries. - -Subscriptions identify a module that should be on the call stack when -a module is created (when testing from the shell, use the module `shell`), -and a callback module which is used to retrieve the specs for exometer -metrics to create. - -## Function Index ## - - -
monitor/2Monitor a legacy module.
start_link/0Start the server (called automatically by exometer).
- - - - -## Function Details ## - - - -### monitor/2 ### - -

-monitor(FromMod::atom(), Callback::atom()) -> ok
-
-
- -Monitor a legacy module. - -`FromMod` is the name of a module that should appear on the call stack -when a call to `folsom_metrics:new_` is made (or `'_'`, -which will match any call stack). `Callback` is a callback module, -exporting the function `copy_folsom(Name,Type,Opts)`, which returns a -`{Name, Type, Options}` tuple, a list of such tuples, or the atom `false`. - -The callback module is called from the `exometer_folsom_monitor` -process, so the call stack will not contain the legacy modules. -However, if the corresponding exometer metrics end up calling other -folsom-based metrics (e.g. using the `exometer_folsom` module), there -will be a risk of generating a loop. - - - -### start_link/0 ### - -`start_link() -> any()` - -Start the server (called automatically by exometer). - diff --git a/doc/exometer_function.md b/doc/exometer_function.md index e4e5926..842be2c 100644 --- a/doc/exometer_function.md +++ b/doc/exometer_function.md @@ -138,7 +138,7 @@ expr_descr() = expr_int() | erl_parse:abstract_expr()]} +expr_erl() = {erl, [erl_parse:abstract_expr()]} @@ -339,7 +339,7 @@ simple_fun() = {function, mod_name(), exometer:behaviour() +behaviour() -> exometer:behaviour()
@@ -416,7 +416,7 @@ relationship between sublists is 'or'. This is the same as in Erlang. ### new/3 ###

-new(Name::exometer:name(), X2::function, Opts::exometer:options()) -> {ok, fun_rep()}
+new(Name::exometer:name(), X2::function, Opts::exometer:options()) -> {ok, fun_rep()}
 

diff --git a/doc/exometer_histogram.md b/doc/exometer_histogram.md index 9558e2a..e8ddca0 100644 --- a/doc/exometer_histogram.md +++ b/doc/exometer_histogram.md @@ -87,7 +87,7 @@ to determine the percentiles `90` and up. ### behaviour/0 ###

-behaviour() -> exometer:behaviour()
+behaviour() -> exometer:behaviour()
 

@@ -187,9 +187,6 @@ Return value: `[Result1, Result2]`, where the results are insert the values. `Time2` is the time it took to calculate all default datapoints. The data set is shuffled between the two runs. -To assess the accuracy of the reported percentiles, use e.g. -`bear:get_statistics(exometer_histogram:test_series())` as a reference. - ### test_series/0 ### @@ -201,7 +198,7 @@ test_series() -> [integer()] Create a series of values for histogram testing. -These are the properties of the current test set: +These are the properties of the current test set (note: bear no longer in use): ```erlang diff --git a/doc/exometer_info.md b/doc/exometer_info.md index 6e39e47..b892250 100644 --- a/doc/exometer_info.md +++ b/doc/exometer_info.md @@ -85,7 +85,7 @@ for each matching metric, and calls `pp(Entry)` for each entry. ### pp_lookup/1 ###

-pp_lookup(Name::exometer:name()) -> pp() | undefined
+pp_lookup(Name::exometer:name()) -> pp() | undefined
 

@@ -98,7 +98,7 @@ This function returns `undefined` if the entry cannot be found. ### pp_select/1 ###

-pp_select(Pat::ets:match_spec()) -> [pp()]
+pp_select(Pat::ets:match_spec()) -> [pp()]
 

@@ -115,7 +115,7 @@ Note that the match body of the select pattern must produce the full ### status/1 ###

-status(Exometer_entry::exometer:entry()) -> enabled | disabled
+status(Exometer_entry::exometer:entry()) -> enabled | disabled
 

diff --git a/doc/exometer_proc.md b/doc/exometer_proc.md index abf6984..cb2cb5c 100644 --- a/doc/exometer_proc.md +++ b/doc/exometer_proc.md @@ -107,7 +107,7 @@ Apply process_flag-specific options. ### spawn_process/2 ###

-spawn_process(Name::exometer:name(), F::fun(() -> no_return())) -> pid()
+spawn_process(Name::exometer:name(), F::fun(() -> no_return())) -> pid()
 

diff --git a/doc/exometer_report.md b/doc/exometer_report.md index 1d73f54..fae0779 100644 --- a/doc/exometer_report.md +++ b/doc/exometer_report.md @@ -198,7 +198,7 @@ with a list of one datapoint/value pair.

-datapoint() = exometer:datapoint()
+datapoint() = exometer:datapoint()
 
@@ -258,7 +258,7 @@ interval() = pos_integer() | atom()

-metric() = exometer:name() | {find, exometer:name()} | {select, ets:match_spec()}
+metric() = exometer:name() | {find, exometer:name()} | {select, ets:match_spec()}
 
@@ -308,8 +308,16 @@ time_ms() = pos_integer()
add_reporter/2Add a reporter.
call_reporter/2Send a custom (synchronous) call to Reporter.
cast_reporter/2Send a custom (asynchronous) cast to Reporter.
delete_interval/2Delete a named interval.
disable_me/2Used by a reporter to disable itself.
disable_reporter/1Disable Reporter.
enable_reporter/1Enable Reporter.
get_intervals/1List the named intervals for Reporter.
list_metrics/0Equivalent to list_metrics([]).
list_metrics/1List all metrics matching Path, together with subscription status.
list_reporters/0List the name and pid of each known reporter.
list_subscriptions/1List all subscriptions for Reporter.
new_entry/1Called by exometer whenever a new entry is created.
remove_reporter/1Remove reporter and all its subscriptions.
remove_reporter/2Remove Reporter (non-blocking call).
restart_intervals/1Restart all named intervals, respecting specified delays.
set_interval/3Specify a named interval.
setopts/3Called by exometer when options of a metric entry are changed.
start_link/0Starts the server ---------------------------------------------------------------------.
start_reporters/0
subscribe/4Equivalent to subscribe(Reporter, Metric, DataPoint, Interval, [], -true).
subscribe/5Equivalent to subscribe(Reporter, Metric, DataPoint, Interval, Extra, +--------------------------------------------------------------------.
start_reporters/0
subscribe/4Equivalent to subscribe(Reporter, +Metric, +DataPoint, +Interval, +[], +true).
subscribe/5Equivalent to subscribe(Reporter, +Metric, +DataPoint, +Interval, +Extra, false).
subscribe/6Add a subscription to an existing reporter.
terminate_reporter/1
trigger_interval/2Trigger a named interval.
unsubscribe/3Equivalent to unsubscribe(Reporter, Metric, DataPoint, []).
unsubscribe/4Removes a subscription.
unsubscribe_all/2Removes all subscriptions related to Metric in Reporter.
@@ -465,7 +473,7 @@ List the named intervals for `Reporter`. ### list_metrics/0 ###

-list_metrics() -> {ok, [{exometer:name(), [datapoint()], [{reporter_name(), datapoint()}], exometer:status()}]} | {error, any()}
+list_metrics() -> {ok, [{exometer:name(), [datapoint()], [{reporter_name(), datapoint()}], exometer:status()}]} | {error, any()}
 

@@ -476,7 +484,7 @@ Equivalent to [`list_metrics([])`](#list_metrics-1). ### list_metrics/1 ###

-list_metrics(Path::metric()) -> {ok, [{exometer:name(), [datapoint()], [{reporter_name(), datapoint()}], exometer:status()}]} | {error, any()}
+list_metrics(Path::metric()) -> {ok, [{exometer:name(), [datapoint()], [{reporter_name(), datapoint()}], exometer:status()}]} | {error, any()}
 

@@ -514,7 +522,7 @@ List all subscriptions for `Reporter`. ### new_entry/1 ###

-new_entry(Entry::exometer:entry()) -> ok
+new_entry(Entry::exometer:entry()) -> ok
 

@@ -597,7 +605,7 @@ all intervals to be restarted/resynched with corresponding relative delays. ### setopts/3 ###

-setopts(Metric::exometer:entry(), Options::options(), Status::exometer:status()) -> ok
+setopts(Metric::exometer:entry(), Options::options(), Status::exometer:status()) -> ok
 

@@ -633,7 +641,7 @@ subscribe(Reporter::reporter_name(), Metric::<
-Equivalent to [`subscribe(Reporter, Metric, DataPoint, Interval, [],true)`](#subscribe-6). +Equivalent to [`subscribe(Reporter,Metric,DataPoint,Interval,[],true)`](#subscribe-6). @@ -644,7 +652,7 @@ subscribe(Reporter::reporter_name(), Metric::<
-Equivalent to [`subscribe(Reporter, Metric, DataPoint, Interval, Extra,false)`](#subscribe-6). +Equivalent to [`subscribe(Reporter,Metric,DataPoint,Interval,Extra,false)`](#subscribe-6). diff --git a/doc/exometer_report_logger.md b/doc/exometer_report_logger.md index 0ed3b26..7a53b24 100644 --- a/doc/exometer_report_logger.md +++ b/doc/exometer_report_logger.md @@ -10,7 +10,7 @@ Exometer report collector and logger. __Behaviours:__ [`gen_server`](gen_server.md). -__This module defines the `exometer_report_logger` behaviour.__
Required callback functions: `logger_init_input/1`, `logger_init_output/1`, `logger_handle_data/2`. +__This module defines the `exometer_report_logger` behaviour.__
Required callback functions: `logger_handle_data/2`. diff --git a/doc/exometer_slide.md b/doc/exometer_slide.md index 38b9ead..782464c 100644 --- a/doc/exometer_slide.md +++ b/doc/exometer_slide.md @@ -77,7 +77,7 @@ sample_fun() = fun((timestamp(), exometer_util:timestamp() +timestamp() = exometer_util:timestamp() @@ -149,6 +149,11 @@ add_element(TS::timestamp(), Evt::timestamp(), Evt::value(), Slide::#slide{size = integer(), n = integer(), max_n = undefined | integer(), last = integer(), buf1 = list(), buf2 = list()}, Wrap::false) -> #slide{size = integer(), n = integer(), max_n = undefined | integer(), last = integer(), buf1 = list(), buf2 = list()} + +
+ Add an element to the buffer, optionally indicating if a swap occurred. This function works like [`add_element/3`](#add_element-3), but will also indicate diff --git a/doc/exometer_spiral.md b/doc/exometer_spiral.md index 1f3faf6..4e86642 100644 --- a/doc/exometer_spiral.md +++ b/doc/exometer_spiral.md @@ -23,7 +23,7 @@ __Behaviours:__ [`exometer_probe`](exometer_probe.md). ### behaviour/0 ###

-behaviour() -> exometer:behaviour()
+behaviour() -> exometer:behaviour()
 

diff --git a/doc/exometer_util.md b/doc/exometer_util.md index 8673757..6062157 100644 --- a/doc/exometer_util.md +++ b/doc/exometer_util.md @@ -28,7 +28,7 @@ timestamp() = non_neg_integer()
clear_event_flag/2
drop_duplicates/1 -drop_duplicates/1 will drop all duplicate elements from a list of tuples identified by their first element.
ensure_all_started/1
get_datapoints/1
get_env/2
get_opt/2
get_opt/3
get_statistics/3Calculate statistics from a sorted list of values.
get_statistics2/4
get_status/1
histogram/1
histogram/2
perc/2
pick_items/2Pick values from specified positions in a sorted list of numbers.
report_type/3
seed/0
seed/0
seed/1
seed/1
seed0/0
seed0/0
set_call_count/2
set_call_count/3
set_event_flag/2
set_status/2
table/0
tables/0
test_event_flag/2
timestamp/0Generate a millisecond-resolution timestamp.
timestamp_to_datetime/1Convert timestamp to a regular datetime.
uniform/0
uniform/0
uniform/1
uniform/1
+drop_duplicates/1 will drop all duplicate elements from a list of tuples identified by their first element.ensure_all_started/1get_datapoints/1get_env/2get_opt/2get_opt/3get_statistics/1get_statistics/3Calculate statistics from a sorted list of values.get_statistics2/4get_status/1histogram/1histogram/2perc/2pick_items/2Pick values from specified positions in a sorted list of numbers.report_type/3seed/0seed/0seed/1seed/1seed0/0seed0/0set_call_count/2set_call_count/3set_event_flag/2set_status/2table/0tables/0test_event_flag/2timestamp/0Generate a millisecond-resolution timestamp.timestamp_to_datetime/1Convert timestamp to a regular datetime.uniform/0uniform/0uniform/1uniform/1 @@ -87,6 +87,12 @@ ensure_all_started(App::atom()) -> {ok, [atom()]} | {error, term()} `get_opt(K, Opts, Default) -> any()` + + +### get_statistics/1 ### + +`get_statistics(Values) -> any()` + ### get_statistics/3 ### @@ -258,7 +264,7 @@ This timestamp format is used e.g. by the `exometer_slide` and ### timestamp_to_datetime/1 ###

-timestamp_to_datetime(TS::timestamp()) -> {calendar:datetime(), non_neg_integer()}
+timestamp_to_datetime(TS::timestamp()) -> {calendar:datetime(), non_neg_integer()}
 

diff --git a/doc/overview.edoc b/doc/overview.edoc index 4db982b..16e559d 100644 --- a/doc/overview.edoc +++ b/doc/overview.edoc @@ -44,8 +44,7 @@ optional packages, both users and developers. 4. {@section exometer_histogram (probe)} 5. {@section exometer_uniform (probe)} 6. {@section exometer_spiral (probe)} - 7. {@section exometer_folsom [entry]} - 8. {@section exometer_function [entry]} + 7. {@section exometer_function [entry]} 3. {@section Built in Reporters} 1. {@section exometer_report_tty} 4. {@section Instrumenting Erlang code} @@ -129,10 +128,6 @@ as a uniform distribution or a regular histogram. The various outputs from these entries are reported as data points under the given metric. -An entry can also interface external analytics packages. -`exometer_folsom', for example, integrates with the -`folsom_metrics' package found at [https://github.com/boundary/folsom]. - === Probe === Probes are a further specialization of exometer entries that run in @@ -272,16 +267,6 @@ values reported during the last minute. The grand total of all values received during the lifetime of the probe is also available. -=== exometer_folsom [entry] === - -The folsom entry integrates with the folsom metrics package provided -by the boundary repo at github. Updated values sent to the folsom entry -can be forwarded to folsom's counter, histogram, duration, meter, -and spiral. - -Folsom integration is provided as a backup. New code using Exometer Core -should use the native probes that duplicate folsom. - === exometer_function [entry] === The function entry allows for a simple caller-supplied function to be @@ -323,10 +308,6 @@ Note that dependent applications need to be started first. On newer OTP versions For testing, you can also use {@link exometer:start/0}. -If you make use of e.g. folsom metrics, you also need to start `folsom'. -Exometer Core will not do that automatically, nor does it contain an -application dependency for it. - See {@section Configuring Exometer Core} for details on configuration data format. @@ -468,10 +449,7 @@ Below is an example, from `exometer_core/priv/app.config': {['_'], function , [{module, exometer_function}]}, {['_'], counter , [{module, exometer}]}, {['_'], histogram, [{module, exometer_histogram}]}, - {['_'], spiral , [{module, exometer_spiral}]}, - {['_'], duration , [{module, exometer_folsom}]}, - {['_'], meter , [{module, exometer_folsom}]}, - {['_'], gauge , [{module, exometer_folsom}]} + {['_'], spiral , [{module, exometer_spiral}]} ]} ]} @@ -483,10 +461,7 @@ defaults would be as follows: exometer.template.function.module = exometer_function exometer.template.counter.module = exometer exometer.template.histogram.module = exometer_histogram -exometer.template.spiral.module = exometer_spiral -exometer.template.duration.module = exometer_folsom -exometer.template.meter.module = exometer_folsom -exometer.template.gauge.module = exometer_folsom +exometer.template.spiral.module = exometer_spiral === Configuring statically defined entries === diff --git a/priv/app.config b/priv/app.config index 8c29ffa..000671a 100644 --- a/priv/app.config +++ b/priv/app.config @@ -7,10 +7,7 @@ {['_'], function , [{module, exometer_function}]}, {['_'], counter , [{module, exometer}]}, {['_'], histogram, [{module, exometer_histogram}]}, - {['_'], spiral , [{module, exometer_spiral}]}, - {['_'], duration , [{module, exometer_folsom}]}, - {['_'], meter , [{module, exometer_folsom}]}, - {['_'], gauge , [{module, exometer_folsom}]} + {['_'], spiral , [{module, exometer_spiral}]} ]}, {report, [ diff --git a/rebar.config b/rebar.config index e2e8738..9796977 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,6 @@ {deps, [ {parse_trans, "3.4.1"}, - {folsom, "1.0.0"}, {hut, "1.3.0"}, {setup, "2.1.0"} ]}. @@ -12,7 +11,7 @@ {test, [{deps, [{meck, "0.9.2"}]}, {extra_src_dirs, [{"test", [{recursive, true}]}]} ]}, - {docs, [{deps, [{edown, "0.8.4"}]}]} + {docs, [{deps, [{edown, "0.9.1"}]}]} ]}. {erl_opts, diff --git a/rebar.lock b/rebar.lock index 98c93fc..89cc974 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,19 +1,13 @@ {"1.2.0", -[{<<"bear">>,{pkg,<<"bear">>,<<"1.0.0">>},1}, - {<<"folsom">>,{pkg,<<"folsom">>,<<"1.0.0">>},0}, - {<<"hut">>,{pkg,<<"hut">>,<<"1.3.0">>},0}, +[{<<"hut">>,{pkg,<<"hut">>,<<"1.3.0">>},0}, {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.1">>},0}, {<<"setup">>,{pkg,<<"setup">>,<<"2.1.0">>},0}]}. [ {pkg_hash,[ - {<<"bear">>, <<"430419C1126B477686CDE843E88BA0F2C7DC5CDF0881C677500074F704339A99">>}, - {<<"folsom">>, <<"50ECC998D2149939F1D5E0AA3E32788F8ED16A58E390D81B5C0BE4CC4EF25589">>}, {<<"hut">>, <<"71F2F054E657C03F959CF1ACC43F436EA87580696528CA2A55C8AFB1B06C85E7">>}, {<<"parse_trans">>, <<"6E6AA8167CB44CC8F39441D05193BE6E6F4E7C2946CB2759F015F8C56B76E5FF">>}, {<<"setup">>, <<"05F69185A5EB71474C9BC6BA892565651EC7507791F85632B7B914DBFE130510">>}]}, {pkg_hash_ext,[ - {<<"bear">>, <<"157B67901ADF84FF0DA6EAE035CA1292A0AC18AA55148154D8C582B2C68959DB">>}, - {<<"folsom">>, <<"DD6AB97278E94F9E4CFC43E188224A7B8C7EAEC0DD2E935007005177F3EEBB0E">>}, {<<"hut">>, <<"7E15D28555D8A1F2B5A3A931EC120AF0753E4853A4C66053DB354F35BF9AB563">>}, {<<"parse_trans">>, <<"620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A">>}, {<<"setup">>, <<"EFD072578F0CF85BEA96CAAFFC7ADB0992398272522660A136E10567377071C5">>}]} diff --git a/src/exo_montest.erl b/src/exo_montest.erl deleted file mode 100644 index 0641c26..0000000 --- a/src/exo_montest.erl +++ /dev/null @@ -1,82 +0,0 @@ -%% ------------------------------------------------------------------- -%% -%% Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved. -%% -%% This Source Code Form is subject to the terms of the Mozilla Public -%% License, v. 2.0. If a copy of the MPL was not distributed with this -%% file, You can obtain one at http://mozilla.org/MPL/2.0/. -%% -%% ------------------------------------------------------------------- -%% -%% @doc Demo module for `exometer_folsom_monitor' behaviours. -%% -%% This module simply -%% @end --module(exo_montest). --behaviour(exometer_folsom_monitor). --behaviour(exometer_entry). - --export([copy_folsom/3]). --export([behaviour/0, - delete/3, - get_datapoints/3, - get_value/4, - new/3, - reset/3, - sample/3, - setopts/3, - update/4]). - -behaviour() -> - entry. - -copy_folsom(Name, Type, Opts) when is_tuple(Name) -> - {tuple_to_list(Name), ad_hoc, [{folsom_name, Name}, - {module, ?MODULE}, - {type, Type} - | options(Type, Opts)]}; -copy_folsom(_, _, _) -> - false. - -new(N, _, Opts) -> - {ok, {proplists:get_value(type, Opts, unknown), - proplists:get_value(folsom_name, Opts, N)}}. - -update(_, Value, counter, {_, Name}) -> - folsom_metrics:notify_existing_metric(Name, {inc,Value}, counter); -update(_, Value, Type, {_, Name}) -> - folsom_metrics:notify_existing_metric(Name, Value, Type). - -reset(_, _, _) -> - {error, unsupported}. - -get_value(_, Type, {_, Name}, DPs) -> - exometer_folsom:get_value(Name, Type, [], DPs). - -sample(_, _, _) -> - {error, unsupported}. - -setopts(_, _, _) -> - ok. - -delete(_, _, _) -> - {error, unsupported}. - -get_datapoints(Name, Type, _) -> - exometer_folsom:get_datapoints(Name, Type, []). - -options(history, [Size]) -> - [{size, Size}]; -options(histogram, [SampleType, SampleSize, Alpha]) -> - [{sample_type, SampleType}, - {sample_size, SampleSize}, - {alpha, Alpha}]; -options(duration , [SampleType, SampleSize, Alpha]) -> - [{sample_type, SampleType}, - {sample_size, SampleSize}, - {alpha, Alpha}]; -options(meter_reader, []) -> []; -options(spiral , []) -> []; -options(meter , []) -> []; -options(gauge , []) -> []; -options(counter , []) -> []. diff --git a/src/exometer.erl b/src/exometer.erl index d6b43a6..28089cb 100644 --- a/src/exometer.erl +++ b/src/exometer.erl @@ -24,9 +24,7 @@ %% {['_'], fast_counter, [{module, exometer}]}, %% {['_'], gauge , [{module, exometer}]}, %% {['_'], histogram , [{module, exometer_histogram}]}, -%% {['_'], spiral , [{module, exometer_spiral}]}, -%% {['_'], duration , [{module, exometer_folsom}]}, -%% {['_'], meter , [{module, exometer_folsom}]}, +%% {['_'], spiral , [{module, exometer_spiral}]} %% ]} %% ]} %% diff --git a/src/exometer_admin.erl b/src/exometer_admin.erl index 64b6f31..ae0e4b8 100644 --- a/src/exometer_admin.erl +++ b/src/exometer_admin.erl @@ -558,8 +558,7 @@ module(histogram) -> exometer_histogram; module(spiral ) -> exometer_spiral; module(netlink ) -> exometer_netlink; module(cpu ) -> exometer_cpu; -module(function ) -> exometer_function; -module(meter ) -> exometer_folsom. +module(function ) -> exometer_function. search_default(Name, Type) -> case ets:lookup(?EXOMETER_SHARED, {default,Type,Name}) of diff --git a/src/exometer_alias.erl b/src/exometer_alias.erl index bb15071..2038728 100644 --- a/src/exometer_alias.erl +++ b/src/exometer_alias.erl @@ -51,10 +51,14 @@ -record(alias, {key, alias, entry, dp}). -record(st, {}). +%% copied from re.erl (not an exported type) +-type mp() :: {re_pattern, _, _, _, _}. + + -type alias() :: atom() | binary(). -type name() :: exometer:name(). -type dp() :: exometer:datapoint(). --type regexp() :: iodata() | re:mp(). +-type regexp() :: iodata() | mp(). -type acc() :: any(). -type fold_fun() :: fun((alias(), name(), dp(), acc()) -> acc()). -type reason() :: any(). diff --git a/src/exometer_core.app.src b/src/exometer_core.app.src index d314559..199d3e3 100644 --- a/src/exometer_core.app.src +++ b/src/exometer_core.app.src @@ -2,7 +2,7 @@ [{description,"Code instrumentation and metrics collection package."}, {vsn,git}, {registered,[]}, - {applications,[kernel,stdlib,hut,setup,folsom,parse_trans]}, + {applications,[kernel,stdlib,hut,setup,parse_trans]}, {included_applications,[]}, {mod,{exometer_core_app,[]}}, {start_phases,[{start_reporters,[]},{preset_defaults,[]}]}, diff --git a/src/exometer_core_sup.erl b/src/exometer_core_sup.erl index 4405c2c..0c957cf 100644 --- a/src/exometer_core_sup.erl +++ b/src/exometer_core_sup.erl @@ -39,7 +39,6 @@ init([]) -> ?CHILD(exometer_cache, worker), ?CHILD(exometer_report, worker), ?CHILD(exometer_report_logger_sup, supervisor), - ?CHILD(exometer_folsom_monitor, worker), ?CHILD(exometer_alias, worker) ], {ok, {{one_for_one, 5, 10}, Children0}}. diff --git a/src/exometer_folsom.erl b/src/exometer_folsom.erl deleted file mode 100644 index 5bffc26..0000000 --- a/src/exometer_folsom.erl +++ /dev/null @@ -1,232 +0,0 @@ -%% ------------------------------------------------------------------- -%% -%% Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved. -%% -%% This Source Code Form is subject to the terms of the Mozilla Public -%% License, v. 2.0. If a copy of the MPL was not distributed with this -%% file, You can obtain one at http://mozilla.org/MPL/2.0/. -%% -%% ------------------------------------------------------------------- - --module(exometer_folsom). --behaviour(exometer_entry). - --export([behaviour/0, - new/3, - delete/3, - get_datapoints/3, - get_value/4, - update/4, - reset/3, - sample/3, - setopts/3]). - --spec behaviour() -> exometer:behaviour(). -behaviour() -> entry. - -new(Name, counter, _Opts) -> - folsom_metrics:new_counter(Name); -new(Name, spiral, _Opts) -> - folsom_metrics:new_spiral(Name); -new(Name, histogram, Opts) -> - case lists:keysearch(arg, 1, Opts) of - {_, {histogram, SampleType, SampleArgs}} -> - {folsom_metrics:new_histogram(Name, SampleType, SampleArgs), - opt_ref(Opts)}; - false -> - {folsom_metrics:new_histogram(Name, slide_uniform, {60, 1028}), - opt_ref(Opts)} - end; -new(Name, meter, Opts) -> - {folsom_metrics:new_meter(Name), opt_ref(Opts)}; -new(Name, meter_reader, Opts) -> - {folsom_metrics:new_meter_reader(Name), opt_ref(Opts)}; -new(Name, gauge, Opts) -> - {folsom_metrics:new_gauge(Name), opt_ref(Opts)}; -new(Name, duration, Opts) -> - {folsom_metrics:new_duration(Name), opt_ref(Opts)}; -new(Name, history, Opts) -> - case lists:keyfind(size, 1, Opts) of - {_, Sz} -> {folsom_metrics:new_history(Name, Sz), opt_ref(Opts)}; - false -> {folsom_metrics:new_history(Name), opt_ref(Opts)} - end. - - -opt_ref(Opts) -> - case lists:keyfind(truncate, 1, Opts) of - false -> - [{truncate,true}]; - {_, B} when is_boolean(B) -> - [{truncate,B}] - end. - -delete(Name, _Type, _Ref) -> - folsom_metrics:delete_metric(Name). - -update(Name, Value, counter, _Ref) -> - folsom_metrics:notify_existing_metric(Name, {inc, Value}, counter); -update(Name, tick, meter_reader, _Ref) -> - folsom_metrics_meter_reader:tick(Name); -update(Name, Value, meter_reader, _Ref) -> - folsom_metrics_meter_reader:mark(Name, Value); -update(Name, Value, Type, _Ref) -> - folsom_metrics:notify_existing_metric(Name, Value, Type). - -reset(Name, counter, _Ref) -> - folsom_metrics_counter:clear(Name); -reset(Name, gauge, _Ref) -> - folsom_metrics_gauge:clear(Name); -reset(_, _, _) -> - {error, unsupported}. - -get_value(Name, history, _Ref, DataPoints0) -> - try DataPoints = datapoints(history, DataPoints0), - lists:foldr( - fun(events, Acc) -> - [{events, just_events( - folsom_metrics_history:get_events(Name))} - | Acc]; - (values, Acc) -> - [{values, folsom_metrics_history:get_events(Name)} - | Acc]; - (timed_events, Acc) -> - [{timed_events, - timed_events( - folsom_metrics_history:get_events(Name))} - | Acc]; - (Sz, Acc) when is_integer(Sz), Sz > 0 -> - [{Sz, just_events( - folsom_metrics_history:get_events(Name, Sz))} - | Acc]; - (info, Acc) -> - [{info, folsom_metrics_history:get_value(Name)} - | Acc]; - (_, Acc) -> Acc - end, [], DataPoints) - catch - error:_ -> unavailable - end; -get_value(Name, Type, Ref, DataPoints) -> - Trunc = get_trunc_opt(Ref), - Vals = get_value_(Name, Type, Ref), - try [filter_dp(D, Vals, Trunc) || D <- datapoints(Type, DataPoints)] - catch - error:_Error -> - unavailable - end. - -get_trunc_opt(undefined) -> true; -get_trunc_opt(L) -> - proplists:get_value(truncate, L, true). - -get_datapoints(_Name, Type, _Ref) -> - datapoints(Type, default). - -datapoints(Type, default) -> datapoints(Type); -datapoints(_, L) when is_list(L) -> L. - -datapoints(counter) -> - [value]; -datapoints(gauge) -> - [value]; -datapoints(histogram) -> - stats_datapoints(); -datapoints(duration) -> - [count, last |stats_datapoints()]; -datapoints(spiral) -> - [one, count]; -datapoints(meter) -> - [count,one,five,fifteen,day,mean,acceleration]; -datapoints(history) -> - [events, info]. - - -filter_dp(Mean, DPs, Trunc) when Mean==mean; Mean==arithmetic_mean -> - case lists:keyfind(mean, 1, DPs) of - false -> - case lists:keyfind(arithmetic_mean, 1, DPs) of - false -> {mean, zero(Trunc)}; - {_,V} -> {mean, opt_trunc(Trunc, V)} - end; - {_,V} -> {mean, opt_trunc(Trunc, V)} - end; -filter_dp(H, DPs, Trunc) when is_integer(H) -> - case lists:keyfind(H, 1, DPs) of - false -> - case lists:keyfind(percentile, 1, DPs) of - false -> {H, zero(Trunc)}; - {_, Ps} -> - get_dp(H, Ps, Trunc) - end; - {_,V} -> {H, opt_trunc(Trunc, V)} - end; -filter_dp(H, DPs, Trunc) -> - get_dp(H, DPs, Trunc). - -opt_trunc(true, V) when is_float(V) -> - trunc(V); -opt_trunc(round, V) when is_float(V) -> - round(V); -opt_trunc(_, V) -> - V. - -get_dp(K, DPs, Trunc) -> - case lists:keyfind(K, 1, DPs) of - false -> {K, zero(Trunc)}; - {_, V} -> {K, opt_trunc(Trunc, V)} - end. - -zero(true) -> 0; -zero(round) -> 0; -zero(false) -> 0.0. - - -stats_datapoints() -> - [n,mean,min,max,median,50,75,90,95,99,999]. - -setopts(_Entry, _Options, _Status) -> - ok. - -sample(_Name, _Type, _Ref) -> - { error, unsupported }. - -get_value_(Name, counter, _Ref) -> - [{value, folsom_metrics_counter:get_value(Name)}]; -get_value_(Name, gauge, _Ref) -> - [{value, folsom_metrics_gauge:get_value(Name)}]; -get_value_(Name, histogram, _Ref) -> - calc_stats(folsom_metrics_histogram:get_values(Name)); -get_value_(Name, duration, _Ref) -> - {Name, Cnt, _Start, Last} = folsom_metrics_duration:get_value(Name), - Stats = calc_stats(folsom_metrics_histogram:get_values(Name)), - [{count, Cnt}, {last, Last} | Stats]; -get_value_(Name, meter, _Ref) -> - folsom_metrics:get_metric_value(Name); -get_value_(Name, spiral, _Ref) -> - folsom_metrics_spiral:get_values(Name). - -calc_stats(Values) -> - L = length(Values), - exometer_util:get_statistics(L, - lists:sum(Values), - lists:sort(Values)). - -just_events([{I, Events}|T]) when is_integer(I) -> - just_events1(Events, T); -just_events([]) -> - []. - -just_events1([{event, E}|Es], T) -> - [E|just_events1(Es, T)]; -just_events1([], T) -> - just_events(T). - -timed_events([{I, Events}|T]) when is_integer(I) -> - timed_events(Events, I, T); -timed_events([]) -> - []. - -timed_events([{event, E}|Es], I, T) -> - [{I, E}|timed_events(Es, I, T)]; -timed_events([], _, T) -> - timed_events(T). diff --git a/src/exometer_folsom_monitor.erl b/src/exometer_folsom_monitor.erl deleted file mode 100644 index 148616a..0000000 --- a/src/exometer_folsom_monitor.erl +++ /dev/null @@ -1,217 +0,0 @@ -%% ------------------------------------------------------------------- -%% -%% Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved. -%% -%% This Source Code Form is subject to the terms of the Mozilla Public -%% License, v. 2.0. If a copy of the MPL was not distributed with this -%% file, You can obtain one at http://mozilla.org/MPL/2.0/. -%% -%% ------------------------------------------------------------------- -%% -%% @doc Hook API for following folsom-based legacy code with exometer -%% -%% This module installs hooks into folsom, allowing subscribers to trap -%% the creation of metrics using the folsom API, and instruct exometer -%% to create matching metrics entries. -%% -%% Subscriptions identify a module that should be on the call stack when -%% a module is created (when testing from the shell, use the module `shell'), -%% and a callback module which is used to retrieve the specs for exometer -%% metrics to create. -%% @end --module(exometer_folsom_monitor). - --behaviour(gen_server). - --export([start_link/0, - init/1, - handle_call/3, - handle_cast/2, - handle_info/2, - terminate/2, - code_change/3]). - --export([monitor/2]). --export([hook/1]). - --record(st, {mon = orddict:new()}). - --include_lib("parse_trans/include/codegen.hrl"). --include_lib("hut/include/hut.hrl"). --include("exometer.hrl"). - --type type() :: exometer:type(). --type name() :: exometer:name(). --type options() :: exometer:options(). - --callback copy_folsom(name(), type(), options()) -> - {name(), type(), options()} | - [{name(), type(), options()}] | - false. - --spec monitor(atom(), atom()) -> ok. -%% @doc Monitor a legacy module. -%% -%% `FromMod' is the name of a module that should appear on the call stack -%% when a call to `folsom_metrics:new_' is made (or '_', -%% which will match any call stack). `Callback' is a callback module, -%% exporting the function `copy_folsom(Name,Type,Opts)', which returns a -%% `{Name, Type, Options}' tuple, a list of such tuples, or the atom `false'. -%% -%% The callback module is called from the `exometer_folsom_monitor' -%% process, so the call stack will not contain the legacy modules. -%% However, if the corresponding exometer metrics end up calling other -%% folsom-based metrics (e.g. using the `exometer_folsom' module), there -%% will be a risk of generating a loop. -%% @end -monitor(FromMod, Callback) when is_atom(FromMod), is_atom(Callback) -> - gen_server:call(?MODULE, {monitor, FromMod, Callback}). - -%% @private -hook(Args) -> - Stack = try error(x) - catch - ?EXCEPTION(error, _, Stacktrace) -> - ?GET_STACK(Stacktrace) - end, - gen_server:cast(?MODULE, {hook, Args, Stack}). - -%% @doc Start the server (called automatically by exometer). -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). - -%% @private -init(_) -> - Mon = lists:foldl( - fun({Mf, Mc}, D) -> - orddict:append(Mf, Mc, D) - end, orddict:new(), find_env()), - init_monitor(Mon), - {ok, #st{mon = Mon}}. - -find_env() -> - E1 = [E || {_, E} <- setup:find_env_vars(exometer_folsom_monitor)], - E2 = exometer_util:get_env(folsom_monitor, []), - lists:flatmap( - fun({_,_} = M) -> [M]; - (L) when is_list(L) -> L - end, E1 ++ E2). - -%% @private -handle_call({monitor, Mod, CB}, _, #st{mon = Mon} = S) - when is_atom(Mod), is_atom(CB) -> - if Mon == [] -> do_init_monitor(); - true -> ok - end, - {reply, ok, S#st{mon = orddict:append(Mod, CB, Mon)}}; -handle_call(_, _, S) -> - {reply, {error, unsupported}, S}. - -%% @private -handle_cast({hook, Args, Stack}, S) -> - check_stack(S#st.mon, Stack, Args), - {noreply, S}. -%% @private -handle_info(_, S) -> {noreply, S}. -%% @private -terminate(_, _) -> ok. -%% @private -code_change(_, S, _) -> {ok, S}. - -init_monitor([]) -> - ok; -init_monitor([_|_]) -> - do_init_monitor(). - -do_init_monitor() -> - case is_transformed() of - true -> - ?log(debug, "already transformed...~n", []), - ok; - false -> - ?log(debug, "transforming folsom_metrics...~n", []), - parse_trans_mod:transform_module(folsom_metrics, fun pt/2, []) - end. - -pt(Forms, _) -> - Funcs = funcs(), - NewForms = parse_trans:plain_transform( - fun(F) -> - plain_pt(F, Funcs) - end, Forms), - mark_transformed(NewForms). - -is_transformed() -> - Attrs = folsom_metrics:module_info(attributes), - [true || {?MODULE,[]} <- Attrs] =/= []. - -mark_transformed([{attribute,L,module,_} = M|Fs]) -> - [M, {attribute,L,?MODULE,[]} | Fs]; -mark_transformed([H|T]) -> - [H | mark_transformed(T)]. - -plain_pt({function,L,F,A,Cs}, Funcs) -> - case lists:keyfind({F,A}, 1, Funcs) of - {_, Type} -> - {function,L,F,A,insert_hook(Type, Cs)}; - false -> - continue - end; -plain_pt(_, _) -> - continue. - -funcs() -> - [{{new_counter , 1}, counter}, - {{new_gauge , 1}, gauge}, - {{new_meter , 1}, meter}, - {{new_meter_reader, 1}, meter_reader}, - {{new_history , 2}, history}, - {{new_histogram , 4}, histogram}, - {{new_spiral , 1}, spiral}, - {{new_duration , 4}, duration}]. - - -insert_hook(Type, Cs) -> - lists:map( - fun({clause,L0,Args,Gs,Body}) -> - L = element(2,hd(Body)), - {clause,L0,Args,Gs, - [{call,L,{remote,L,{atom,L,?MODULE},{atom,L,hook}}, - [cons([{atom,L,Type}|Args], L)]}|Body]} - end, Cs). - -cons([H|T], L) -> {cons,L,H,cons(T,L)}; -cons([] , L) -> {nil,L}. - -check_stack(Mon, Stack, Args) -> - orddict:fold( - fun('_', CBs, Acc) -> - _ = [maybe_create(CB, Args) || CB <- CBs], - Acc; - (Mod, CBs, Acc) -> - case lists:keymember(Mod, 1, Stack) of - true -> - _ = [maybe_create(CB, Args) || CB <- CBs]; - false -> - ignore - end, - Acc - end, ok, Mon). - -maybe_create(CB, [FolsomType, Name | Args]) -> - try CB:copy_folsom(Name, FolsomType, Args) of - {ExoName, ExoType, ExoArgs} -> - exometer:new(ExoName, ExoType, ExoArgs); - L when is_list(L) -> - lists:foreach( - fun({ExoName, ExoType, ExoArgs}) -> - exometer:new(ExoName, ExoType, ExoArgs) - end, L); - false -> - ignore - catch - Cat:Msg -> - ?log(error, "~p:copy_folsom(~p,~p,~p): ~p:~p~n", - [CB, Name, FolsomType, Args, Cat, Msg]), - ignore - end. diff --git a/src/exometer_histogram.erl b/src/exometer_histogram.erl index d3991ba..5f3cfdc 100644 --- a/src/exometer_histogram.erl +++ b/src/exometer_histogram.erl @@ -420,9 +420,6 @@ test_run(Module) -> %% `{Time1, Time2, Datapoints}'. `Time1' is the time (in microsecs) it took to %% insert the values. `Time2' is the time it took to calculate all default %% datapoints. The data set is shuffled between the two runs. -%% -%% To assess the accuracy of the reported percentiles, use e.g. -%% `bear:get_statistics(exometer_histogram:test_series())' as a reference. %% @end test_run(Module, Interval) -> Series = test_series(), @@ -462,7 +459,7 @@ tc(F) -> -spec test_series() -> [integer()]. %% @doc Create a series of values for histogram testing. %% -%% These are the properties of the current test set: +%% These are the properties of the current test set (note: bear no longer in use): %%
 %% 1> rp(bear:get_statistics(exometer_histogram:test_series())).
 %% [{min,3},
diff --git a/src/exometer_util.erl b/src/exometer_util.erl
index b4dab4d..bedcd67 100644
--- a/src/exometer_util.erl
+++ b/src/exometer_util.erl
@@ -20,6 +20,7 @@
     get_env/2,
     tables/0,
     table/0,
+    get_statistics/1,
     get_statistics/3,
     get_statistics2/4,
     pick_items/2,
@@ -223,6 +224,10 @@ histogram(Values, DataPoints) ->
     [DP || {K,_} = DP <- H,
            lists:member(K, DataPoints)].
 
+get_statistics(Values) ->
+    Sorted = lists:sort(Values),
+    get_statistics(length(Sorted), lists:sum([V || {_,V} <- Sorted]), Sorted).
+
 -spec get_statistics(Length::non_neg_integer(),
                      Total::non_neg_integer(),
                      Sorted::list()) -> [{atom(), number()}].
diff --git a/test/exometer_SUITE.erl b/test/exometer_SUITE.erl
index 6b93aca..b5b0561 100644
--- a/test/exometer_SUITE.erl
+++ b/test/exometer_SUITE.erl
@@ -32,14 +32,11 @@
     test_std_histogram/1,
     test_slot_histogram/1,
     test_std_duration/1,
-    test_folsom_histogram/1,
     test_aggregate/1,
     test_history1_slide/1,
     test_history1_slotslide/1,
-    test_history1_folsom/1,
     test_history4_slide/1,
     test_history4_slotslide/1,
-    test_history4_folsom/1,
     test_re_register_probe/1,
     test_ext_predef/1,
     test_app_predef/1,
@@ -95,14 +92,11 @@ groups() ->
        test_std_histogram,
        test_slot_histogram,
        test_std_duration,
-       test_folsom_histogram,
        test_aggregate,
        test_history1_slide,
        test_history1_slotslide,
-       test_history1_folsom,
        test_history4_slide,
        test_history4_slotslide,
-       test_history4_folsom,
        test_slide_ignore_outdated
       ]},
      {re_register, [shuffle],
@@ -130,15 +124,6 @@ init_per_suite(Config) ->
 end_per_suite(_Config) ->
     ok.
 
-init_per_testcase(Case, Config) when
-      Case == test_folsom_histogram;
-      Case == test_history1_folsom;
-      Case == test_history4_folsom ->
-    {ok, StartedApps} = exometer_test_util:ensure_all_started(exometer_core),
-    ct:log("StartedApps = ~p", [StartedApps]),
-    application:start(bear),
-    application:start(folsom),
-    [{started_apps, StartedApps} | Config];
 init_per_testcase(Case, Config) when
       Case == test_ext_predef;
       Case == test_function_match ->
@@ -162,14 +147,6 @@ init_per_testcase(_Case, Config) ->
     ct:log("StartedApps = ~p~n", [StartedApps]),
     [{started_apps, StartedApps} | Config].
 
-end_per_testcase(Case, Config) when
-      Case == test_folsom_histogram;
-      Case == test_history1_folsom;
-      Case == test_history4_folsom ->
-    _ = stop_started_apps(Config),
-    folsom:stop(),
-    application:stop(bear),
-    ok;
 end_per_testcase(Case, Config) when
       Case == test_ext_predef;
       Case == test_function_match ->
@@ -367,32 +344,6 @@ update_duration(C, V) ->
     timer:sleep(V),
     exometer:update(C, timer_end).
 
-test_folsom_histogram(_Config) ->
-    ok = exometer:new(
-	   C1 = [?MODULE,hist,?LINE],
-	   ad_hoc, [{module, exometer_folsom},
-		    {type, histogram}]),  %% truncate by default
-    ok = exometer:new(
-	   C2 = [?MODULE,hist,?LINE],
-	   ad_hoc, [{module, exometer_folsom},
-		    {type, histogram},
-		    {truncate, true}]),
-    ok = exometer:new(
-	   C3 = [?MODULE,hist,?LINE],
-	   ad_hoc, [{module, exometer_folsom},
-		    {type, histogram},
-		    {truncate, false}]),
-    _ = [[update_(C1,V),update_(C2,V),update_(C3,V)] || V <- vals()],
-    {_, {ok,DPs1}} = timer:tc(exometer, get_value, [C1]),
-    {_, {ok,DPs2}} = timer:tc(exometer, get_value, [C2]),
-    {_, {ok,DPs3}} = timer:tc(exometer, get_value, [C3]),
-    [{n,134},{mean,2},{min,1},{max,9},{median,2},
-     {50,2},{75,3},{90,4},{95,5},{99,8},{999,9}] = DPs1 = DPs2,
-    [{n,134},{mean,2126866},{min,1},{max,9},{median,2},
-     {50,2},{75,3},{90,4},{95,5},{99,8},{999,9}] =
-     	scale_mean(DPs3),
-    ok.
-
 test_aggregate(_Config) ->
     K = ?LINE,
     ok = exometer:new(E1 = [?MODULE, K, a, 1], gauge, []),
@@ -414,18 +365,12 @@ test_history1_slide(_Config) ->
 test_history1_slotslide(_Config) ->
     test_history(1, slot_slide, file_path("test/data/puts_time_hist1.bin")).
 
-test_history1_folsom(_Config) ->
-    test_history(1, folsom, file_path("test/data/puts_time_hist1.bin")).
-
 test_history4_slide(_Config) ->
     test_history(4, slide, file_path("test/data/puts_time_hist4.bin")).
 
 test_history4_slotslide(_Config) ->
     test_history(4, slot_slide, file_path("test/data/puts_time_hist4.bin")).
 
-test_history4_folsom(_Config) ->
-    test_history(4, folsom, file_path("test/data/puts_time_hist4.bin")).
-
 test_re_register_probe(_Config) ->
     K = ?LINE,
     ok = exometer:re_register(S1 = [?MODULE, K, s, 1], spiral, []),  % re_register as new/3
@@ -556,7 +501,7 @@ test_history(N, slide, F) ->
     RefStats = load_data(F, M),
     ct:log("history(~w,s): ~p~n"
            "reference:   ~p~n", [N, exometer:get_value(M),
-                                 subset(RefStats)]),
+                                 RefStats]),
     ok;
 test_history(N, slot_slide, F) ->
     M = [?MODULE, hist, ?LINE],
@@ -567,27 +512,11 @@ test_history(N, slot_slide, F) ->
                        {slot_period, 1}]),
     RefStats = load_data(F, 2000, M),
     {T, {ok, Val}} = timer:tc(exometer,get_value,[M]),
-    Subset = subset(RefStats),
-    Error = calc_error(Val, Subset),
+    Error = calc_error(Val, RefStats),
     ct:log("time: ~p~n"
            "history(~w,ss): ~p~n"
            "reference:    ~p~n"
-           "error: ~p~n", [T, N, Val, Subset, Error]),
-    ok;
-test_history(N, folsom, F) ->
-    M = [?MODULE, hist, ?LINE],
-    ok = exometer:new(
-           M, ad_hoc, [{module, exometer_folsom},
-                       {type, histogram},
-                       {truncate, true}]),
-    RefStats = load_data(F, M),
-    {T, {ok, Val}} = timer:tc(exometer,get_value,[M]),
-    Subset = subset(RefStats),
-    Error = calc_error(Val, Subset),
-    ct:log("time: ~p~n"
-           "history(~w,f): ~p~n"
-           "reference: ~p~n"
-           "error: ~p~n", [T, N, Val, Subset, Error]),
+           "error: ~p~n", [T, N, Val, RefStats, Error]),
     ok.
 
 vals() ->
@@ -620,7 +549,7 @@ load_data(F, M) ->
     ct:log("load_data(~s,...)", [F]),
     ct:log("CWD = ~p", [element(2, file:get_cwd())]),
     {ok, [Values]} = file:consult(F),
-    Stats = bear:get_statistics(Values),
+    Stats = exometer_util:get_statistics(Values),
     _T1 = os:timestamp(),
     _ = [ok = exometer:update(M, V) || V <- Values],
     _T2 = os:timestamp(),
@@ -628,7 +557,7 @@ load_data(F, M) ->
 
 load_data(F, Rate, M) ->
     {ok, [Values]} = file:consult(F),
-    Stats = bear:get_statistics(Values),
+    Stats = exometer_util:get_statistics(Values),
     pace(Rate, fun([V|Vs]) ->
                        ok = exometer:update(M, V),
                        {more, Vs};
@@ -673,20 +602,25 @@ shoot(F, St, [_|T]) ->
 shoot(_, St, []) ->
     {more, St}.
 
-subset(Stats) ->
-    lists:map(
-      fun(mean) -> {mean, proplists:get_value(arithmetic_mean, Stats)};
-         (K) when is_atom(K) -> lists:keyfind(K, 1, Stats);
-         (P) when is_integer(P) ->
-              lists:keyfind(P, 1, proplists:get_value(percentile,Stats,[]))
-      end, [n,mean,min,max,median,50,75,90,95,99,999]).
-
 calc_error(Val, Ref) ->
+    ct:pal("Val = ~p, Ref = ~p", [Val, Ref]),
     lists:map(
       fun({{K,V}, {K,R}}) ->
-              {K, abs(V-R)/R}
-      end, lists:zip(Val, Ref)).
+              {K, try_err(V, R)}
+      end, lists:zip(Val, sort_ref(Val, Ref))).
 
+sort_ref([{K,_}|T], Ref) ->
+    {_, V} = lists:keyfind(K, 1, Ref),
+    [{K, V} | sort_ref(T, Ref)];
+sort_ref([], _) ->
+    [].
+
+try_err(V, R) ->
+    try abs(V-R)/R
+    catch
+        error:_ ->
+            error
+    end.
 
 compile_app1(Config) ->
     DataDir = filename:absname(?config(data_dir, Config)),