Skip to content

Commit 136dedc

Browse files
Copilotalvarolopez
andcommitted
Refactor Prometheus configuration to use flexible label filters
- Replaced prometheus_label_type_instance with two new options: - vm_uuid_label_name: configurable name of the UUID label (default: "uuid") - labels: list of key:value pairs for label filters (default: ["type_instance:scaph_process_power_microwatts"]) - Updated _energy_consumed_wh to parse label list and build label dictionary - Added support for multiple label filters in any combination - Updated all tests to use new configuration structure - Regenerated etc/caso/caso.conf.sample with oslo-config-generator - Updated prometheus-extractor.rst documentation: - New configuration parameters explained - Added examples for multiple label filters - Updated troubleshooting section - All tests pass (4/4 prometheus tests) Co-authored-by: alvarolopez <468751+alvarolopez@users.noreply.github.com>
1 parent 6595b6f commit 136dedc

File tree

4 files changed

+79
-21
lines changed

4 files changed

+79
-21
lines changed

caso/extract/prometheus.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,16 @@
3939
help="Name of the Prometheus metric to query for energy consumption.",
4040
),
4141
cfg.StrOpt(
42-
"prometheus_label_type_instance",
43-
default="scaph_process_power_microwatts",
44-
help="Value for the type_instance label in Prometheus queries.",
42+
"vm_uuid_label_name",
43+
default="uuid",
44+
help="Name of the label that matches the VM UUID in Prometheus metrics.",
45+
),
46+
cfg.ListOpt(
47+
"labels",
48+
default=["type_instance:scaph_process_power_microwatts"],
49+
help="List of label filters as key:value pairs to filter the Prometheus "
50+
"metric (e.g., 'type_instance:scaph_process_power_microwatts'). "
51+
"The VM UUID label will be added automatically based on vm_uuid_label_name.",
4552
),
4653
cfg.IntOpt(
4754
"prometheus_step_seconds",
@@ -99,6 +106,8 @@ def _energy_consumed_wh(self, vm_uuid):
99106
step_seconds = CONF.prometheus.prometheus_step_seconds
100107
query_range = CONF.prometheus.prometheus_query_range
101108
verify_ssl = CONF.prometheus.prometheus_verify_ssl
109+
vm_uuid_label_name = CONF.prometheus.vm_uuid_label_name
110+
label_filters = CONF.prometheus.labels
102111

103112
prom = prometheus_api_client.PrometheusConnect(
104113
url=prom_url, disable_ssl=not verify_ssl
@@ -107,11 +116,20 @@ def _energy_consumed_wh(self, vm_uuid):
107116
# factor = step_seconds / 3600 converts µW·s to µWh
108117
factor = step_seconds / 3600
109118

110-
# Build labels for this VM
111-
labels = {
112-
"type_instance": CONF.prometheus.prometheus_label_type_instance,
113-
"uuid": vm_uuid,
114-
}
119+
# Build labels dictionary from the list of "key:value" strings
120+
labels = {}
121+
for label_filter in label_filters:
122+
if ":" in label_filter:
123+
key, value = label_filter.split(":", 1)
124+
labels[key.strip()] = value.strip()
125+
else:
126+
LOG.warning(
127+
f"Invalid label filter format '{label_filter}', "
128+
"expected 'key:value'. Skipping."
129+
)
130+
131+
# Add the VM UUID label
132+
labels[vm_uuid_label_name] = vm_uuid
115133

116134
# Build label string: {key="value", ...}
117135
label_selector = ",".join(f'{k}="{v}"' for k, v in labels.items())

caso/tests/extract/test_prometheus.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ def configured_extractor(mock_flavors):
6060
# Configure CONF
6161
CONF.set_override("site_name", "TEST-Site")
6262
CONF.set_override("service_name", "TEST-Service")
63+
CONF.set_override("prometheus_endpoint", "http://localhost:9090", group="prometheus")
64+
CONF.set_override("prometheus_metric_name", "prometheus_value", group="prometheus")
65+
CONF.set_override("vm_uuid_label_name", "uuid", group="prometheus")
66+
CONF.set_override(
67+
"labels",
68+
["type_instance:scaph_process_power_microwatts"],
69+
group="prometheus",
70+
)
71+
CONF.set_override("prometheus_step_seconds", 30, group="prometheus")
72+
CONF.set_override("prometheus_query_range", "1h", group="prometheus")
73+
CONF.set_override("prometheus_verify_ssl", True, group="prometheus")
6374

6475
with mock.patch(
6576
"caso.extract.openstack.base.BaseOpenStackExtractor.__init__",

doc/source/prometheus-extractor.rst

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ prometheus_endpoint = http://localhost:9090
2424
# Name of the Prometheus metric to query
2525
prometheus_metric_name = prometheus_value
2626
27-
# Value for the type_instance label
28-
prometheus_label_type_instance = scaph_process_power_microwatts
27+
# Name of the label that matches the VM UUID
28+
vm_uuid_label_name = uuid
29+
30+
# List of label filters as key:value pairs
31+
labels = type_instance:scaph_process_power_microwatts
2932
3033
# Frequency between samples in seconds
3134
prometheus_step_seconds = 30
@@ -43,14 +46,16 @@ The Prometheus extractor:
4346

4447
1. **Scans VMs**: Retrieves the list of VMs from Nova for each configured project
4548
2. **Queries Per VM**: For each VM, executes a Prometheus query using the configured metric name and labels
46-
3. **Calculates Energy**: Uses the formula `sum_over_time(metric_name{type_instance="value", uuid="vm-uuid"}[query_range]) * (step_seconds/3600) / 1000000` to convert microwatt power samples to Watt-hours
47-
4. **Creates Records**: Generates an `EnergyRecord` for each VM with energy consumption data and execution metrics
49+
3. **Builds Labels**: Combines the configured label filters with the VM UUID label (e.g., `{type_instance="scaph_process_power_microwatts", uuid="vm-uuid"}`)
50+
4. **Calculates Energy**: Uses the formula `sum_over_time(metric_name{labels}[query_range]) * (step_seconds/3600) / 1000000` to convert microwatt power samples to Watt-hours
51+
5. **Creates Records**: Generates an `EnergyRecord` for each VM with energy consumption data and execution metrics
4852

4953
## Configuration Parameters
5054

5155
- **prometheus_endpoint**: URL of the Prometheus server (default: `http://localhost:9090`)
5256
- **prometheus_metric_name**: Name of the metric to query (default: `prometheus_value`)
53-
- **prometheus_label_type_instance**: Value for the `type_instance` label used to filter metrics (default: `scaph_process_power_microwatts`)
57+
- **vm_uuid_label_name**: Name of the label that matches the VM UUID in Prometheus metrics (default: `uuid`)
58+
- **labels**: List of label filters as `key:value` pairs to filter the Prometheus metric. The VM UUID label will be added automatically (default: `["type_instance:scaph_process_power_microwatts"]`)
5459
- **prometheus_step_seconds**: Frequency between samples in the time series, in seconds (default: `30`)
5560
- **prometheus_query_range**: Time range for the query (default: `1h`). Examples: `1h`, `6h`, `24h`
5661
- **prometheus_verify_ssl**: Whether to verify SSL certificates when connecting to Prometheus (default: `true`)
@@ -65,7 +70,8 @@ Scaphandre exports energy metrics in microwatts:
6570
[prometheus]
6671
prometheus_endpoint = http://prometheus.example.com:9090
6772
prometheus_metric_name = prometheus_value
68-
prometheus_label_type_instance = scaph_process_power_microwatts
73+
vm_uuid_label_name = uuid
74+
labels = type_instance:scaph_process_power_microwatts
6975
prometheus_step_seconds = 30
7076
prometheus_query_range = 6h
7177
prometheus_verify_ssl = false
@@ -79,12 +85,28 @@ If you have custom energy metrics with different labels:
7985
[prometheus]
8086
prometheus_endpoint = http://prometheus.example.com:9090
8187
prometheus_metric_name = my_custom_power_metric
82-
prometheus_label_type_instance = my_power_label_value
88+
vm_uuid_label_name = instance_id
89+
labels = environment:production,datacenter:dc1
8390
prometheus_step_seconds = 60
8491
prometheus_query_range = 1h
8592
prometheus_verify_ssl = true
8693
```
8794

95+
### For Multiple Label Filters
96+
97+
You can specify multiple label filters:
98+
99+
```ini
100+
[prometheus]
101+
prometheus_endpoint = http://prometheus.example.com:9090
102+
prometheus_metric_name = node_power_watts
103+
vm_uuid_label_name = vm_uuid
104+
labels = type_instance:power_consumption,source:ipmi,rack:rack42
105+
prometheus_step_seconds = 30
106+
prometheus_query_range = 1h
107+
prometheus_verify_ssl = true
108+
```
109+
88110
## Energy Record Format
89111

90112
The Prometheus extractor generates `EnergyRecord` objects with the following fields:
@@ -140,7 +162,8 @@ messengers = ssm
140162
[prometheus]
141163
prometheus_endpoint = http://prometheus.example.com:9090
142164
prometheus_metric_name = prometheus_value
143-
prometheus_label_type_instance = scaph_process_power_microwatts
165+
vm_uuid_label_name = uuid
166+
labels = type_instance:scaph_process_power_microwatts
144167
prometheus_step_seconds = 30
145168
prometheus_query_range = 6h
146169
prometheus_verify_ssl = false
@@ -156,7 +179,7 @@ output_path = /var/spool/apel/outgoing/openstack
156179
- Check that your metric exists in Prometheus UI
157180
- Ensure the metric has data for the configured time range
158181
- Verify VMs exist in the configured projects
159-
- Check that the metric has the required labels (`type_instance` and `uuid`)
182+
- Check that the metric has the required labels (those specified in `labels` config and the UUID label specified by `vm_uuid_label_name`)
160183

161184
**Connection timeout:**
162185
- Check network connectivity to Prometheus
@@ -165,8 +188,8 @@ output_path = /var/spool/apel/outgoing/openstack
165188

166189
**Invalid query results:**
167190
- Ensure your metric contains instantaneous power values in microwatts
168-
- Check that the metric has the `uuid` label matching VM UUIDs
169-
- Verify the `type_instance` label matches your configuration
191+
- Check that the metric has the UUID label matching VM UUIDs (configured via `vm_uuid_label_name`)
192+
- Verify the label filters match your configuration
170193
- Test the query in Prometheus UI: `sum_over_time(prometheus_value{type_instance="scaph_process_power_microwatts", uuid="<vm-uuid>"}[1h])`
171194

172195
**No VMs found:**

etc/caso/caso.conf.sample

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,14 @@
410410
# Name of the Prometheus metric to query for energy consumption. (string value)
411411
#prometheus_metric_name = prometheus_value
412412

413-
# Value for the type_instance label in Prometheus queries. (string value)
414-
#prometheus_label_type_instance = scaph_process_power_microwatts
413+
# Name of the label that matches the VM UUID in Prometheus metrics. (string
414+
# value)
415+
#vm_uuid_label_name = uuid
416+
417+
# List of label filters as key:value pairs to filter the Prometheus metric
418+
# (e.g., 'type_instance:scaph_process_power_microwatts'). The VM UUID label
419+
# will be added automatically based on vm_uuid_label_name. (list value)
420+
#labels = type_instance:scaph_process_power_microwatts
415421

416422
# Frequency between samples in the time series (in seconds). (integer value)
417423
#prometheus_step_seconds = 30

0 commit comments

Comments
 (0)