Formatting Metrics

App Metrics supports formatting metrics in a Plain Text and JSON format as well as formatting metrics recorded in supported time series database formats such as InfluxDB, Prometheus, Elasticsearch and Graphite.

Formatter packages allow metric snapshots to be serialized, they are designed be used with reporters allowing us to Push metrics or wired-up with a web application allowing us to Pull metrics.

Basics

One or more formatters can be configured using the MetricsBuilder as follows.

First install the App Metrics nuget package which includes Plain Text and Json Formatters.

nuget install App.Metrics

Then to configure both the Plain Text and Json Formatters:

var builder = new MetricsBuilder()
    .OutputMetrics.AsPlainText()
    .OutputMetrics.AsJson();

Then to write metrics to System.Console without configuring a reporter, retreive a metrics snapshot and use each formatter to serialize and then write to System.Console:

var metrics = builder.Build();

// TODO: Record some metrics

var snapshot = metrics.Snapshot.Get();

foreach(var formatter in metrics.OutputMetricsFormatters)
{
    using (var stream = new MemoryStream())
    {
        await formatter.WriteAsync(stream, snapshot);

        var result = Encoding.UTF8.GetString(stream.ToArray());

        System.Console.WriteLine(result);
    }
}

When building an IMetricsRoot using AppMetrics.CreateDefaultBuilder() to build the default configuration, the plain text and JSON formatters are added as part of the defaults.

The following is an example ouput of a simple counter using the plain text formatter:

# TIMESTAMP: 111111111111111111
# MEASUREMENT: [Application] my_counter
# TAGS:
                  mtype = counter
                   unit = none
# FIELDS:
                  value = 1
--------------------------------------------------------------

And the following an example output of a simple counter using the JSON formatter:

{
  "timestamp": "0001-01-1T00:00:00.0000000Z",
  "contexts": [
    {
      "context": "Application",
      "counters": [
        {
          "name": "my_counter",
          "unit": "none",
          "count": 1
        }
      ]
    }
  ]
}

Custom Formatters

To implement a custom formatter:

First install the App.Metrics.Abstractions nuget package:

nuget install App.Metrics.Abstractions

Then implement your custom formatter by implementing IMetricsOutputFormatter:

public class CustomOutputFormatter : IMetricsOutputFormatter
{
    public MetricsMediaTypeValue MediaType => new MetricsMediaTypeValue("text", "vnd.custom.metrics", "v1", "plain");

    public Task WriteAsync(Stream output,
        MetricsDataValueSource snapshot,
        CancellationToken cancellationToken = default)
    {
        // TODO: Serialize the snapshot

        return Task.CompletedTask;
    }
}

The MetricsMediaTypeValue allows content negotiation in a web context, e.g. when using the /metrics.

The custom formatter can made available on the IMetricsRoot using the MetricsBuilder:

var metrics = new MetricsBuilder()
    .OutputMetrics.Using<CustomOutputFormatter>()
    // OR
    // .OutputMetrics.Using(new CustomOutputFormatter())
    .Builder();

Formatters can be configured so that they can be used with the endpoints provided by the App.Metrics.AspNetCore.Endpoints nuget package. This allows for a pull based metrics approach rather than push via a reporter. See Prometheus Reporting for example.