Custom metrics
Custom metrics allow you to track anything in your application, from newly registered users to database disk usage. Custom metrics are not a replacement for custom instrumentations but provide an additional way to make specific application data accessible and measurable over time.
AppSignal offers three custom metric types, they are:
You can track custom metrics in graphs in your AppSignal dashboards.
Gauge
A gauge is a metric value at a specific time. If you set more than one gauge with the same key, the last reported value for that moment in time is persisted.
Gauges are used for things like tracking sizes of databases, disks, or other absolute values like CPU usage, several items (users, accounts, etc.). Currently, all AppSignal host metrics are stored as gauges.
Ruby and Elixir
# The first argument is a string, the second argument a number # Appsignal.set_gauge(metric_name, value) Appsignal.set_gauge("database_size", 100) Appsignal.set_gauge("database_size", 10) # Will create the metric "database_size" with the value 10
Node.js
const meter = Appsignal.client.metrics(); // The first argument is a string, the second argument a number // meter.setGauge(metric_name, value) meter.setGauge("database_size", 100); meter.setGauge("database_size", 10); // Will create the metric "database_size" with the value 10
Python
# Import the AppSignal metric helper from appsignal import set_gauge # The first argument is a string, the second argument a number (int/float) # set_gauge(metric_name, value) set_gauge("database_size", 100) set_gauge("database_size", 10) # Will create the metric named "database_size" with the value 10
Measurement
At AppSignal measurements are used for things like response times and background job durations. We allow you to track a metric with wildly varying values over time and create graphs based on their average value or call count during that time.
By tracking a measurement, the average and count will be persisted for the metric. A measurement metric creates several metric fields:
- Count: which counts how many times the helper was called. Used for metrics such as throughput.
- Mean: the average metric value for the point in time.
- 90th percentile: the 90th percentile of the metric value for the point in time.
- 95th percentile: the 95th percentile of the metric value for the point in time.
Ruby and Elixir
# The first argument is a string, the second argument a number # Appsignal.add_distribution_value(metric_name, value) Appsignal.add_distribution_value("memory_usage", 100) Appsignal.add_distribution_value("memory_usage", 110) # Will create a metric "memory_usage" with the mean field value 105 # Will create a metric "memory_usage" with the count field value 2
Node.js
const meter = Appsignal.client.metrics(); // The first argument is a string, the second argument a number // meter.addDistributionValue(metric_name, value) meter.addDistributionValue("memory_usage", 100); meter.addDistributionValue("memory_usage", 110); // Will create a metric "memory_usage" with the mean field value 105 // Will create a metric "memory_usage" with the count field value 2
Python
# Import the AppSignal metric helper from appsignal import add_distribution_value # The first argument is a string, the second argument a number (int/float) # add_distribution_value(metric_name, value) add_distribution_value("memory_usage", 100) add_distribution_value("memory_usage", 110) # Will create a metric "memory_usage" with the mean field value 105 # Will create a metric "memory_usage" with the count field value 2
Counter
The counter metric type stores a number value for a given time frame. These counter values are combined into a total count value for the display time frame resolution. This means that when viewing a graph with a minutely resolution it will combine the values of the given minute, and for the hourly resolution combines the values of per hour.
Counters are good to use to track events. With a gauge you can track how many of something (users, comments, etc.) there is at a certain time, but with counters, you can track how many events occurred at a specific time (users signing in, comments being made, etc.).
When the helper is called multiple times, the total/sum of all calls is persisted.
Counters are non-monotonic: increasing and decreasing. Both positive and negative values are supported. For monotonic counters from other systems, there is no validation to make sure the counter values only ever goes up.
Ruby and Elixir
# The first argument is a string, the second argument a number # Appsignal.increment_counter(metric_name, value) Appsignal.increment_counter("login_count", 1) Appsignal.increment_counter("login_count", 1) # Will create the metric "login_count" with the value 2 for a point in the minutely/hourly resolution
Node.js
const meter = Appsignal.client.metrics(); // The first argument is a string, the second argument a number // meter.incrementCounter(metric_name, value) meter.incrementCounter("login_count", 1); meter.incrementCounter("login_count", 1); // Will create the metric "login_count" with the value 2 for a point in the minutely/hourly resolution
Python
# Import the AppSignal metric helper from appsignal import increment_counter # The first argument is a string, the second argument a number (int/float) # increment_counter(metric_name, value) increment_counter("metric_name", 1) # Increase the value by one increment_counter("metric_name", 1) increment_counter("metric_name", -1) # Decrease the value by one # Will create the metric named "metric_name" with the value 2 for a point in the minutely/hourly resolution
Metric naming
We recommend naming your metrics something easily recognizable. While you can wildcard parts of the metric name for dashboard creation, we recommend you only use this for small grouping and not use IDs in metric names.
Metric names only support numbers, letters, dots and underscores ([a-z0-9._]
) as valid characters. Any other characters will be replaced with an underscore by our processor. You can find the list of metrics as processed on the "Add Dashboard".
Some examples of good metric names are:
database_size
account_count
users.count
notifier.failed
notifier.perform
notifier.success
By default AppSignal already tracks metrics for your application, such as host metrics. See the metrics list on the "Add Dashboard" page for the metrics that are already available for your app.
Metric values
Metrics only support numbers as valid values. Any other value will be silently ignored or will raise an error as triggered by the implementation language number parser. For Ruby and Elixir we support a double and integer as valid values:
# Integer Appsignal.increment_counter("login_count", 1) # Double Appsignal.increment_counter("assignment_completed", 0.12)
In Node.js, only the number
type is a valid value:
const meter = Appsignal.client.metrics(); meter.incrementCounter("assignment_completed", 0.12);
Value formatting
AppSignal graphs have several display formats, such as numbers, file sizes, durations, etc. These formats help in presenting the metric values in a human-readable way.
Selecting a value formatter input does not affect the data stored in our systems, only how it's displayed.
To show metric values correctly using these formatters, please check the table below how the value should be reported.
Formatter | Reported value | Description |
---|---|---|
Number | Display value | A human-readable formatted number. The values should be reported on the same scale as they are displayed. The value 1 is displayed as "1 ", 10_000 as "10 K " and 1_000_000 is displayed as "1 M ". |
Percentage | Display value | A metric value formatted as a percentage. The values should be reported on the same scale as they are displayed. The value 40 is displayed as "40 % ". |
Throughput | Display value | A metric value formatted as requests per minute/hour. The values should be reported on the same scale as they are displayed. It will display the throughput formatted as a number for both the minute and the hour. The value 10_000 is displayed "10k / hour 166 / min ". Commonly used for counter metrics. |
Duration | Milliseconds | A duration of time. The values should be reported as milliseconds. The value 100 is displayed as "100 ms " and 60_000 as "60 sec ". Commonly used for measurement metric. |
File size | Customizable | A file size formatted as megabytes by default. 1.0 megabytes is displayed as 1Mb . What file size unit the reported metric value is read as can be customized in the graph builder. |
File size
Metric values that represent a file size can use the file size formatter. To specify which unit of size the reported value is the file size formatter allows for several input values.
The available options are:
Size in Bit
Size in Bytes
Size in Kilobits
Size in Kilobytes
Size in Megabytes
When sending a metric with the following value:
Ruby and Elixir
Appsignal.set_gauge("database_size", 1024)
Node.js
const meter = Appsignal.client.metrics(); meter.setGauge("database_size", 1024);
The graph will render the following display value for the specified file size formatter:
Size in Bit
will render "128 Bytes"Size in Bytes
will render "1 KB"Size in Kilobits
will render "128 KB"Size in Kilobytes
will render "1 MB"Size in Megabytes
will render "1 GB"
Metric tags
A single metric can consist of various groups of data; for example, a 'total_orders' custom metric could consist of pending and processed orders.
You can add multiple tags to metrics for deeper insights into the metric data AppSignal is reporting. Each tag will be represented by its line on an AppSignal graph.
By default, the AppSignal metric helpers do not set tags on a custom metric.
How you can use tags in AppSignal graphs:
Tags can "label" a line in the graph legend, making it easier to see what each line represents when you hover your mouse over them. Filtering with tags can show the same metric in different contexts on different graphs.
To get the most out of metric tags, we advise the following:
-
Be consistent with tagging: For optimal tracking and graph legibility, we advise against reporting a custom metric both with and without tags. Reporting the same metric in different ways can create confusion and make it difficult to interpret the data accurately.
-
Always use the same metric tags when: We recommend using the same combination of tags whenever you report a metric. For example, if a metric uses tags A and B in one area of your app, it should use them in all areas. Avoid changing the tags, as consistent tagging will make graphing easier.
-
Use a limited range of values for metric tags: To avoid overly complex or illegible graphs, we recommend using a limited range of tags on your custom metrics, such as regions (EU, US, and Asia). You can perform a broader analysis of your app's metric data when using a limited and precise range of tags for all of your app metric data.
In general when implementing metric tagging, consider developing a robust tagging strategy that can be applied consistently across your application and will need little to no adjustments in the long term.
Ruby
Appsignal.set_gauge("database_size", 100, :region => "eu") Appsignal.set_gauge("database_size", 50, :region => "us") Appsignal.set_gauge("database_size", 200, :region => "asia") # Multiple tags per metric Appsignal.set_gauge("my_metric_name", 100, :tag_a => "a", :tag_b => "b") Appsignal.set_gauge("my_metric_name", 10, :tag_a => "a", :tag_b => "b") Appsignal.set_gauge("my_metric_name", 200, :tag_a => "b", :tag_b => "c")
Elixir
Appsignal.set_gauge("database_size", 100, %{region: "eu"}) Appsignal.set_gauge("database_size", 50, %{region: "us"}) Appsignal.set_gauge("database_size", 200, %{region: "asia"}) # Multiple tags per metric Appsignal.set_gauge("my_metric_name", 100, %{tag_a: "a", tag_b: "b"}) Appsignal.set_gauge("my_metric_name", 10, %{tag_a: "a", tag_b: "b"}) Appsignal.set_gauge("my_metric_name", 200, %{tag_a: "b", tag_b: "c"})
Node.js
const meter = Appsignal.client.metrics(); meter.setGauge("database_size", 100, { region: "eu" }); meter.setGauge("database_size", 50, { region: "us" }); meter.setGauge("database_size", 200, { region: "asia" }); // Multiple tags per metric meter.setGauge("my_metric_name", 100, { tag_a: "a", tag_b: "b" }); meter.setGauge("my_metric_name", 10, { tag_a: "a", tag_b: "b" }); meter.setGauge("my_metric_name", 200, { tag_a: "b", tag_b: "c" });
Python
from appsignal import set_gauge set_gauge("database_size", 100, {"region": "eu"}) set_gauge("database_size", 50, {"region": "us"}) set_gauge("database_size", 200, {"region": "asia"}) # Multiple tags per metric set_gauge("my_metric_name", 100, {"tag_a": "a", "tag_b": "b"}) set_gauge("my_metric_name", 10, {"tag_a": "a", "tag_b": "b"}) set_gauge("my_metric_name", 200, {"tag_a": "b", "tag_b": "c"})
Rendering metric with and without tags
If you created a custom metric and you have multiple tags associated with it, you can render the metric with and without the tag at the same time in a graph.
Ruby
Appsignal.increment_counter("sign_ups", 1, region: "eu") Appsignal.increment_counter("sign_ups", 1)
Elixir
Appsignal.increment_counter("sign_ups", 1, %{region: "eu"}) Appsignal.increment_counter("sign_ups", 1)
Node.js
const meter = Appsignal.client.metrics(); meter.incrementCounter("sign_ups", 1, { region: "eu" }); meter.incrementCounter("sign_ups", 1);
Python
from appsignal import increment_counter increment_counter("sign_ups", 1, {"region": "eu"}) increment_counter("sign_ups", 1)
Graphing Custom Metrics
Once you've started recording custom metrics, you can start tracking your metrics in custom graphs using our Graph Builder. To do this, navigate to a dashboard of choice, or create a new dashboard and click "Add graph".
When creating a graph, you can select which metrics and tags you want to chart and configure your graph's legends and labels. Once created, the graph will be added to the dashboard and display all recorded custom metric data for the specified period of time.
You can read more about dashboards and graphs in our Dashboard documentation.