{"id":15470466,"url":"https://github.com/feuerlabs/exometer_core","last_synced_at":"2025-05-15T20:07:18.611Z","repository":{"id":23410040,"uuid":"26772418","full_name":"Feuerlabs/exometer_core","owner":"Feuerlabs","description":"Core components of exometer","archived":false,"fork":false,"pushed_at":"2025-05-14T21:13:18.000Z","size":1554,"stargazers_count":193,"open_issues_count":22,"forks_count":120,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-15T20:06:37.942Z","etag":null,"topics":["erlang"],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Feuerlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-11-17T19:08:17.000Z","updated_at":"2025-04-21T15:45:23.000Z","dependencies_parsed_at":"2024-06-18T15:14:32.503Z","dependency_job_id":"11f3e994-4bf1-4adf-b479-011bcc630f45","html_url":"https://github.com/Feuerlabs/exometer_core","commit_stats":{"total_commits":166,"total_committers":31,"mean_commits":5.354838709677419,"dds":0.6746987951807228,"last_synced_commit":"d1d8b08b65b7f86631147e00b106259ede5d9d50"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Feuerlabs%2Fexometer_core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Feuerlabs%2Fexometer_core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Feuerlabs%2Fexometer_core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Feuerlabs%2Fexometer_core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Feuerlabs","download_url":"https://codeload.github.com/Feuerlabs/exometer_core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414501,"owners_count":22067272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang"],"created_at":"2024-10-02T02:04:50.245Z","updated_at":"2025-05-15T20:07:13.548Z","avatar_url":"https://github.com/Feuerlabs.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n# Exometer Core - Erlang instrumentation package, core services #\n\nCopyright (c) 2014 Basho Technologies, Inc.  All Rights Reserved.\n\n__Version:__ Feb 17 2024 15:18:00\n\n__Authors:__ Ulf Wiger ([`ulf.wiger@feuerlabs.com`](mailto:ulf.wiger@feuerlabs.com)), Magnus Feuer ([`magnus.feuer@feuerlabs.com`](mailto:magnus.feuer@feuerlabs.com)).\n\n[![Build Status](https://github.com/Feuerlabs/exometer_core/actions/workflows/main.yml/badge.svg)](https://github.com/Feuerlabs/exometer_core/actions/workflows/main.yml)\n[![Hex.pm Version][hex version badge]][hex]\n[![Hex.pm License][hex license badge]][hex]\n[![Build Tool][build tool]][hex]\n\nThe Exometer Core package allows for easy and efficient instrumentation of\nErlang code, allowing crucial data on system performance to be\nexported to a wide variety of monitoring systems.\n\nExometer Core comes with a set of pre-defined monitor components, and can\nbe expanded with custom components to handle new types of Metrics, as\nwell as integration with additional external systems such as\ndatabases, load balancers, etc.\n\nThis document gives a high level overview of the Exometer system. For\ndetails, please see the documentation for individual modules, starting\nwith `exometer`.\n\nNote the section on [Dependency Management](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Dependency_Management) for how to deal with\noptional packages, both users and developers.\n\n\n### \u003ca name=\"Table_of_Content\"\u003eTable of Content\u003c/a\u003e ###\n\n1. [Concept and definitions](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Concept_and_definitions)\n    1. [Metric](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Metric)\n    2. [Data Point](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Data_Point)\n    3. [Metric Type](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Metric_Type)\n    4. [Entry Callback](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Entry_Callback)\n    5. [Probe](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Probe)\n    6. [Caching](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Caching)\n    7. [Subscriptions and Reporters](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Subscriptions_and_Reporters)\n2. [Built-in entries and probes](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Built-in_entries_and_probes)\n    1. [counter (exometer native)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#counter_(exometer_native))\n    2. [fast_counter (exometer native)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#fast_counter_(exometer_native))\n    3. [gauge (exometer native)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#gauge_(exometer_native))\n    4. [exometer_histogram (probe)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_histogram_(probe))\n    5. [exometer_uniform (probe)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_uniform_(probe))\n    6. [exometer_spiral (probe)](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_spiral_(probe))\n    7. [exometer_function [entry]](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_function_[entry])\n3. [Built in Reporters](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Built_in_Reporters)\n    1. [exometer_report_tty](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#exometer_report_tty)\n4. [Instrumenting Erlang code](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Instrumenting_Erlang_code)\n    1. [Exometer Core Start](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Exometer_Core_Start)\n    2. [Creating metrics](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Creating_metrics)\n    3. [Deleting metrics](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Deleting_metrics)\n    4. [Setting metric values](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Setting_metric_values)\n    5. [Retrieving metric values](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Retrieving_metric_values)\n    6. [Setting up subscriptions](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Setting_up_subscriptions)\n    7. [Set metric options](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Set_metric_options)\n5. [Configuring Exometer Core](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_Exometer_Core)\n    1. [Configuring type - entry maps](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_type_-_entry_maps)\n    2. [Configuring statically defined entries](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_statically_defined_entries)\n    3. [Configuring static subscriptions](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_static_subscriptions)\n    4. [Configuring reporter plugins](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_reporter_plugins)\n6. [Creating custom exometer entries](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Creating_custom_exometer_entries)\n7. [Creating custom probes](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Creating_custom_probes)\n8. [Creating custom reporter plugins](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Creating_custom_reporter_plugins)\n9. [Dependency management](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Dependency_management)\n\n\n### \u003ca name=\"Concepts_and_Definitions\"\u003eConcepts and Definitions\u003c/a\u003e ###\n\nExometer Core introduces a number of concepts and definitions used\nthroughout the documentation and the code.\n\n![Overview](/doc/exometer_overview.png?raw=true)\n\n\n#### \u003ca name=\"Metric\"\u003eMetric\u003c/a\u003e ####\n\nA metric is a specific measurement sampled inside an Erlang system and\nthen reported to the Exometer Core system. An example metric would be\n\"transactions_per_second\", or \"memory_usage\".\n\nMetrics are identified by a list of terms, such as given below:\n\n`[ xml_front_end, parser, file_size ]`\n\nA metric is created through a call by the code to be instrumented to\n`exometer:new/2`. Once created, the metric can be updated through\n`exometer:update/2`, or on its own initiative through the\n`exometer_probe:sample` behavior implementation.\n\n\n#### \u003ca name=\"Data_Point\"\u003eData Point\u003c/a\u003e ####\n\nEach metric can consist of multiple data points, where each point has\na specific value.\n\nA typical example of data points would be a\n`transactions_per_second` (tps) metric, usually stored as a\nhistogram covering the last couple of minutes of tps samples. Such a\nhistogram would host multiple values, such as `min`, `max`,\n`median`, `mean`, `50_percentile`, `75_percentile`,\netc.\n\nIt is up to the type of the metric, and the data probe backing that\ntype (see below), to specify which data points are available under the\ngiven metric.\n\n\n#### \u003ca name=\"Metric_Type\"\u003eMetric Type\u003c/a\u003e ####\n\nThe type of a metric, specified when the metric is created through\n`exometer:new/2`, determines which `exometer_entry`\ncallback to use.\n\nThe link between the type and the entry to use is configured\nthrough the `exometer_admin` module, and its associated exometer\ndefaults configuration data.\n\nThe metric type, in other words, is only used to map a metric to a\nconfigurable `exometer_entry` callback.\n\n\n#### \u003ca name=\"Entry_Callback\"\u003eEntry Callback\u003c/a\u003e ####\n\nAn exometer entry callback will receive values reported to a metric through the\n`exometer:update/2` call and compile it into one or more data points.\nThe entry callback can either be a counter (implemented natively\nin `exometer`), or a more complex statistical analysis such\nas a uniform distribution or a regular histogram.\n\nThe various outputs from these entries are reported as data points\nunder the given metric.\n\n\n#### \u003ca name=\"Probe\"\u003eProbe\u003c/a\u003e ####\n\nProbes are a further specialization of exometer entries that run in\ntheir own Erlang processes and have their own state (like a\ngen_server). A probe is implemented through the `exometer_probe`\nbehavior.\n\nA probe can be used if independent monitoring is needed of,\nfor example, `/proc` trees, network interfaces, and other subsystems\nthat need periodic sampling. In these cases, the\n`exometer_probe:probe_sample()` call is invoked regularly by exometer,\nin the probe's own process, in order to extract data from\nthe given subsystem and add it to the metric's data points.\n\n\n#### \u003ca name=\"Caching\"\u003eCaching\u003c/a\u003e ####\n\nMetric and data point values are read with the `exometer:get_value/1`\nfunction. In the case of counters, this operation is very fast. With probes,\nthe call results in a synchronous dialog with the probe process, and the\ncost of serving the request depends on the probe implementation and the\nnature of the metric being served.\n\nIf the cost of reading the value is so high that calling the function often\nwould result in prohibitive load, it is possible to cache the value. This is\ndone either explicitly from the probe itself (by calling\n`exometer_cache:write/3`), or by specifying the option `{cache, Lifetime}`\nfor the entry. If an entry has a non-zero cache lifetime specified, the\n`get_value/1` call will try fetching the cached value before calling the\nactual entry and automatically caching the result.\n\nNote that if `{cache, Lifetime}` is not specified, `exometer:get_value/1`\nwill neither read nor write to the cache. It is possible for the probe\nto periodically cache a value regardless of how the cache lifetime is set,\nand the probe may also explicitly read from the cache if it isn't done\nautomatically.\n\n\n#### \u003ca name=\"Subscriptions_and_Reporters\"\u003eSubscriptions and Reporters\u003c/a\u003e ####\n\nThe subscription concept, managed by `exometer_report` allows metrics\nand their data points to be sampled at given intervals and delivered\nto one or more recipients, which can be either an arbitrary process\nor a Reporter plugin.\n\nEach subscription ties a specific metric-datapoint pair to a reporter\nand an interval (given in milliseconds). The reporter system will, at\nthe given interval, send the current value of the data point to the\nsubscribing reporter. The subscription, with all its parameters,\nis setup through a call to `exometer_report:subscribe/4`.\n\nIn the case of processes, subscribed-to values will be delivered as a\nmessage. Modules, which implement the `exometer_report` callback\nbehavior, will receive the plugins as a callbacks within the\n`exometer_report` process.\n\nSubscriptions can either be setup at runtime, through\n`exometer_report:subscribe/4` calls, or statically through the\n`exometer_report` configuration data.\n\n\n### \u003ca name=\"Built-in_entries_and_probes\"\u003eBuilt-in entries and probes\u003c/a\u003e ###\n\nThere are a number of built-in entries and probes shipped\nwith the Exometer Core package, as described below:\n\n\n#### \u003ca name=\"counter_(exometer_native)\"\u003ecounter (exometer native)\u003c/a\u003e ####\n\nThe counter is implemented directly in `exometer` to provide simple\ncounters.  A call to `exometer:update/2` will add the provided value\nto the counter.\n\nThe counter can be reset to zero through `exometer:reset/1`.\n\nThe available data points under a metric using the counter entry\nare `value` and `ms_since_reset`.\n\n\n#### \u003ca name=\"fast_counter_(exometer_native)\"\u003efast_counter (exometer native)\u003c/a\u003e ####\n\nA fast counter implements the counter functionality, through the\n`trace_info` system, yielding a speed increase of about 3.5 in\ncomparison to the regular counter.\n\nThe tradeoff is that running tracing and/or debugging may interfere\nwith the counter functionality.\n\nA call to `exometer:update/2` will add the provided value to the\ncounter.\n\nThe counter can be reset to zero through `exometer:reset/1`.\n\nThe available data points under a metric using the fast_counter\nentry are `value` and `ms_since_reset`.\n\n\n#### \u003ca name=\"gauge_(exometer_native)\"\u003egauge (exometer native)\u003c/a\u003e ####\n\nThe gauge is implemented directly in `exometer` to provide simple\ngauges.  A call to `exometer:update/2` will set the gauge's value\nto the provided value. That is, the value of the gauge entry is\nalways the most recently provided value.\n\nThe gauge can be reset to zero through `exometer:reset/1`.\n\nThe available data points under a metric using the gauge entry\nare `value` and `ms_since_reset`.\n\n\n#### \u003ca name=\"exometer_histogram_(probe)\"\u003eexometer_histogram (probe)\u003c/a\u003e ####\n\nThe histogram probe stores a given number of updates, provided through\n`exometer:update/2`, in a histogram. The histogram maintains a log\nderived from all values received during a configurable time span and\nprovides min, max, median, mean, and percentile analysis data points\nfor the stored data.\n\nIn order to save memory, the histogram is divided into equal-sized\ntime slots, where each slot spans a settable interval. All values\nreceived during a time slot will be averaged into a single value to be\nstored in the histogram once the time slot expires. The averaging\nfunction (which can be replaced by the caller), allows for\nhigh-frequency update metrics to have their resolution traded against\nresource consumption.\n\n\n#### \u003ca name=\"exometer_uniform_(probe)\"\u003eexometer_uniform (probe)\u003c/a\u003e ####\n\nThe uniform probe provides a uniform sample over a pool of values\nprovided through `exometer:update/2`. When the pool reaches its configurable\nmax size, existing values will be replaced at random to make space for\nnew values. Much like `exometer_histogram`, the uniform probe\nprovides min, max, median, mean, and percentile analysis data points\nfor the stored data.\n\n\n#### \u003ca name=\"exometer_spiral_(probe)\"\u003eexometer_spiral (probe)\u003c/a\u003e ####\n\nThe spiral probe maintains the total sum of all values stored in its\nhistogram. The histogram has a configurable time span, all values\nprovided to the probe, through `exometer:update/2`, within that time\nspan will be summed up and reported. If, for example, the histogram\ncovers 60 seconds, the spiral probe will report the sum of all\nvalues reported during the last minute.\n\nThe grand total of all values received during the lifetime of the\nprobe is also available.\n\n\n#### \u003ca name=\"exometer_function_[entry]\"\u003eexometer_function [entry]\u003c/a\u003e ####\n\nThe function entry allows for a simple caller-supplied function to be\ninvoked in order to retrieve non-exometer data. The\n`exometer_function:get_value/4` function will invoke a\n`Module:Function(DataPoints)` call, where `Module` and\n`Function` are provided by the caller.\n\nThe function entry provides an easy way of integrating an external\nsystem without having to write a complete entry.\n\n\n### \u003ca name=\"Built_in_Reporters\"\u003eBuilt in Reporters\u003c/a\u003e ###\n\nExometer Core ships with some built-in reporters which can be used to forward\nupdated metrics and their data points to external systems. They can also\nserve as templates for custom-developed reporters.\n\n\n#### \u003ca name=\"exometer_report_tty\"\u003eexometer_report_tty\u003c/a\u003e ####\n\nThe `exometer_report_tty` reporter is mainly intended for experimentation.\nIt outputs reports directly to the tty.\n\n\n### \u003ca name=\"Instrumenting_Erlang_code\"\u003eInstrumenting Erlang code\u003c/a\u003e ###\n\nThe code using Exometer Core needs to be instrumented in order to setup and\nuse metrics reporting.\n\n\n#### \u003ca name=\"Exometer_Core_Start\"\u003eExometer Core Start\u003c/a\u003e ####\n\nThe system using Exometer Core must start the `exometer` application\nprior to using it:\n\n```erlang\n\napplication:start(lager),\napplication:start(exometer_core).\n```\n\nNote that dependent applications need to be started first. On newer OTP versions\n(R61B or later), you can use `application:ensure_all_started(exometer)`.\n\nFor testing, you can also use [`exometer:start/0`](https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer.md#start-0).\n\nSee [Configuring Exometer Core](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_Exometer_Core) for details on configuration data\nformat.\n\n\n#### \u003ca name=\"Creating_metrics\"\u003eCreating metrics\u003c/a\u003e ####\n\nA metric, can be created throuh a call to\n\n```erlang\n\nexometer:new(Name, Type)\n```\n\n`Name` is a list of atoms, uniquely identifying the metric created.\nThe type of the metric, specified by `Type` will be mapped\nto an exometer entry through the table maintained by\n`exometer_admin` Please see the [Configuring type - entry\nmaps](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_type_-_entry_maps) for details.\n\nThe resolved entry to use will determine the data points available\nunder the given metric.\n\n\n#### \u003ca name=\"Deleting_metrics\"\u003eDeleting metrics\u003c/a\u003e ####\n\nA metric previously created with `exometer:new/2` can be deleted by\n`exometer:delete/1`.\n\nAll subscriptions to the deleted metrics will be cancelled.\n\n\n#### \u003ca name=\"Setting_metric_values\"\u003eSetting metric values\u003c/a\u003e ####\n\nA created metric can have its value updated through the\n`exometer:update/2` function:\n\n```erlang\n\nexometer:update(Name, Value)\n```\n\nThe `Name` parameter is the same atom list provided to a previous\n`exometer:new/2` call. The `Value` is an arbitrarty element that is\nforwarded to the `exometer:update/2` function of the entry/probe that the\nmetric is mapped to.\n\nThe receiving entry/probe will process the provided value and modify\nits data points accordingly.\n\n\n#### \u003ca name=\"Retrieving_metric_values\"\u003eRetrieving metric values\u003c/a\u003e ####\n\nExometer-using code can at any time retrieve the data point values\nassociated with a previously created metric. In order to find out which\ndata points are available for a metric, the following call can be used:\n\n```erlang\n\nexometer:info(Name, datapoints)\n```\n\nThe `Name` parameter is the same atom list provided to a previous\n`exometer:new/2` call. The call will return a list of data point\natoms that can then be provided to `exometer:get_value/1` to\nretrieve their actual value:\n\n```erlang\n\nexometer:get_value(Name, DataPoint)\n```\n\nThe `Name` paramer identifies the metric, and `DataPoints`\nidentifies the data points (returned from the previous `info()` call)\nto retrieve the value for.\n\nIf no DataPoints are provided, the values of a default list of data points,\ndetermined by the backing entry / probe, will be returned.\n\n\n#### \u003ca name=\"Setting_up_subscriptions\"\u003eSetting up subscriptions\u003c/a\u003e ####\n\nA subscription can either be statically configured, or dynamically\nsetup from within the code using Exometer Core. For details on statically\nconfigured subscriptions, please see [Configuring static subscriptions](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_static_subscriptions).\n\nA dynamic subscription can be setup with the following call:\n\n```erlang\n\nexometer_report:subscribe(Recipient, Metric, DataPoint, Inteval)\n```\n\n`Recipient` is the name of a reporter.\n\n\n#### \u003ca name=\"Set_metric_options\"\u003eSet metric options\u003c/a\u003e ####\n\nEach created metric can have options setup for it through the following call:\n\n```erlang\n\nexometer:setopts(Name, Options)\n```\n\nThe `Name` paramer identifies the metric to set the options for, and\nOptions is a proplist (`[{ Key, Value },...]`) with the options to be\nset.\n\nExometer Core looks up the the backing entry that hosts the metric with\nthe given Name, and will invoke the entry\\'s `setopts/4` function to set\nthe actual options. Please see the `setopts/4` function for the various\nentries for details.\n\n\n### \u003ca name=\"Configuring_Exometer_Core\"\u003eConfiguring Exometer Core\u003c/a\u003e ###\n\nExometer Core defaults can be changed either through OTP application environment\nvariables or through the use of Basho's `cuttlefish`\n([`https://github.com/basho/cuttlefish`](https://github.com/basho/cuttlefish)).\n\n__Note:__ Exometer Core will check both the `exometer` and the `exometer_core`\napplication environments. The `exometer` environment overrides the\n`exometer_core` environment. However, if only `exometer_core` is used, any\n`exometer` environment will simply be ignored. This is because of the\napplication controller: environment data is not loaded until the application\nin question is loaded.\n\n\n#### \u003ca name=\"Configuring_type_-_entry_maps\"\u003eConfiguring type - entry maps\u003c/a\u003e ####\n\nThe dynamic method of configuring defaults for `exometer` entries is:\n\n```erlang\n\nexometer_admin:set_default(NamePattern, Type, Default)\n```\n\nWhere `NamePattern` is a list of terms describing what is essentially\na name prefix with optional wildcards (`'_'`). A pattern that\nmatches any legal name is `['_']`.\n\n`Type` is an atom defining a type of metric. The types already known to\n`exometer`, `counter`, `fast_counter`, `ticker`, `uniform`, `histogram`,\n`spiral`, `netlink`, and `probe` may be redefined, but other types can be\ndescribed as well.\n\n`Default` is either an `#exometer_entry{}` record (unlikely), or a list of\n`{Key, Value}` options, where the keys correspond to `#exometer_entry` record\nattribute names. The following attributes make sense to preset:\n\n```erlang\n\n{module, atom()}              % the callback module\n{status, enabled | disabled}  % operational status of the entry\n{cache, non_neg_integer()}    % cache lifetime (ms)\n{options, [{atom(), any()}]}  % entry-specific options\n```\n\nBelow is an example, from `exometer_core/priv/app.config`:\n\n```erlang\n\n{exometer, [\n    {defaults, [\n        {['_'], function , [{module, exometer_function}]},\n        {['_'], counter  , [{module, exometer}]},\n        {['_'], histogram, [{module, exometer_histogram}]},\n        {['_'], spiral   , [{module, exometer_spiral}]}\n    ]}\n]}\n```\n\nIn systems that use CuttleFish, the file `exometer/priv/exometer.schema`\ncontains a schema for default settings. The setup corresponding to the above\ndefaults would be as follows:\n\n```ini\n\nexometer.template.function.module  = exometer_function\nexometer.template.counter.module   = exometer\nexometer.template.histogram.module = exometer_histogram\nexometer.template.spiral.module    = exometer_spiral\n```\n\n\n#### \u003ca name=\"Configuring_statically_defined_entries\"\u003eConfiguring statically defined entries\u003c/a\u003e ####\n\nUsing the `exometer` environment variable `predefined`, entries can be added\nat application startup. The variable should have one of the following values:\n\n* `{script, File}` - `File` will be processed using `file:script/2`. The return\n  value (the result of the last expression in the script) should be a list of`{Name, Type, Options}` tuples.\n\n* `{apply, M, F, A}` - The result of `apply(M, F, A)` should be `{ok, L}` where`L` is a list of `{Name, Type, Options}` tuples.\n\n* `L`, where L is a list of `{Name, Type, Options}` tuples or extended\ninstructions (see below).\n\nThe list of instructions may include:\n\n* `{delete, Name}` - deletes `Name` from the exometer registry.\n\n* `{select_delete, Pattern}` - applies a select pattern and\ndeletes all matching entries.\n\n* `{re_register, {Name, Type, Options}}` - redefines an entry if present,\notherwise creates it.\n\nExometer Core will also scan all loaded applications for the environment\nvariables `exometer_defaults` and `exometer_predefined`, and process\nas above. If an application is loaded and started after exometer has started,\nit may call the function `exometer:register_application()` or\n`exometer:register_application(App)`. This function will do nothing if\nexometer isn't already running, and otherwise process the `exometer_defaults`\nand `exometer_predefined` variables as above. The function can also be\ncalled during upgrade, as it will re-apply the settings each time.\n\n\n#### \u003ca name=\"Configuring_static_subscriptions\"\u003eConfiguring static subscriptions\u003c/a\u003e ####\n\nStatic subscriptions, which are automatically setup at exometer\nstartup without having to invoke `exometer_report:subscribe/4`, are\nconfigured through the report sub section under exometer.\n\nBelow is an example, from `exometer/priv/app.config`:\n\n```erlang\n\n{exometer, [\n    {report, [\n        {subscribers, [\n            {exometer_report_collectd, [db, cache, hits], mean, 2000, true},\n            {exometer_report_collectd, [db, cache, hits], max, 5000, false}\n        ]}\n    ]}\n]}\n```\n\nThe `report` section configures static subscriptions and reporter\nplugins. See [Configuring reporter plugins](https://github.com/Feuerlabs/exometer_core/blob/master/doc/README.md#Configuring_reporter_plugins) for details on\nhow to configure individual plugins.\n\nThe `subscribers` sub-section contains all static subscriptions to be\nsetup att exometer applications start. Each tuple in the prop list\nshould be of one of the following formats:\n\n* `{Reporter, Metric, DataPoint, Interval}`\n\n* `{Reporter, Metric, DataPoint, Interval, RetryFailedMetrics}`\n\n* `{Reporter, Metric, DataPoint, Interval, RetryFailedMetrics, Extra}`\n\n* `{apply, {M, F, A}}`\n\n* `{select, {MatchPattern, DataPoint, Interval [, Retry [, Extra] ]}}`\n\nIn the case of `{apply, M, F, A}`, the result of `apply(M, F, A)` must\nbe a list of `subscribers` tuples.\n\nIn the case of `{select, Expr}`, a list of metrics is fetched using\n`exometer:select(MatchPattern)`, where the result must be on the form\n`{Key, Type, Status}` (i.e. what corresponds to `'$_'`).\nThe rest of the items will be applied to each of the matching entries.\n\nThe meaning of the above tuple elements is:\n\n+ `Reporter :: module()`\u003cbr /\u003eSpecifies the reporter plugin module, such as`exometer_report_collectd` that is to receive updated metric's data\npoints.\n\n+ `Metric :: [atoms()]`\u003cbr /\u003eSpecifies the path to a metric previously created with an`exometer:new/2` call.\n\n+ `DataPoint` ::  atom() | [atom()]'\u003cbr /\u003eSpecifies the data point within the given metric to send to the\n    receiver. The data point must match one of the data points returned by`exometer:info(Name, datapoints)` for the given metrics name.\n\n+ `Interval` :: integer()' (milliseconds)\u003cbr /\u003eSpecifies the interval, in milliseconds, between each update of the\ngiven metric's data point. At the given interval, the data point will\nbe samples, and the result will be sent to the receiver.\n\n+ `RetryFailedMetrics :: boolean()`\u003cbr /\u003eSpecifies if the metric should be continued to be reported\n    even if it is not found during a reporting cycle. This would be\n    the case if a metric is not created by the time it is reported for\n    the first time. If the metric will be created at a later time,\n    this value should be set to true. Set this value to false if all\n    attempts to report the metric should stop if when is not found.\n    The default value is `true`.\n\n+ `Extra :: any()`\u003cbr /\u003eProvides a means to pass along extra information for a given\n   subscription. An example is the `syntax` option for the SNMP reporter,\n   in which case `Extra` needs to be a property list.\n\nExample configuration in sys.config, using the `{select, Expr}` pattern:\n\n```erlang\n\n[\n {exometer, [\n             {predefined,\n              [{[a,1], counter, []},\n               {[a,2], counter, []},\n               {[b,1], counter, []},\n               {[c,1], counter, []}]},\n             {report,\n              [\n               {reporters,\n                [{exometer_report_tty, []}]},\n               {subscribers,\n                [{select, {[{ {[a,'_'],'_','_'}, [], ['$_']}],\n                           exometer_report_tty, value, 1000}}]}\n              ]}\n            ]}\n].\n\n```\n\nThis will activate a subscription on `[a,1]` and `[a,2]` in the\n`exometer_report_tty` reporter, firing once per second.\n\n\n#### \u003ca name=\"Configuring_reporter_plugins\"\u003eConfiguring reporter plugins\u003c/a\u003e ####\n\nThe various reporter plugins to be loaded by exometer are configured\nin the `report` section under `reporters`\n\nEach reporter has an entry named after its module, and the content of\nthat entry is dependent on the reporter itself. The following chapters\nspecifies the configuration parameters for the reporters shipped with\nexometer.\n\n\n### \u003ca name=\"Creating_custom_exometer_entries\"\u003eCreating custom exometer entries\u003c/a\u003e ###\n\nPlease see @see exometer_entry documentation for details.\n\n\n### \u003ca name=\"Creating_custom_probes\"\u003eCreating custom probes\u003c/a\u003e ###\n\nPlease see @see exometer_probe documentation for details.\n\n\n### \u003ca name=\"Creating_custom_reporter_plugins\"\u003eCreating custom reporter plugins\u003c/a\u003e ###\n\nPlease see @see exometer_report documentation for details.\n\n\n#### \u003ca name=\"Customizing_rebar.config\"\u003eCustomizing rebar.config\u003c/a\u003e ####\n\nThe OS environment variables `EXOMETER_CORE_CONFIG_PREPROCESS` and\n`EXOMETER_CORE_CONFIG_POSTPROCESS` can be used to insert a script, similar to\n`rebar.config.script` in the processing flow of the exometer build.\n\nAs the names imply, the script given by `EXOMETER_CONFIG_CONFIG_PREPROCESS`\n(if any) will be run before exometer does any processing of its own, and the\n`EXOMETER_CORE_CONFIG_POSTPROCESS` script (if any) will be run after all other\nprocessing is complete.\n\n[travis]: https://travis-ci.org/Feuerlabs/exometer_core\n[travis badge]: https://img.shields.io/travis/Feuerlabs/exometer_core/master.svg?style=flat-square\n[hex]: https://hex.pm/packages/exometer_core\n[hex version badge]: https://img.shields.io/hexpm/v/exometer_core.svg?style=flat-square\n[hex license badge]: https://img.shields.io/hexpm/l/exometer_core.svg?style=flat-square\n[erlang version badge]: https://img.shields.io/badge/erlang-18--21-blue.svg?style=flat-square\n[build tool]: https://img.shields.io/badge/build%20tool-rebar3-orange.svg?style=flat-square\n\n\n## Modules ##\n\n\n\u003ctable width=\"100%\" border=\"0\" summary=\"list of modules\"\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer.md\" class=\"module\"\u003eexometer\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_admin.md\" class=\"module\"\u003eexometer_admin\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_alias.md\" class=\"module\"\u003eexometer_alias\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_cache.md\" class=\"module\"\u003eexometer_cache\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_cpu.md\" class=\"module\"\u003eexometer_cpu\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_duration.md\" class=\"module\"\u003eexometer_duration\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_entry.md\" class=\"module\"\u003eexometer_entry\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_function.md\" class=\"module\"\u003eexometer_function\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_histogram.md\" class=\"module\"\u003eexometer_histogram\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_info.md\" class=\"module\"\u003eexometer_info\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_probe.md\" class=\"module\"\u003eexometer_probe\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_proc.md\" class=\"module\"\u003eexometer_proc\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_report.md\" class=\"module\"\u003eexometer_report\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_report_logger.md\" class=\"module\"\u003eexometer_report_logger\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_report_tty.md\" class=\"module\"\u003eexometer_report_tty\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_shallowtree.md\" class=\"module\"\u003eexometer_shallowtree\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_slide.md\" class=\"module\"\u003eexometer_slide\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_slot_slide.md\" class=\"module\"\u003eexometer_slot_slide\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_spiral.md\" class=\"module\"\u003eexometer_spiral\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_uniform.md\" class=\"module\"\u003eexometer_uniform\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"https://github.com/Feuerlabs/exometer_core/blob/master/doc/exometer_util.md\" class=\"module\"\u003eexometer_util\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeuerlabs%2Fexometer_core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeuerlabs%2Fexometer_core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeuerlabs%2Fexometer_core/lists"}