a recursive dns resolver
at main 1.7 kB view raw
1package metrics 2 3import ( 4 "context" 5 "fmt" 6 "log/slog" 7 "os" 8 "sync" 9 "time" 10 11 "tangled.sh/seiso.moe/alky/pkg/dns" 12) 13 14var ( 15 instanceID string 16 initOnce sync.Once 17 version string 18) 19 20func initializeInstanceID() { 21 hostname, err := os.Hostname() 22 if err != nil { 23 hostname = "unknown-host" 24 } 25 26 if version != "" { 27 instanceID = fmt.Sprintf("%s-%s", hostname, version) 28 } else { 29 instanceID = fmt.Sprintf("%s-dev", hostname) 30 } 31} 32 33func MetricsMiddleware(metrics *ClickHouseMetrics) func(dns.Handler) dns.Handler { 34 if metrics == nil { 35 slog := slog.Default() 36 slog.Warn("Metrics client is nil, metrics middleware will be a no-op") 37 return func(next dns.Handler) dns.Handler { 38 return next 39 } 40 } 41 42 instanceID := GetInstanceID() 43 44 return func(next dns.Handler) dns.Handler { 45 return dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Request) { 46 if r.Context == nil { 47 r.Context = context.Background() 48 } 49 50 start := time.Now() 51 next.ServeDNS(w, r) 52 duration := time.Since(start) 53 54 if r.Message != nil && len(r.Message.Question) > 0 { 55 question := r.Message.Question[0] 56 57 metrics.RecordQuery(QueryMetric{ 58 Timestamp: start, 59 InstanceID: instanceID, 60 QueryName: question.QName, 61 QueryType: question.QType.String(), 62 QueryClass: question.QClass.String(), 63 RemoteAddr: r.RemoteAddr.String(), 64 ResponseCode: r.Message.Header.RCode.String(), 65 Duration: duration.Nanoseconds(), 66 }) 67 } else { 68 slog := slog.Default() 69 slog.Warn("Metrics middleware received request with missing message or question", "remote_addr", r.RemoteAddr) 70 } 71 }) 72 } 73} 74 75func GetInstanceID() string { 76 initOnce.Do(initializeInstanceID) 77 return instanceID 78}