From 815adacbb179eb9a1705546cd85fbe5c8968ab47 Mon Sep 17 00:00:00 2001 From: Peter Oettig Date: Sat, 5 Apr 2025 01:53:41 +0200 Subject: [PATCH] Fix that exporter metrics were never exposed --- main.go | 2 +- pkg/collector/channel.go | 23 ++++++++++++----------- pkg/collector/exporterMetrics.go | 6 ++++++ pkg/collector/serverinfo.go | 4 ++-- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/main.go b/main.go index 8aa657d..6907b1b 100644 --- a/main.go +++ b/main.go @@ -37,7 +37,7 @@ func main() { seq = append(seq, cInfo) } - prometheus.MustRegister(append(seq, collector.NewClient(c))) + prometheus.MustRegister(append(seq, collector.NewClient(c), internalMetrics)) // The Handler function provides a default handler to expose metrics // via an HTTP server. "/metrics" is the usual endpoint for that. http.Handle("/metrics", promhttp.Handler()) diff --git a/pkg/collector/channel.go b/pkg/collector/channel.go index 20cf5ba..60e275f 100644 --- a/pkg/collector/channel.go +++ b/pkg/collector/channel.go @@ -1,10 +1,10 @@ package collector import ( - "log" "fmt" "github.com/hikhvar/ts3exporter/pkg/serverquery" "github.com/prometheus/client_golang/prometheus" + "log" ) const channelSubsystem = "channel" @@ -28,6 +28,7 @@ type Channel struct { } func NewChannel(executor serverquery.Executor, internalMetrics *ExporterMetrics) *Channel { + internalMetrics.Init(channelSubsystem) return &Channel{ executor: executor, internalMetrics: internalMetrics, @@ -55,15 +56,15 @@ func (c *Channel) Collect(met chan<- prometheus.Metric) { log.Printf("failed to refresh channel view: %v", err) } for _, ch := range channels.All() { - met <- prometheus.MustNewConstMetric(c.ClientsOnline, prometheus.GaugeValue, float64(ch.ClientsOnline), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.MaxClients, prometheus.GaugeValue, float64(ch.MaxClients), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.Codec, prometheus.GaugeValue, float64(ch.Codec), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.CodecQuality, prometheus.GaugeValue, float64(ch.CodecQuality), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.LatencyFactor, prometheus.GaugeValue, float64(ch.LatencyFactor), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.Unencrypted, prometheus.GaugeValue, float64(ch.Unencrypted), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.Permanent, prometheus.GaugeValue, float64(ch.Permanent), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.SemiPermanent, prometheus.GaugeValue, float64(ch.SemiPermanent), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.Default, prometheus.GaugeValue, float64(ch.Default), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) - met <- prometheus.MustNewConstMetric(c.Password, prometheus.GaugeValue, float64(ch.Password), ch.HostingServer.Name, fmt.Sprintf("%d",ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.ClientsOnline, prometheus.GaugeValue, float64(ch.ClientsOnline), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.MaxClients, prometheus.GaugeValue, float64(ch.MaxClients), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.Codec, prometheus.GaugeValue, float64(ch.Codec), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.CodecQuality, prometheus.GaugeValue, float64(ch.CodecQuality), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.LatencyFactor, prometheus.GaugeValue, float64(ch.LatencyFactor), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.Unencrypted, prometheus.GaugeValue, float64(ch.Unencrypted), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.Permanent, prometheus.GaugeValue, float64(ch.Permanent), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.SemiPermanent, prometheus.GaugeValue, float64(ch.SemiPermanent), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.Default, prometheus.GaugeValue, float64(ch.Default), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) + met <- prometheus.MustNewConstMetric(c.Password, prometheus.GaugeValue, float64(ch.Password), ch.HostingServer.Name, fmt.Sprintf("%d", ch.ID), ch.Name) } } diff --git a/pkg/collector/exporterMetrics.go b/pkg/collector/exporterMetrics.go index 5c80ec3..297fb99 100644 --- a/pkg/collector/exporterMetrics.go +++ b/pkg/collector/exporterMetrics.go @@ -18,6 +18,11 @@ func NewExporterMetrics() *ExporterMetrics { } } +// Init initializes the metrics given a collector label to make sure that they appear even though they might be never updated +func (i *ExporterMetrics) Init(collector string) { + i.refreshErrors.WithLabelValues(collector) +} + // RefreshError increases the refresh error counter of the given collector by one. func (i *ExporterMetrics) RefreshError(collector string) { i.refreshErrors.WithLabelValues(collector).Inc() @@ -28,5 +33,6 @@ func (i *ExporterMetrics) Describe(descs chan<- *prometheus.Desc) { } func (i *ExporterMetrics) Collect(metrics chan<- prometheus.Metric) { + // Ensure that the metric is always initialized i.refreshErrors.Collect(metrics) } diff --git a/pkg/collector/serverinfo.go b/pkg/collector/serverinfo.go index e7dda95..24e3c49 100644 --- a/pkg/collector/serverinfo.go +++ b/pkg/collector/serverinfo.go @@ -1,10 +1,9 @@ package collector import ( - "log" - "github.com/hikhvar/ts3exporter/pkg/serverquery" "github.com/prometheus/client_golang/prometheus" + "log" ) const serverInfoSubsystem = "serverinfo" @@ -43,6 +42,7 @@ type ServerInfo struct { } func NewServerInfo(executor serverquery.Executor, internalMetrics *ExporterMetrics) *ServerInfo { + internalMetrics.Init(serverInfoSubsystem) return &ServerInfo{ executor: executor, internalMetrics: internalMetrics,