aboutsummaryrefslogtreecommitdiff
path: root/internal/metrics
diff options
context:
space:
mode:
Diffstat (limited to 'internal/metrics')
-rw-r--r--internal/metrics/metrics.go114
1 files changed, 114 insertions, 0 deletions
diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go
new file mode 100644
index 0000000..aae46cd
--- /dev/null
+++ b/internal/metrics/metrics.go
@@ -0,0 +1,114 @@
+package metrics
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "rgdd.se/silentct/internal/monitor"
+ "rgdd.se/silentct/pkg/storage/index"
+)
+
+type Metrics struct {
+ errorCounter prometheus.Counter
+ logIndex *prometheus.GaugeVec
+ logSize *prometheus.GaugeVec
+ logTimestamp *prometheus.GaugeVec
+ needRestart prometheus.Gauge
+ unexpectedCertificateCount *prometheus.GaugeVec
+}
+
+func NewMetrics(registry *prometheus.Registry) *Metrics {
+ m := &Metrics{
+ errorCounter: prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "silentct_error_counter",
+ Help: "The number of errors propagated to the main loop.",
+ },
+ ),
+ logIndex: prometheus.NewGaugeVec(
+ prometheus.GaugeOpts{
+ Name: "silentct_log_index",
+ Help: "The next log entry to be downloaded.",
+ },
+ []string{"log_id", "log_name"},
+ ),
+ logSize: prometheus.NewGaugeVec(
+ prometheus.GaugeOpts{
+ Name: "silentct_log_size",
+ Help: "The number of entries in the log.",
+ },
+ []string{"log_id", "log_name"},
+ ),
+ logTimestamp: prometheus.NewGaugeVec(
+ prometheus.GaugeOpts{
+ Name: "silentct_log_timestamp",
+ Help: "The log's UNIX timestamp in ms.",
+ },
+ []string{"log_id", "log_name"},
+ ),
+ needRestart: prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Name: "silentct_need_restart",
+ Help: "A non-zero value if the monitor needs restarting.",
+ },
+ ),
+ unexpectedCertificateCount: prometheus.NewGaugeVec(
+ prometheus.GaugeOpts{
+ Name: "silentct_unexpected_certificate_count",
+ Help: "Number of certificates without any allowlisting",
+ },
+ []string{"log_id", "log_name", "log_index", "crt_sans"},
+ ),
+ }
+ registry.MustRegister(
+ m.errorCounter,
+ m.logIndex,
+ m.logSize,
+ m.logTimestamp,
+ m.needRestart,
+ m.unexpectedCertificateCount,
+ )
+ return m
+}
+
+func (m *Metrics) LogState(logName string, state monitor.State) {
+ labels := prometheus.Labels{
+ "log_id": fmt.Sprintf("%x", state.LogID[:]),
+ "log_name": logName,
+ }
+ m.logIndex.With(labels).Set(float64(state.NextIndex))
+ m.logSize.With(labels).Set(float64(state.TreeSize))
+ m.logTimestamp.With(labels).Set(float64(state.Timestamp))
+}
+
+func (m *Metrics) RemoveLogState(logName string, state monitor.State) {
+ labels := prometheus.Labels{
+ "log_id": fmt.Sprintf("%x", state.LogID[:]),
+ "log_name": logName,
+ }
+ m.logIndex.Delete(labels)
+ m.logSize.Delete(labels)
+ m.logTimestamp.Delete(labels)
+}
+
+func (m *Metrics) UnexpectedCertificateCount(logNames []string, alerts []index.CertificateInfo) {
+ m.unexpectedCertificateCount.Reset()
+ for i, alert := range alerts {
+ labels := prometheus.Labels{
+ "crt_sans": strings.Join(alert.SANs, " "),
+ "log_id": fmt.Sprintf("%x", alert.LogID),
+ "log_name": logNames[i],
+ "log_index": fmt.Sprintf("%d", alert.LogIndex),
+ }
+ m.unexpectedCertificateCount.With(labels).Set(1)
+ }
+}
+
+func (m *Metrics) CountError() {
+ m.errorCounter.Inc()
+}
+
+func (m *Metrics) NeedRestart() {
+ m.needRestart.Set(float64(1))
+}