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  }