dnsd: serve prometheus metrics on port 8053

This commit is contained in:
Michael Stapelberg 2018-06-18 08:04:56 +02:00
parent 0e6add220c
commit 24e2d5de00
3 changed files with 50 additions and 4 deletions

View File

@ -6,15 +6,33 @@ import (
"flag" "flag"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/gokrazy/gokrazy"
"router7/internal/dhcp4d" "router7/internal/dhcp4d"
"router7/internal/dns" "router7/internal/dns"
"router7/internal/multilisten"
"router7/internal/netconfig" "router7/internal/netconfig"
_ "net/http/pprof"
) )
func updateListeners() error {
hosts, err := gokrazy.PrivateInterfaceAddrs()
if err != nil {
return err
}
if net1, err := multilisten.IPv6Net1("/perm"); err == nil {
hosts = append(hosts, net1)
}
return multilisten.ListenAndServe(hosts, "8053", http.DefaultServeMux)
}
func logic() error { func logic() error {
// TODO: set correct upstream DNS resolver(s) // TODO: set correct upstream DNS resolver(s)
ip, err := netconfig.LinkAddress("/perm", "lan0") ip, err := netconfig.LinkAddress("/perm", "lan0")
@ -37,10 +55,15 @@ func logic() error {
if err := readLeases(); err != nil { if err := readLeases(); err != nil {
log.Printf("cannot resolve DHCP hostnames: %v", err) log.Printf("cannot resolve DHCP hostnames: %v", err)
} }
http.Handle("/metrics", srv.PrometheusHandler())
updateListeners()
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGUSR1) signal.Notify(ch, syscall.SIGUSR1)
go func() { go func() {
for range ch { for range ch {
if err := updateListeners(); err != nil {
log.Printf("updateListeners: %v", err)
}
if err := readLeases(); err != nil { if err := readLeases(); err != nil {
log.Printf("readLeases: %v", err) log.Printf("readLeases: %v", err)
} }

View File

@ -3,6 +3,7 @@ package dns
import ( import (
"log" "log"
"net" "net"
"net/http"
"os" "os"
"strings" "strings"
"sync" "sync"
@ -10,9 +11,10 @@ import (
"router7/internal/dhcp4d" "router7/internal/dhcp4d"
"golang.org/x/time/rate"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/time/rate"
) )
type Server struct { type Server struct {
@ -21,6 +23,10 @@ type Server struct {
domain string domain string
upstream string upstream string
sometimes *rate.Limiter sometimes *rate.Limiter
prom struct {
registry *prometheus.Registry
queries prometheus.Counter
}
mu sync.Mutex mu sync.Mutex
hostname, ip string hostname, ip string
@ -40,6 +46,13 @@ func NewServer(addr, domain string) *Server {
hostname: hostname, hostname: hostname,
ip: ip, ip: ip,
} }
server.prom.registry = prometheus.NewRegistry()
server.prom.queries = prometheus.NewCounter(prometheus.CounterOpts{
Name: "dns_queries",
Help: "Number of DNS queries received",
})
server.prom.registry.MustRegister(server.prom.queries)
server.prom.registry.MustRegister(prometheus.NewGoCollector())
server.initHostsLocked() server.initHostsLocked()
dns.HandleFunc(".", server.handleRequest) dns.HandleFunc(".", server.handleRequest)
return server return server
@ -68,6 +81,10 @@ func (s *Server) hostByIP(n string) (string, bool) {
return r, ok return r, ok
} }
func (s *Server) PrometheusHandler() http.Handler {
return promhttp.HandlerFor(s.prom.registry, promhttp.HandlerOpts{})
}
func (s *Server) SetLeases(leases []dhcp4d.Lease) { func (s *Server) SetLeases(leases []dhcp4d.Lease) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
@ -126,6 +143,7 @@ func isLocalInAddrArpa(q string) bool {
// TODO: require search domains to be present, then use HandleFunc("lan.", internalName) // TODO: require search domains to be present, then use HandleFunc("lan.", internalName)
func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) { func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
s.prom.queries.Inc()
if len(r.Question) == 1 { // TODO: answer all questions we can answer if len(r.Question) == 1 { // TODO: answer all questions we can answer
q := r.Question[0] q := r.Question[0]
if q.Qtype == dns.TypeA && q.Qclass == dns.ClassINET { if q.Qtype == dns.TypeA && q.Qclass == dns.ClassINET {

View File

@ -547,8 +547,13 @@ func Apply(dir, root string) error {
} }
} }
if err := notify.Process("/user/dyndns", syscall.SIGUSR1); err != nil { for _, process := range []string{
log.Printf("notifying dyndns: %v", err) "dyndns", // depends on the public IPv4 address
"dnsd", // listens on private IPv4/IPv6 and public IPv6Net1
} {
if err := notify.Process("/user/"+process, syscall.SIGUSR1); err != nil {
log.Printf("notifying %s: %v", process, err)
}
} }
if err := applySysctl(); err != nil { if err := applySysctl(); err != nil {