Skip to content

Commit f0e130e

Browse files
committed
skydns: prometheus working
Completely reworked it, added tests.
1 parent ec6fd22 commit f0e130e

File tree

9 files changed

+157
-225
lines changed

9 files changed

+157
-225
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ install:
99
- go get github.com/coreos/go-systemd/activation
1010
- go get github.com/miekg/dns
1111
- go get github.com/rcrowley/go-metrics
12+
- go get github.com/prometheus/client_golang/prometheus
1213
- go get github.com/rcrowley/go-metrics/stathat
1314

1415
before_script:

main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ func main() {
156156
}()
157157
}
158158

159-
stats.Collect() // Graphite
160-
stats.Metrics() // Prometheus
159+
stats.Collect() // Graphite
160+
server.Metrics() // Prometheus
161161

162162
if err := s.Run(); err != nil {
163163
log.Fatalf("skydns: %s", err)

server/dnssec.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (s *server) Sign(m *dns.Msg, bufsize uint16) {
4848
expir := uint32(now.Add(7 * 24 * time.Hour).Unix()) // sign for a week
4949

5050
defer func() {
51-
PromSCacheSize.Set(float64(s.scache.Size()))
51+
promSCacheSize.Set(float64(s.scache.Size()))
5252
}()
5353

5454
for _, r := range rrSets(m.Answer) {
@@ -108,7 +108,7 @@ func (s *server) signSet(r []dns.RR, now time.Time, incep, expir uint32) (*dns.R
108108
log.Printf("skydns: scache miss for %s type %d", r[0].Header().Name, r[0].Header().Rrtype)
109109

110110
StatsDnssecCacheMiss.Inc(1)
111-
PromSCacheMiss.Inc()
111+
promSCacheMiss.Inc()
112112

113113
sig, err, shared := inflight.Do(key, func() (*dns.RRSIG, error) {
114114
sig1 := s.NewRRSIG(incep, expir)

server/forwarding.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
// ServeDNSForward forwards a request to a nameservers and returns the response.
1616
func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) {
1717
StatsForwardCount.Inc(1)
18-
PromForwardCount.Inc()
18+
promForwardCount.Inc()
1919

2020
if s.config.NoRec {
2121
m := new(dns.Msg)
@@ -105,7 +105,7 @@ func (s *server) ServeDNSReverse(w dns.ResponseWriter, req *dns.Msg) {
105105
// in the server's config. If none defined it returns an error
106106
func (s *server) Lookup(n string, t, bufsize uint16, dnssec bool) (*dns.Msg, error) {
107107
StatsLookupCount.Inc(1)
108-
PromLookupCount.Inc()
108+
promLookupCount.Inc()
109109

110110
if len(s.config.Nameservers) == 0 {
111111
return nil, fmt.Errorf("no nameservers configured can not lookup name")

server/server.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -202,20 +202,21 @@ func (s *server) ServeDNS(w dns.ResponseWriter, req *dns.Msg) {
202202
}
203203

204204
if tcp {
205-
PromRequestCountTCP.Inc()
205+
promRequestCount.WithLabelValues("tcp").Inc()
206206
} else {
207-
PromRequestCountUDP.Inc()
207+
promRequestCount.WithLabelValues("udp").Inc()
208208
}
209-
PromRequestCountTotal.Inc()
209+
promRequestCount.WithLabelValues("total").Inc()
210+
210211
StatsRequestCount.Inc(1)
211212

212213
if dnssec {
213214
StatsDnssecOkCount.Inc(1)
214-
PromDnssecOkCount.Inc()
215+
promDnssecOkCount.Inc()
215216
}
216217

217218
defer func() {
218-
PromRCacheSize.Set(float64(s.rcache.Size()))
219+
promRCacheSize.Set(float64(s.rcache.Size()))
219220
}()
220221

221222
// Check cache first.
@@ -252,7 +253,7 @@ func (s *server) ServeDNS(w dns.ResponseWriter, req *dns.Msg) {
252253
s.rcache.Remove(key)
253254
}
254255

255-
PromRCacheMiss.Inc()
256+
promRCacheMiss.Inc()
256257

257258
q := req.Question[0]
258259
name := strings.ToLower(q.Name)
@@ -780,7 +781,7 @@ func (s *server) NameError(m, req *dns.Msg) {
780781
m.Ns[0].Header().Ttl = s.config.MinTtl
781782

782783
StatsNameErrorCount.Inc(1)
783-
PromNameErrorCount.Inc()
784+
promNameErrorCount.Inc()
784785
}
785786

786787
func (s *server) NoDataError(m, req *dns.Msg) {
@@ -789,7 +790,7 @@ func (s *server) NoDataError(m, req *dns.Msg) {
789790
m.Ns[0].Header().Ttl = s.config.MinTtl
790791

791792
StatsNoDataCount.Inc(1)
792-
PromNoDataCount.Inc()
793+
promNoDataCount.Inc()
793794
}
794795

795796
func (s *server) logNoConnection(e error) {

server/server_test.go

-39
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ package server
88

99
import (
1010
"encoding/json"
11-
"io/ioutil"
12-
"net/http"
1311
"sort"
1412
"strconv"
1513
"strings"
@@ -19,7 +17,6 @@ import (
1917

2018
"github.com/coreos/go-etcd/etcd"
2119
"github.com/miekg/dns"
22-
"github.com/miekg/skydns/stats"
2320
backendetcd "github.com/skynetservices/skydns/backends/etcd"
2421
"github.com/skynetservices/skydns/cache"
2522
"github.com/skynetservices/skydns/msg"
@@ -1284,39 +1281,3 @@ func BenchmarkDNSSECSingleNoCache(b *testing.B) {
12841281
c.Exchange(m, "127.0.0.1:"+StrPort)
12851282
}
12861283
}
1287-
1288-
// Metric testing
1289-
1290-
func newMetricServer(t *testing.T) *server {
1291-
s := newTestServer(t, false)
1292-
1293-
stats.PrometheusPort = "12300"
1294-
stats.PrometheusNamespace = "test"
1295-
stats.Metrics()
1296-
return s
1297-
}
1298-
1299-
func query(n string, t uint16) {
1300-
// qeury the local server to get some metrics
1301-
m := new(dns.Msg)
1302-
m.SetQuestion(n, t)
1303-
dns.Exchange(m, "127.0.0.1:"+StrPort)
1304-
}
1305-
1306-
func scrape(t *testing.T, key string) {
1307-
resp, err := http.Get("http://localhost:12300/metrics")
1308-
if err != nil {
1309-
t.Fatal("could not get metrics")
1310-
}
1311-
1312-
body, _ := ioutil.ReadAll(resp.Body)
1313-
println(body)
1314-
}
1315-
1316-
func TestMetricRequests(t *testing.T) {
1317-
s := newMetricServer(t)
1318-
defer s.Stop()
1319-
1320-
query("miek.nl.", dns.TypeMX)
1321-
scrape(t, "dns_request_count_udp")
1322-
}

server/stats.go

+140-17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
package server
66

77
import (
8+
"log"
9+
"net/http"
10+
"os"
11+
"strconv"
12+
813
"github.com/prometheus/client_golang/prometheus"
914
)
1015

@@ -21,7 +26,7 @@ func (nopCounter) Inc(_ int64) {}
2126
// used by graphite.
2227
var (
2328
// Pondering deletion in favor of the better and more
24-
// maintained (by me) Prometheus reporting.
29+
// maintained (by me) prometheus reporting.
2530

2631
StatsForwardCount Counter = nopCounter{}
2732
StatsStubForwardCount Counter = nopCounter{}
@@ -34,21 +39,139 @@ var (
3439
StatsDnssecCacheMiss Counter = nopCounter{}
3540
)
3641

37-
// Prometheus counters and gauges
3842
var (
39-
PromForwardCount prometheus.Counter
40-
PromStubForwardCount prometheus.Counter
41-
PromLookupCount prometheus.Counter
42-
43-
PromRequestCountTotal prometheus.Counter
44-
PromRequestCountTCP prometheus.Counter
45-
PromRequestCountUDP prometheus.Counter
46-
47-
PromDnssecOkCount prometheus.Counter
48-
PromNameErrorCount prometheus.Counter
49-
PromNoDataCount prometheus.Counter
50-
PromRCacheSize prometheus.Gauge
51-
PromSCacheSize prometheus.Gauge
52-
PromRCacheMiss prometheus.Counter
53-
PromSCacheMiss prometheus.Counter
43+
prometheusPort = os.Getenv("PROMETHEUS_PORT")
44+
prometheusPath = os.Getenv("PROMETHEUS_PATH")
45+
prometheusNamespace = os.Getenv("PROMETHEUS_NAMESPACE")
46+
prometheusSubsystem = os.Getenv("PROMETHEUS_SUBSYSTEM")
47+
)
48+
49+
var (
50+
promForwardCount prometheus.Counter
51+
promStubForwardCount prometheus.Counter
52+
promLookupCount prometheus.Counter
53+
promRequestCount *prometheus.CounterVec
54+
promDnssecOkCount prometheus.Counter
55+
promNameErrorCount prometheus.Counter
56+
promNoDataCount prometheus.Counter
57+
promRCacheSize prometheus.Gauge
58+
promSCacheSize prometheus.Gauge
59+
promRCacheMiss prometheus.Counter
60+
promSCacheMiss prometheus.Counter
5461
)
62+
63+
func Metrics() {
64+
if prometheusPort == "" {
65+
return
66+
}
67+
68+
if prometheusPath == "" {
69+
prometheusPath = "/metrics"
70+
}
71+
if prometheusNamespace == "" {
72+
prometheusNamespace = "skydns"
73+
}
74+
75+
promForwardCount = prometheus.NewCounter(prometheus.CounterOpts{
76+
Namespace: prometheusNamespace,
77+
Subsystem: prometheusSubsystem,
78+
Name: "dns_forward_count",
79+
Help: "Counter of DNS requests forwarded.",
80+
})
81+
82+
promStubForwardCount = prometheus.NewCounter(prometheus.CounterOpts{
83+
Namespace: prometheusNamespace,
84+
Subsystem: prometheusSubsystem,
85+
Name: "dns_stub_forward_count",
86+
Help: "Counter of DNS requests forwarded to stubs.",
87+
})
88+
89+
// convert to VEC and use labels
90+
promLookupCount = prometheus.NewCounter(prometheus.CounterOpts{
91+
Namespace: prometheusNamespace,
92+
Subsystem: prometheusSubsystem,
93+
Name: "dns_lookup_count",
94+
Help: "Counter of DNS lookups performed.",
95+
})
96+
97+
promRequestCount = prometheus.NewCounterVec(prometheus.CounterOpts{
98+
Namespace: prometheusNamespace,
99+
Subsystem: prometheusSubsystem,
100+
Name: "dns_request_count",
101+
Help: "Counter of total DNS requests made.",
102+
}, []string{"type"}, // total, udp, tcp
103+
)
104+
prometheus.MustRegister(promRequestCount)
105+
106+
promDnssecOkCount = prometheus.NewCounter(prometheus.CounterOpts{
107+
Namespace: prometheusNamespace,
108+
Subsystem: prometheusSubsystem,
109+
Name: "dns_dnssec_ok_count",
110+
Help: "Counter of DNSSEC requests.",
111+
})
112+
113+
promNameErrorCount = prometheus.NewCounter(prometheus.CounterOpts{
114+
Namespace: prometheusNamespace,
115+
Subsystem: prometheusSubsystem,
116+
Name: "dns_name_error_count",
117+
Help: "Counter of DNS requests resulting in a name error.",
118+
})
119+
120+
promNoDataCount = prometheus.NewCounter(prometheus.CounterOpts{
121+
Namespace: prometheusNamespace,
122+
Subsystem: prometheusSubsystem,
123+
Name: "dns_no_data_count",
124+
Help: "Counter of DNS requests that contained no data.",
125+
})
126+
127+
// Caches
128+
promRCacheSize = prometheus.NewGauge(prometheus.GaugeOpts{
129+
Namespace: prometheusNamespace,
130+
Subsystem: prometheusSubsystem,
131+
Name: "rcache_total_size",
132+
Help: "The total size of all DNS messages in the rcache.",
133+
})
134+
135+
promSCacheSize = prometheus.NewGauge(prometheus.GaugeOpts{
136+
Namespace: prometheusNamespace,
137+
Subsystem: prometheusSubsystem,
138+
Name: "scache_total_size",
139+
Help: "The total size of all RRSIGs in the scache.",
140+
})
141+
142+
promRCacheMiss = prometheus.NewCounter(prometheus.CounterOpts{
143+
Namespace: prometheusNamespace,
144+
Subsystem: prometheusSubsystem,
145+
Name: "dns_rcache_miss_count",
146+
Help: "Counter of DNS requests that result in cache miss.",
147+
})
148+
149+
promSCacheMiss = prometheus.NewCounter(prometheus.CounterOpts{
150+
Namespace: prometheusNamespace,
151+
Subsystem: prometheusSubsystem,
152+
Name: "dns_scache_miss_count",
153+
Help: "Counter of signature requests that result in cache miss.",
154+
})
155+
156+
prometheus.MustRegister(promForwardCount)
157+
prometheus.MustRegister(promStubForwardCount)
158+
prometheus.MustRegister(promLookupCount)
159+
160+
prometheus.MustRegister(promDnssecOkCount)
161+
prometheus.MustRegister(promNameErrorCount)
162+
prometheus.MustRegister(promNoDataCount)
163+
prometheus.MustRegister(promRCacheSize)
164+
prometheus.MustRegister(promSCacheSize)
165+
prometheus.MustRegister(promRCacheMiss)
166+
prometheus.MustRegister(promSCacheMiss)
167+
168+
_, err := strconv.Atoi(prometheusPort)
169+
if err != nil {
170+
return
171+
}
172+
173+
http.Handle(prometheusPath, prometheus.Handler())
174+
go func() {
175+
log.Fatalf("skydns: %s", http.ListenAndServe(":"+prometheusPort, nil))
176+
}()
177+
}

server/stub.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (s *server) UpdateStubZones() {
7070
// ServeDNSStubForward forwards a request to a nameservers and returns the response.
7171
func (s *server) ServeDNSStubForward(w dns.ResponseWriter, req *dns.Msg, ns []string) {
7272
StatsStubForwardCount.Inc(1)
73-
PromStubForwardCount.Inc()
73+
promStubForwardCount.Inc()
7474

7575
// Check EDNS0 Stub option, if set drop the packet.
7676
option := req.IsEdns0()

0 commit comments

Comments
 (0)