github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/aagent/watchers/nagioswatcher/prometheus.go (about) 1 // Copyright (c) 2020-2022, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package nagioswatcher 6 7 import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 "sync" 12 "time" 13 14 "github.com/choria-io/go-choria/internal/util" 15 ) 16 17 var promStates map[string]State 18 var promTimes map[string]time.Time 19 var promChecks map[string]int 20 var startTime int64 21 22 var mu sync.Mutex 23 24 func init() { 25 mu.Lock() 26 promTimes = make(map[string]time.Time) 27 promStates = make(map[string]State) 28 promChecks = make(map[string]int) 29 startTime = time.Now().Unix() 30 mu.Unlock() 31 } 32 33 type logger interface { 34 Debugf(format string, args ...any) 35 } 36 37 func updatePromState(name string, state State, dir string, log logger) error { 38 mu.Lock() 39 defer mu.Unlock() 40 41 promStates[name] = state 42 promTimes[name] = time.Now() 43 44 _, ok := promChecks[name] 45 if !ok { 46 promChecks[name] = 0 47 } 48 promChecks[name]++ 49 50 return savePromState(dir, log) 51 } 52 53 func deletePromState(name string, dir string, log logger) error { 54 mu.Lock() 55 defer mu.Unlock() 56 57 delete(promStates, name) 58 delete(promTimes, name) 59 delete(promChecks, name) 60 61 return savePromState(dir, log) 62 } 63 64 // locks held by callers 65 func savePromState(td string, log logger) error { 66 if td == "" { 67 log.Debugf("Not updating prometheus - text file directory is unset") 68 return nil 69 } 70 71 if !util.FileIsDir(td) { 72 log.Debugf("%q is not a directory", td) 73 return nil 74 } 75 76 tfile, err := os.CreateTemp(td, "") 77 if err != nil { 78 return fmt.Errorf("failed to create prometheus metric in %q: %s", td, err) 79 } 80 81 fmt.Fprintf(tfile, "# HELP choria_machine_nagios_start_time Time the Choria Machine subsystem started in unix seconds\n") 82 fmt.Fprintf(tfile, "# TYPE choria_machine_nagios_start_time gauge\n") 83 fmt.Fprintf(tfile, "choria_machine_nagios_start_time %d\n", startTime) 84 85 fmt.Fprintf(tfile, "# HELP choria_machine_nagios_watcher_status Choria Nagios Check Status\n") 86 fmt.Fprintf(tfile, "# TYPE choria_machine_nagios_watcher_status gauge\n") 87 for name, s := range promStates { 88 if s == UNKNOWN || s == OK || s == CRITICAL || s == WARNING { 89 fmt.Fprintf(tfile, "choria_machine_nagios_watcher_status{name=%q,status=%q} %d\n", name, stateNames[s], int(s)) 90 } 91 } 92 93 fmt.Fprintf(tfile, "# HELP choria_machine_nagios_watcher_last_run_seconds Choria Nagios Check Time\n") 94 fmt.Fprintf(tfile, "# TYPE choria_machine_nagios_watcher_last_run_seconds gauge\n") 95 for name, t := range promTimes { 96 fmt.Fprintf(tfile, "choria_machine_nagios_watcher_last_run_seconds{name=%q} %d\n", name, t.Unix()) 97 } 98 99 fmt.Fprintf(tfile, "# HELP choria_machine_nagios_watcher_checks_count Choria Nagios Check Count\n") 100 fmt.Fprintf(tfile, "# TYPE choria_machine_nagios_watcher_checks_count counter\n") 101 for name, c := range promChecks { 102 fmt.Fprintf(tfile, "choria_machine_nagios_watcher_checks_count{name=%q} %d\n", name, c) 103 } 104 105 tfile.Close() 106 os.Chmod(tfile.Name(), 0644) 107 return os.Rename(tfile.Name(), filepath.Join(td, "choria_machine_nagios_watcher_status.prom")) 108 }