From 1fdf07933c4c855c3aed70e6eefce0a7f8e05f97 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sat, 31 May 2025 17:09:23 +0200 Subject: [PATCH] feat(config): expose folder and device info as metrics (fixes #9519) (#10148) Tihs makes it easier to use metrics based on device and folder labels, names, and other attributes. Other metrics which are based on folder or device ID can be joined with these info metrics to enrich their label sets. ``` # HELP syncthing_config_device_info Provides additional information labels on devices # TYPE syncthing_config_device_info gauge syncthing_config_device_info{device="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU",introducer="false",name="s1",paused="false",untrusted="false"} 1 # HELP syncthing_config_folder_info Provides additional information labels on folders # TYPE syncthing_config_folder_info gauge syncthing_config_folder_info{folder="default",label="The default folder",path="s2",paused="false",type="sendreceive"} 1 ``` With this you can e.g. query for ``` syncthing_connections_active * on(device) group_left syncthing_config_device_info ``` Fixes #9519 Closes #10074 Closes #10147 --- cmd/syncthing/main.go | 1 + lib/config/metrics.go | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 lib/config/metrics.go diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 458f0761e..01256fec1 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -578,6 +578,7 @@ func syncthingMain(options serveOptions) { os.Exit(svcutil.ExitError.AsInt()) } earlyService.Add(cfgWrapper) + config.RegisterInfoMetrics(cfgWrapper) // Candidate builds should auto upgrade. Make sure the option is set, // unless we are in a build where it's disabled or the STNOUPGRADE diff --git a/lib/config/metrics.go b/lib/config/metrics.go new file mode 100644 index 000000000..fadc83439 --- /dev/null +++ b/lib/config/metrics.go @@ -0,0 +1,62 @@ +// Copyright (C) 2025 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package config + +import ( + "strconv" + + "github.com/prometheus/client_golang/prometheus" +) + +// RegisterInfoMetrics registers Prometheus metrics for the given config +// wrapper. +func RegisterInfoMetrics(cfg Wrapper) { + prometheus.DefaultRegisterer.MustRegister(prometheus.CollectorFunc((&folderInfoMetric{cfg}).Collect)) + prometheus.DefaultRegisterer.MustRegister(prometheus.CollectorFunc((&folderDeviceMetric{cfg}).Collect)) +} + +type folderInfoMetric struct { + cfg Wrapper +} + +var folderInfoMetricDesc = prometheus.NewDesc( + "syncthing_config_folder_info", + "Provides additional information labels on folders", + []string{"folder", "label", "type", "path", "paused"}, + nil, +) + +func (m *folderInfoMetric) Collect(ch chan<- prometheus.Metric) { + for _, folder := range m.cfg.FolderList() { + ch <- prometheus.MustNewConstMetric( + folderInfoMetricDesc, + prometheus.GaugeValue, 1, + folder.ID, folder.Label, folder.Type.String(), folder.Path, strconv.FormatBool(folder.Paused), + ) + } +} + +type folderDeviceMetric struct { + cfg Wrapper +} + +var folderDeviceMetricDesc = prometheus.NewDesc( + "syncthing_config_device_info", + "Provides additional information labels on devices", + []string{"device", "name", "introducer", "paused", "untrusted"}, + nil, +) + +func (m *folderDeviceMetric) Collect(ch chan<- prometheus.Metric) { + for _, device := range m.cfg.DeviceList() { + ch <- prometheus.MustNewConstMetric( + folderDeviceMetricDesc, + prometheus.GaugeValue, 1, + device.DeviceID.String(), device.Name, strconv.FormatBool(device.Introducer), strconv.FormatBool(device.Paused), strconv.FormatBool(device.Untrusted), + ) + } +}