1
Files
2023-11-14 10:48:39 +01:00

124 lines
2.8 KiB
Go

package main
import (
"bufio"
"flag"
"fmt"
"log"
"net"
"net/http"
"os"
"os/exec"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
latency = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "script_latency_seconds",
Help: "Latency of scripts.",
},
[]string{"script"},
)
addr = flag.String("a", "0.0.0.0", "address to use")
port = flag.String("p", "9063", "port to run on")
inter = flag.Int("i", 30, "time interval in seconds between two checks")
debug = flag.Bool("d", false, "enable debug logs")
config = flag.String("c", "scripts.conf", "config file path")
scripts []string
)
func init() {
prometheus.MustRegister(latency)
}
func main() {
flag.Parse()
err := loadConfig(*config)
if err != nil {
log.Fatal("ERROR: Failed to load config file, error:", err)
return
}
if len(scripts) == 0 {
log.Fatal("ERROR: Failed to load scripts")
return
}
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
fmt.Fprintln(w, "Prometheus Latency Exporter: <a href='/metrics'>Metrics</a>")
})
go func() {
for {
checkLatency()
time.Sleep(time.Duration(*inter) * time.Second)
}
}()
log.Println("INFO: Starting server on address:", *addr, "port:", *port)
err = http.ListenAndServe(net.JoinHostPort(*addr, *port), nil)
if err != nil {
log.Fatal("ERROR: Failed to start server, error: ", err)
return
}
}
func loadConfig(config string) error {
file, err := os.Open(config)
if err != nil {
return fmt.Errorf("can't open config file: %w", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if len(scanner.Text()) == 0 || scanner.Text()[0] == '#' {
continue
}
scripts = append(scripts, scanner.Text())
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("can't read config file: %w", err)
}
if len(scripts) == 0 {
return fmt.Errorf("no scripts found in config file")
}
log.Println(scripts)
return nil
}
func checkLatency() {
for _, script := range scripts {
duration, err := executePHPScript(script)
if err != nil {
log.Println("ERROR: PHP script returned an error:", err)
continue
}
latency.With(prometheus.Labels{"script": script}).Set(duration.Seconds())
if *debug == true {
log.Printf("DEBUG: Latency script %s: %v seconds", script, duration.Seconds())
}
}
}
func executePHPScript(scriptPath string) (time.Duration, error) {
start := time.Now()
cmd := exec.Command("php", scriptPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return 0, fmt.Errorf("failed to execute PHP script: %w", err)
}
duration := time.Since(start)
return duration, nil
}