dnsd: serve prometheus metrics on port 8053
This commit is contained in:
parent
0e6add220c
commit
24e2d5de00
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user