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

@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"
@@ -91,6 +92,7 @@ func (c *Client) AddWildcardARecord(zone, hostname, ip string, ttl int) error {
func (c *Client) addRecord(req AddRecordRequest) error {
endpoint := fmt.Sprintf("%s/api/dns/records/add", c.baseURL)
log.Printf("[DNS] Adding record: domain=%s, type=%s, ip=%s", req.Domain, req.Type, req.IPAddress)
formData := url.Values{}
formData.Set("domain", req.Domain)
@@ -103,6 +105,7 @@ func (c *Client) addRecord(req AddRecordRequest) error {
httpReq, err := http.NewRequest("POST", endpoint, bytes.NewBufferString(formData.Encode()))
if err != nil {
log.Printf("[DNS] Failed to create request: %v", err)
return fmt.Errorf("failed to create request: %w", err)
}
@@ -110,37 +113,50 @@ func (c *Client) addRecord(req AddRecordRequest) error {
if c.token != "" {
httpReq.Header.Set("Authorization", "Basic "+c.token)
log.Printf("[DNS] Using token auth")
} else if c.username != "" && c.password != "" {
httpReq.SetBasicAuth(c.username, c.password)
log.Printf("[DNS] Using basic auth (username: %s)", c.username)
} else {
log.Printf("[DNS] Warning: No authentication configured!")
}
log.Printf("[DNS] Sending request to %s", endpoint)
resp, err := c.httpClient.Do(httpReq)
if err != nil {
log.Printf("[DNS] Request failed: %v", err)
return fmt.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("[DNS] Failed to read response: %v", err)
return fmt.Errorf("failed to read response body: %w", err)
}
log.Printf("[DNS] Response status: %d, body: %s", resp.StatusCode, string(body))
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("HTTP error %d: %s", resp.StatusCode, string(body))
}
var apiResp APIResponse
if err := json.Unmarshal(body, &apiResp); err != nil {
log.Printf("[DNS] Failed to parse response: %v", err)
return fmt.Errorf("failed to parse response: %w", err)
}
if apiResp.Status != "ok" {
if apiResp.Error != nil {
log.Printf("[DNS] API error: %s - %s", apiResp.Error.Code, apiResp.Error.Message)
return fmt.Errorf("API error: %s - %s", apiResp.Error.Code, apiResp.Error.Message)
}
log.Printf("[DNS] API error: status not ok")
return fmt.Errorf("API error: status not ok")
}
log.Printf("[DNS] Record added successfully")
return nil
}