Allow for providing metric names to modify_query

This change allows for providing the metric name list to the
modify_query method, which can greatly increase performence
when calling the method in a loop. Old behavior with sending
a Prometheus API request is preserved when the new parameter
isn't used.

Change-Id: I151c150c47e39699889baa1564a974e163c6a944
Signed-off-by: Jaromir Wysoglad <jwysogla@redhat.com>
This commit is contained in:
Jaromir Wysoglad
2025-06-30 04:32:51 -04:00
parent af6fa48100
commit fabd89f11d
3 changed files with 63 additions and 12 deletions

View File

@@ -97,14 +97,27 @@ class PromQLRbac(object):
f"{labels_str}" f"{labels_str}"
f"{query[location:]}") f"{query[location:]}")
def modify_query(self, query): def modify_query(self, query, metric_names=None):
"""Add rbac labels to a query. """Add rbac labels to a query.
:param query: The query to modify :param query: The query to modify
:type query: str :type query: str
:param metric_names: List of metric names currently stored in
prometheus. For correct function of the query
modification, it's important for the list to be
accurate and to include all metrics across all
tenants. This parameter can be unspecified or
None, in which case the list will be retrieved
from Prometheus by sending an API request to it.
It's advised to provide the metric list when
doing a query modification in a loop for
performance purposes.
:type metric_names: list
""" """
# We need to get all metric names, no matter the rbac
metric_names = self.client.label_values("__name__") if metric_names is None:
metric_names = self.client.label_values("__name__")
# We need to detect the locations of metric names # We need to detect the locations of metric names
# inside the query # inside the query

View File

@@ -27,15 +27,17 @@ class PromQLRbacTest(testtools.TestCase):
self.rbac.labels = { self.rbac.labels = {
"project": "project123" "project": "project123"
} }
self.rbac.client.label_values = lambda label: [ self.rbac.client.label_values = mock.MagicMock(
'test_query', return_value=[
'cpu_temp_celsius', 'test_query',
'http_requests', 'cpu_temp_celsius',
'test:query:with:colon:', 'http_requests',
'test_query_with_digit1', 'test:query:with:colon:',
'method_code:http_errors:rate5m', 'test_query_with_digit1',
'method:http_requests:rate5m' 'method_code:http_errors:rate5m',
] 'method:http_requests:rate5m'
]
)
self.test_cases = [ self.test_cases = [
( (
"test_query", "test_query",
@@ -227,3 +229,29 @@ class PromQLRbacTest(testtools.TestCase):
kwargs = {'project_label': project_label} kwargs = {'project_label': project_label}
self.assertRaises(ValueError, rbac.PromQLRbac, *args, **kwargs) self.assertRaises(ValueError, rbac.PromQLRbac, *args, **kwargs)
def test_specifying_metric_names(self):
query = "test_query"
metric_names = [
"metric_name1",
"foo",
"bar",
"test_query"
]
expected = "test_query{project='project123'}"
ret = self.rbac.modify_query(query, metric_names)
self.assertEqual(expected, ret)
self.rbac.client.label_values.assert_not_called()
def test_not_specifying_metric_names(self):
query = "test_query"
expected = "test_query{project='project123'}"
ret = self.rbac.modify_query(query)
self.assertEqual(expected, ret)
self.rbac.client.label_values.assert_called_once()

View File

@@ -0,0 +1,10 @@
---
features:
- |
The rbac.PromQLRbac.modify_query method now optionally allows
for providing a list of metric names thanks to a new parameter.
When the new parameter isn't used, the old behavior with sending
a Prometheus API request to retrieve the metric names is used.
When the metric names are provided, no Prometheus API request is
done, which greatly increases performance when using the
modify_query repeatedly, for example in loops.