In my previous post I drew an idea of sending PostgreSQL metrics to Datadog using Java code. This post will reveal implementation details of the Send action described previously.
How does Datadog collect metrics?
There are two basic ways of collecting and sending data:
- Use Datadog agent
- Collect and send manually
Use Datadog agent
Datadog agent consists of three components: the collector, DogStatsD and the forwarder. All run on a host – a server, local machine etc. The collector collects metrics from the host and the forwarder sends them to Datadog. What is important for a custom integration is the DogStatsD, which is a backend server capable of receiving custom metrics from an application. For more information about those components visit the agent page.
Collect and send manually
Alternatively, data can be collected manually (as opposed to using collector) and sent to Datadog API directly. This can be useful if Datadog agent cannot or shouldn’t be installed on a host.
Utilising the two methods
Datadog offers a number of libraries that can be used for integration. I chose two of them:
- java-dogstatsd-client – a statsd client library. This will be used to demonstrate communication with the agent installed on a host.
- metrics-datadog – written by Coursera, Datadog API client that creates a bridge between Dropwizard metrics and Datadog. This method can be used to demonstrate direct communication with the API.
An example solution contains the following interfaces and classes:
- CustomGauge models a gauge
- MetricsProvider gathers desired metrics
- MetricsBroker sends data to Datadog
- MetricsReporter ties MetricsProvider and MetricsBroker together
- ReporterApp is a placeholder scheduler application that uses MetricsReporter and ScheduledExecutorService to report periodically
The following diagram demonstrates structure of classes:
Contains all contracts, the DatadogFakeMetricsReporter, FakeMetricsProvider and the CustomGauge classes.
Dropwizard project with the DatadogMetricsBroker implementation. Set your own apiKey in the server.yml file and run from the module folder:
In order to send data, DatadogReporter has been used:
DatadogReporter datadogReporter = DatadogReporter.forRegistry(new MetricRegistry()) .withTransport(new HttpTransport.Builder().withApiKey(configuration.getApiKey()).build()) .withPrefix("datadog.example") .withHost("techarchnotes.com") .build();
The report method is called to send metrics.
public void report( SortedMap<String, Gauge> gauges, SortedMap<String, Counter> counters, SortedMap<String, Histogram> histograms, SortedMap<String, Meter> meters, SortedMap<String, Timer> timers)
datadogReporter.report( gaugesMap, Collections.emptySortedMap(), Collections.emptySortedMap(), Collections.emptySortedMap(), Collections.emptySortedMap());
Since I use only particular gauge as an example, the rest of the metrics are empty.
A console application with the StatsDMetricsBroker implementation. To run it, type the same command as above from the module folder:
NonBlockingStatsDClient is used to communicate with the statsd server.
StatsDClient statsDClient = new NonBlockingStatsDClient( PREFIX, BIND_HOSTNAME, PORT, CONSTANT_TAGS, ERROR_HANDLER);
If your binding address is different than the one used in this example, change hardcoded values of the host and port bindings in the DatadogStatsDApp class:
private static final String BIND_HOSTNAME = "localhost"; private static final int PORT = 8125;
The metrics should now be received by Datadog. How to observe them will be described in a next post.