package dnstt import "github.com/prometheus/client_golang/prometheus" const namespace = "dnstt" // Exporter exposes aggregate DNSTT traffic metrics from a Collector. type Exporter struct { collector *Collector activeClients *prometheus.Desc peakClients *prometheus.Desc queries *prometheus.Desc bytesIn *prometheus.Desc bytesOut *prometheus.Desc sessions *prometheus.Desc } // NewExporter creates a Prometheus collector for DNSTT metrics. func NewExporter(collector *Collector) *Exporter { labels := append([]string{"domain"}, collector.GeoLabelNames()...) return &Exporter{ collector: collector, activeClients: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "active_clients"), "Number of DNSTT client sessions observed within the active timeout window.", labels, nil, ), peakClients: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "peak_clients"), "Maximum concurrent active DNSTT client sessions observed.", labels, nil, ), queries: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "queries_total"), "Total DNSTT DNS queries observed.", labels, nil, ), bytesIn: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "bytes_in_total"), "Total bytes observed in DNSTT DNS queries.", labels, nil, ), bytesOut: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "bytes_out_total"), "Total bytes observed in DNSTT DNS responses.", labels, nil, ), sessions: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "sessions_total"), "Total unique DNSTT client sessions observed.", labels, nil, ), } } // Describe sends metric descriptors to Prometheus. func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.activeClients ch <- e.peakClients ch <- e.queries ch <- e.bytesIn ch <- e.bytesOut ch <- e.sessions } // Collect sends current metric values to Prometheus. func (e *Exporter) Collect(ch chan<- prometheus.Metric) { for _, tunnel := range e.collector.Snapshot().Tunnels { for _, series := range tunnel.Series { labels := e.labelValues(series) ch <- prometheus.MustNewConstMetric(e.activeClients, prometheus.GaugeValue, float64(series.ActiveClients), labels...) ch <- prometheus.MustNewConstMetric(e.peakClients, prometheus.GaugeValue, float64(series.PeakClients), labels...) ch <- prometheus.MustNewConstMetric(e.queries, prometheus.CounterValue, float64(series.TotalQueries), labels...) ch <- prometheus.MustNewConstMetric(e.bytesIn, prometheus.CounterValue, float64(series.BytesIn), labels...) ch <- prometheus.MustNewConstMetric(e.bytesOut, prometheus.CounterValue, float64(series.BytesOut), labels...) ch <- prometheus.MustNewConstMetric(e.sessions, prometheus.CounterValue, float64(series.TotalSessions), labels...) } } } func (e *Exporter) labelValues(series SeriesSnapshot) []string { values := []string{series.Domain} for _, label := range e.collector.GeoLabelNames() { switch label { case "country": values = append(values, series.Country) case "asn": values = append(values, series.ASN) } } return values }