https://github.com/maxenglander/dometer
dometer is a DNS proxy that emits telemetry
https://github.com/maxenglander/dometer
cpp dns dns-proxy metrics prometheus telemetry
Last synced: over 1 year ago
JSON representation
dometer is a DNS proxy that emits telemetry
- Host: GitHub
- URL: https://github.com/maxenglander/dometer
- Owner: maxenglander
- License: mit
- Created: 2019-08-05T00:33:08.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2020-04-20T07:53:26.000Z (about 6 years ago)
- Last Synced: 2025-01-23T20:53:59.084Z (over 1 year ago)
- Topics: cpp, dns, dns-proxy, metrics, prometheus, telemetry
- Language: C++
- Homepage: https://github.com/maxenglander/dometer
- Size: 33.2 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dometer
`dometer` is a DNS proxy that emits telemetry.
## Platforms
`dometer` has been built and tested on the following platforms:
| Platform | Versions |
| :------- | :------- |
| Mac OS | 10.12.6, 10.15.4 |
| Ubuntu | 18.04.4 |
## Building
In order to build `dometer`, the following build-time dependencies are
required and must be either already present or manually installed.
| Dependency | Recommended version |
| :--------- | :------------------ |
| Bazel | 2.2.0 |
| CMake | 3.16.2 |
| envsubst | 0.20.2 |
Versions other than those recommended above may or may not work.
Once the build-time dependencies are present, run the following command to build
`dometer`:
```
dometer $ bazel build //dometer/cli:main
```
Bazel will download and build the following third-party libraries for run-time use.
* [ThinkAsync/asio (non-Boost version)](http://think-async.com/Asio)
* [TartanLlama/expected](https://github.com/TartanLlama/expected)
* [open-source-parsers/openjsoncpp](https://github.com/open-source-parsers/jsoncpp)
* [jupp0r/prometheus-cpp](https://github.com/jupp0r/prometheus-cpp)
* [TartanLlama/optional](https://github.com/TartanLlama/optional)
* [mpark/variant](https://github.com/mpark/variant)
* [tristanpenman/valijson](https://github.com/tristanpenman/valijson)
## Usage
`dometer` is started through the command-line.
```
dometer $ ./bazel-bin/dometer/cli/main
Dometer.
Usage:
dometer --config=
dometer --help
Options:
--config= Supply configuration file [default: /etc/dometer/config.json].
--help Show this help message.
```
For example:
```
dometer $ ./bazel-bin/dometer/cli --config dometer/config/config.json.sample
```
## Configuration
`dometer` is configured through a JSON file, e.g.:
```
dometer $ ./bazel-bin/dometer/cli/main --config dometer/config/config.json.sample
```
See the [configuration JSON schema](./dometer/config/schema.json) for a description
of the available options, or the [sample configuration file](./dometer/config/config.json.sample)
for an example configuration.
## Components
### DNS
The `dometer` DNS component accepts and resolves incoming DNS requests.
#### Server
The `dometer` DNS server listens for incoming UDP DNS requests, by default at
`udp://0.0.0.0:6353`.
#### Resolver
`dometer` resolves incoming DNS requests using a resolver. The following
resolver types can be selected:
* `libresolv`
By default, the `libresolv` resolver is used.
##### `libresolv`
The `libresolv` resolver library uses the BIND-compatible resolver library native
to the host platform. It can be configured to use one of the following resolver
functions:
| Function | Description |
| :------- | :---------- |
| `query` | Uses the `res_query(3)` resolver routine. |
| `search` | Uses the `res_search(3)` resolver routine. |
### Metrics
The `dometer` metrics component collects metrics on DNS resolution attempts and
replies for each incoming DNS request.
The following metrics are collected:
| Name | Type | Unit | Description |
| :---- | :---- | :---- | :----------- |
| `dometer_dns_lookup_duration` | histogram | seconds | The duration of DNS resolutions attempted by `dometer`. |
#### Handlers
`dometer` emits collected metrics using one or more configured handlers.
Currently, the following handlers are supported:
* `prometheus`
##### `prometheus`
The `prometheus` handler emits metrics as Prometheus time-series. By default, it
exposes metrics through an HTTP server serving requests at `http://0.0.0.0:9090/metrics`.
**Format**
It emits metric data in the following format:
```
dometer_dns_lookup_duration_seconds_count{
error="-|NOERROR|CONNREFUSED|...",
qclass="IN",
qname=".*",
qtype="A|MX|...",
rcode="-|NOERROR|NXDOMAIN|...",
[additional_labels]
}
dometer_dns_lookup_duration_seconds_sum{
error="-|NOERROR|CONNREFUSED|...",
qclass="IN",
qname=".*",
qtype="A|MX|...",
rcode="-|NOERROR|NXDOMAIN|...",
[additional_labels]
}
dometer_dns_lookup_duration_seconds_bucket{
error="-|NOERROR|CONNREFUSED|...",
qclass="IN",
qname=".*",
qtype="A|MX|...",
rcode="-|NOERROR|NXDOMAIN|...",
[additional_labels],
le=""
}
```
**Maximum time-series**
Because the possible combinations of domains and record types that can be
requested through `dometer` is potentially unbounded, the Prometheus metric
handler tracks time-series with an LRU cache. This LRU cache will evict the
least recently used time-series when new time-series data would result in the
cache storing more than the user-defined maximum number of time-series.
A Prometheus time-series is a unique combination of:
* Time-series name (e.g. `dometer_dns_lookup_duration_bucket`)
* A set of labels and their values (e.g. `{error="-",rcode="NXDOMAIN",...}`)
The following Prometheus time-series are distinct, even though they were
generated or updated by the same DNS request to `dometer`:
```
dometer_dns_lookup_duration_seconds_bucket{
error="-",qclass="IN",qname="hello.world",qtype="A",rcode="NXDOMAIN",le="0.1"
} 1
dometer_dns_lookup_duration_seconds_bucket{
error="-",qclass="IN",qname="hello.world",qtype="A",rcode="NXDOMAIN",le="1.0"
} 0
```
The number of time-series generated or updated by a single DNS request to
`dometer` is a function of the metric type and other metric options. For
example, a Prometheus histogram metric generates one time series for the total
count of collected observations, one for the sum of collected observations, and
one for each each bucket.
## Testing
The build dependencies listed above must be present in order to test `dometer`.
Once they are present, run the following command:
```
dometer $ bazel test ...
```
The following testing libraries will be downloaded and built by Bazel.
* [google/googletest](https://github.com/google/googletest)
## API Stability
No guarantees are made about the stability of any part of `dometer`, including:
* The name and shape of emitted metrics
* The command-line interface
## Quality
No guarantees or assertions are made about the performance, reliability, or
safety of this software. Use at your own risk.
## Inspiration and motivation
`dometer` is inspired by Envoy and CoreDNS.
- [Envoy UDP listener](https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/udp_filters/udp_proxy)
- [CoreDNS metrics](https://github.com/coredns/coredns/tree/master/plugin/metrics)
I was motivated to create `dometer` as a personal learning project, and because
I ran into several DNS-related issues at work where a tool like `dometer` would
have been useful for debugging.