@@ -2,9 +2,11 @@ package main
22
33import (
44 "flag"
5+ "fmt"
56 "log"
67 "os"
78 "os/signal"
9+ "sort"
810 "syscall"
911 "time"
1012)
@@ -22,6 +24,7 @@ func main() {
2224 clearErrors := flag .String ("clear-errors" , "" , "Clear all errors for a resolver (mark as successful) and exit" )
2325 hideLatency := flag .Bool ("hide-latency" , false , "Hide latency column in web interface" )
2426 minReliability := flag .Float64 ("min-reliability" , - 1 , "Remove resolvers with reliability below this percentage and exit" )
27+ showFailures := flag .Bool ("failures" , false , "Print failing resolvers/relays with their error messages and exit" )
2528 flag .Parse ()
2629
2730 log .SetFlags (log .LstdFlags | log .Lshortfile )
@@ -78,6 +81,23 @@ func main() {
7881 return
7982 }
8083
84+ // Handle showing failures
85+ if * showFailures {
86+ stats , err := db .GetAllStats ()
87+ if err != nil {
88+ log .Fatalf ("Failed to get stats: %v" , err )
89+ }
90+ failures := filterFailures (stats )
91+ if len (failures ) == 0 {
92+ log .Println ("No failing resolvers/relays" )
93+ return
94+ }
95+ for _ , s := range failures {
96+ fmt .Printf ("%s (%s): %s\n " , s .Name , s .Type , s .LastError )
97+ }
98+ return
99+ }
100+
81101 // Auto-rebuild if resolver_stats is empty but test_results has data
82102 if err := db .RebuildStatsIfNeeded (); err != nil {
83103 log .Printf ("Warning: failed to check/rebuild stats: %v" , err )
@@ -150,3 +170,28 @@ func main() {
150170 }
151171 }
152172}
173+
174+ // filterFailures returns resolvers where the last test failed.
175+ // A resolver is considered failing if it has a LastFail time that is
176+ // more recent than LastSuccess (or if it has never succeeded).
177+ func filterFailures (stats []ResolverStats ) []ResolverStats {
178+ var failures []ResolverStats
179+ for _ , s := range stats {
180+ if s .LastError == "" {
181+ continue
182+ }
183+ // Consider it failing if last_fail > last_success
184+ if s .LastFail != nil {
185+ if s .LastSuccess == nil || s .LastFail .After (* s .LastSuccess ) {
186+ failures = append (failures , s )
187+ }
188+ }
189+ }
190+ sort .Slice (failures , func (i , j int ) bool {
191+ if failures [i ].Type != failures [j ].Type {
192+ return failures [i ].Type < failures [j ].Type
193+ }
194+ return failures [i ].Name < failures [j ].Name
195+ })
196+ return failures
197+ }
0 commit comments