Skip to content

Commit 8d058df

Browse files
Ease config of multiple prometheuses for same metric type (#49)
1 parent a82018e commit 8d058df

File tree

7 files changed

+56
-22
lines changed

7 files changed

+56
-22
lines changed

cortex.secrets.example.yaml

+7-1
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,15 @@ conf:
2626
prometheus:
2727
hosts:
2828
# See: https://github.com/sapcc/vrops-exporter
29-
- name: vrops_prometheus
29+
- name: vmware_prometheus
3030
url: https://path-to-your-vrops-prometheus
3131
sso: *sharedSSOCert
32+
provides: [vrops_vm_metric, vrops_host_metric]
33+
# See: https://github.com/prometheus/node_exporter
34+
- name: kvm_prometheus
35+
url: https://path-to-your-node-exporter
36+
sso: *sharedSSOCert
37+
provides: [node_exporter_metric]
3238
# Override the endpoints and credentials to your OpenStack.
3339
openstack:
3440
keystone:

helm/cortex/Chart.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type: application
1818
# This is the chart version. This version number should be incremented each time you make changes
1919
# to the chart and its templates, including the app version.
2020
# Versions are expected to follow Semantic Versioning (https://semver.org/)
21-
version: 0.3.0
21+
version: 0.4.0
2222

2323
# This is the version number of the application being deployed. This version number should be
2424
# incremented each time you make changes to the application. Versions are not expected to

helm/cortex/values.yaml

+4-5
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,14 @@ conf:
135135
prometheus:
136136
# Prometheus hosts to consider when syncing the metrics.
137137
hosts:
138-
- name: vrops_prometheus
138+
- name: vmware_prometheus
139139
url: https://path-to-vrops-prometheus
140+
provides: [vrops_vm_metric, vrops_host_metric]
140141
# Optional, only required if Prometheus is configured with SSO.
141142
sso: *sharedSSOCert
142-
- name: node_exporter_prometheus
143+
- name: kvm_prometheus
143144
url: https://path-to-node-exporter
145+
provides: [node_exporter_metric]
144146
# Optional, only required if Prometheus is configured with SSO.
145147
sso: *sharedSSOCert
146148
# Prometheus metrics to sync into the database.
@@ -152,12 +154,10 @@ conf:
152154
query: |
153155
vrops_virtualmachine_cpu_demand_ratio{}
154156
type: vrops_vm_metric
155-
prometheusNames: [vrops_prometheus]
156157
- alias: vrops_hostsystem_cpu_contention_percentage
157158
query: |
158159
vrops_hostsystem_cpu_contention_percentage{}
159160
type: vrops_host_metric
160-
prometheusNames: [vrops_prometheus]
161161
# Node exporter metrics for KVM hosts.
162162
- alias: node_exporter_cpu_usage_pct
163163
query: |
@@ -166,7 +166,6 @@ conf:
166166
count by (node) (rate(node_cpu_seconds_total{mode="idle"}[1m]))
167167
)) * 100
168168
type: node_exporter_metric
169-
prometheusNames: [node_exporter_prometheus]
170169

171170
openstack:
172171
keystone:

internal/conf/validation.go

+16
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,21 @@ func (c *config) Validate() error {
134134
if !slices.Contains(validAvailabilities, c.SyncConfig.OpenStack.Placement.Availability) {
135135
return fmt.Errorf("invalid placement availability %s", c.SyncConfig.OpenStack.Placement.Availability)
136136
}
137+
// Check that all confed metric types have a host to sync from.
138+
confedMetricTypes := make(map[string]bool)
139+
for _, metric := range c.SyncConfig.Prometheus.Metrics {
140+
confedMetricTypes[metric.Type] = true
141+
}
142+
providedMetricTypes := make(map[string]bool)
143+
for _, host := range c.SyncConfig.Prometheus.Hosts {
144+
for _, metricType := range host.ProvidedMetricTypes {
145+
providedMetricTypes[metricType] = true
146+
}
147+
}
148+
for metricType := range confedMetricTypes {
149+
if !providedMetricTypes[metricType] {
150+
return fmt.Errorf("no host provided for metric type %s", metricType)
151+
}
152+
}
137153
return nil
138154
}

