package main import ( "flag" "fmt" "github.com/fluepke/vodafone-station-exporter/collector" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/promslog" stdlog "log" "log/slog" "net/http" "os" "reflect" "strings" ) const version = "0.0.1" var logger *slog.Logger type slogWriter struct{} func (s *slogWriter) Write(p []byte) (n int, err error) { logger.Error("promhttp error", slog.String("err", string(p))) return len(p), nil } var ( showVersion = flag.Bool("version", false, "Print version and exit") showMetrics = flag.Bool("show-metrics", false, "Show available metrics and exit") listenAddress = flag.String("web.listen-address", "[::]:9420", "Address to listen on") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics") vodafoneStationUrl = flag.String("vodafone.station-url", "http://192.168.0.1", "Vodafone station URL. For bridge mode this is 192.168.100.1 (note: Configure a route if using bridge mode)") vodafoneStationPassword = flag.String("vodafone.station-password", "How is the default password calculated? mhmm", "Password for logging into the Vodafone station") vodafoneStationPasswordFile = flag.String("vodafone.station-password-file", "", "Path to a file containing the Vodafone station password (overrides -vodafone.station-password)") ) func main() { flag.Parse() cfg := &promslog.Config{} logger = promslog.New(cfg) // Handle password from file if provided if *vodafoneStationPasswordFile != "" { data, err := os.ReadFile(*vodafoneStationPasswordFile) if err != nil { logger.Error("Failed to read password file", slog.String("err", err.Error())) os.Exit(2) } pw := string(data) pw = strings.TrimSpace(pw) vodafoneStationPassword = &pw } if *showMetrics { describeMetrics() os.Exit(0) } if *showVersion { fmt.Println("vodafone-station-exporter") fmt.Printf("Version: %s\n", version) fmt.Println("Author: @fluepke") fmt.Println("Prometheus Exporter for the Vodafone Station (CGA4233DE)") os.Exit(0) } startServer() } func describeMetrics() { fmt.Println("Exported metrics") c := &collector.Collector{} ch := make(chan *prometheus.Desc) go func() { defer close(ch) c.Describe(ch) }() for desc := range ch { if desc == nil { continue } describeMetric(desc) } } func describeMetric(desc *prometheus.Desc) { fqName := reflect.ValueOf(desc).Elem().FieldByName("fqName").String() help := reflect.ValueOf(desc).Elem().FieldByName("help").String() labels := reflect.ValueOf(desc).Elem().FieldByName("variableLabels") fmt.Println(" * `" + fqName + "`: " + help) if labels.Len() == 0 { return } fmt.Print(" - Labels: ") first := true for i := 0; i < labels.Len(); i++ { if !first { fmt.Print(", ") } first = false fmt.Print("`" + labels.Index(i).String() + "`") } fmt.Println("") } func startServer() { logger.Info("Starting vodafone-station-exporter", slog.String("version", version)) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`