Add comprehensive logging and debug endpoints for production troubleshooting

- Add request logging middleware to main.go
- Add debug handler with health, config, stats, and test-dns endpoints
- Add detailed logging to DynDNS handler
- Add logging to Technitium DNS client
- Add database Ping() and GetStats() methods
- New endpoints:
  - /health - detailed health status with database and DNS checks
  - /debug/config - sanitized configuration
  - /debug/stats - database statistics
  - /debug/test-dns - live DNS test endpoint

This will help diagnose production issues with DNS updates.
This commit is contained in:
2026-02-02 22:14:24 -05:00
parent ad494fa623
commit 01694f66a8
5 changed files with 266 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ package handlers
import (
"context"
"encoding/base64"
"log"
"net"
"net/http"
"strings"
@@ -170,14 +171,19 @@ func NewDynDNSHandler(db *database.DB, dnsClient *dns.Client, cfg *config.Config
func (h *DynDNSHandler) Update(c *gin.Context) {
token, err := extractBasicAuthPassword(c)
if err != nil {
log.Printf("[DynDNS] Auth extraction error: %v", err)
c.String(http.StatusUnauthorized, "badauth")
return
}
hostname := c.Query("hostname")
myip := c.Query("myip")
clientIP := c.ClientIP()
log.Printf("[DynDNS] Update request from %s: hostname=%s, myip=%s", clientIP, hostname, myip)
if hostname == "" {
log.Printf("[DynDNS] Error: hostname missing")
c.String(http.StatusBadRequest, "nohost")
return
}
@@ -187,54 +193,67 @@ func (h *DynDNSHandler) Update(c *gin.Context) {
space, err := h.db.GetSpaceByToken(ctx, token)
if err != nil {
log.Printf("[DynDNS] Database error getting space: %v", err)
c.String(http.StatusServiceUnavailable, "911")
return
}
if space == nil {
log.Printf("[DynDNS] Invalid token provided")
c.String(http.StatusUnauthorized, "badauth")
return
}
expectedFQDN := space.GetFQDN(h.config.GetZone())
if hostname != expectedFQDN {
log.Printf("[DynDNS] Hostname mismatch: expected %s, got %s", expectedFQDN, hostname)
c.String(http.StatusBadRequest, "nohost")
return
}
if myip == "" {
myip = c.ClientIP()
log.Printf("[DynDNS] Using client IP: %s", myip)
}
if net.ParseIP(myip) == nil {
log.Printf("[DynDNS] Invalid IP format: %s", myip)
c.String(http.StatusBadRequest, "dnserr")
return
}
zone := h.config.GetZone()
log.Printf("[DynDNS] Updating DNS: zone=%s, subdomain=%s, ip=%s", zone, space.Subdomain, myip)
err = h.dns.AddARecord(zone, space.Subdomain, myip, 300)
if err != nil {
log.Printf("[DynDNS] Failed to add A record: %v", err)
c.String(http.StatusServiceUnavailable, "911")
return
}
log.Printf("[DynDNS] A record added successfully")
err = h.dns.AddWildcardARecord(zone, space.Subdomain, myip, 300)
if err != nil {
log.Printf("[DynDNS] Failed to add wildcard A record: %v", err)
c.String(http.StatusServiceUnavailable, "911")
return
}
log.Printf("[DynDNS] Wildcard A record added successfully")
if space.LastIP == myip {
log.Printf("[DynDNS] IP unchanged: %s", myip)
c.String(http.StatusOK, "nochg %s", myip)
return
}
err = h.db.UpdateSpaceIP(ctx, token, myip)
if err != nil {
log.Printf("[DynDNS] Failed to update space IP in database: %v", err)
c.String(http.StatusServiceUnavailable, "911")
return
}
log.Printf("[DynDNS] Update successful: %s -> %s", hostname, myip)
c.String(http.StatusOK, "good %s", myip)
}