internal/conf/validation_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ func TestValidConf(t *testing.T) {
99
content := `
1010
sync:
1111
prometheus:
12+
hosts:
13+
- name: prometheus
14+
url: http://prometheus:9090
15+
provides: [metric_type_1]
1216
metrics:
1317
- alias: metric_1
1418
query: metric_1
@@ -99,3 +103,18 @@ sync:
99103
t.Fatalf("expected error, got nil")
100104
}
101105
}
106+
107+
func TestInvalidConf_MissingHost(t *testing.T) {
108+
content := `
109+
sync:
110+
prometheus:
111+
metrics:
112+
- alias: metric_1
113+
query: metric_1
114+
type: metric_type_1
115+
`
116+
conf := newConfigFromBytes([]byte(content))
117+
if err := conf.Validate(); err == nil {
118+
t.Fatalf("expected error, got nil")
119+
}
120+
}

internal/conf/yaml.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ type SyncPrometheusMetricConfig struct {
5151
TimeRangeSeconds *int `yaml:"timeRangeSeconds,omitempty"`
5252
IntervalSeconds *int `yaml:"intervalSeconds,omitempty"`
5353
ResolutionSeconds *int `yaml:"resolutionSeconds,omitempty"`
54-
55-
// One or multiple prometheus names to fetch the metric from.
56-
// If multiple names are given, the metric will be fetched from
57-
// all of them.
58-
PrometheusNames []string `yaml:"prometheusNames"`
5954
}
6055

6156
// Configuration for a single prometheus host.
@@ -66,6 +61,8 @@ type SyncPrometheusHostConfig struct {
6661
URL string `yaml:"url"`
6762
// The SSO configuration for this host.
6863
SSO SSOConfig `yaml:"sso,omitempty"`
64+
// The types of metrics this host provides.
65+
ProvidedMetricTypes []string `yaml:"provides"`
6966
}
7067

7168
// Configuration for the sync/prometheus module containing a list of metrics.

internal/sync/prometheus/sync.go

+7-10
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,19 @@ type CombinedSyncer struct {
6262
func NewCombinedSyncer(config conf.SyncPrometheusConfig, db db.DB, monitor sync.Monitor) sync.Datasource {
6363
slog.Info("loading syncers", "metrics", config.Metrics)
6464
syncers := []sync.Datasource{}
65-
hostConfByName := make(map[string]conf.SyncPrometheusHostConfig)
66-
for _, hostConf := range config.Hosts {
67-
hostConfByName[hostConf.Name] = hostConf
68-
}
6965
for _, metricConfig := range config.Metrics {
7066
syncerFunc, ok := supportedSyncers[metricConfig.Type]
7167
if !ok {
7268
panic("unsupported metric type: " + metricConfig.Type)
7369
}
74-
// Sync the metric from one or multiple prometheus hosts.
75-
for _, prometheusName := range metricConfig.PrometheusNames {
76-
hostConf, ok := hostConfByName[prometheusName]
77-
if !ok {
78-
panic("unknown metric host: " + prometheusName)
70+
// Get the prometheuses to sync this metric from.
71+
for _, hostConf := range config.Hosts {
72+
for _, providedMetricType := range hostConf.ProvidedMetricTypes {
73+
if providedMetricType == metricConfig.Type {
74+
slog.Info("adding syncer", "metricType", metricConfig.Type, "host", hostConf.Name)
75+
syncers = append(syncers, syncerFunc(db, hostConf, metricConfig, monitor))
76+
}
7977
}
80-
syncers = append(syncers, syncerFunc(db, hostConf, metricConfig, monitor))
8178
}
8279
}
8380
return CombinedSyncer{

0 commit comments

Comments
 (0)