Skip to content

Commit

Permalink
Merge pull request #12 from rated-network/bug/sc-20798/fix-parsing-cu…
Browse files Browse the repository at this point in the history
…rly-brackets

fix: [sc-20759] fix parsing  curly brackets
  • Loading branch information
dswistowski authored Dec 6, 2024
2 parents 8e3ba3c + 31072ef commit bed8319
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/rated_exporter_sdk/providers/prometheus/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ def extract_metric_names(self, expr: str) -> List[str]:
# Existing function parsing logic
if "(" in expr and ")" in expr:
func_name = expr[: expr.find("(")].strip()
args_str = expr[expr.find("(") + 1 : expr.rfind(")")].strip()
end_bracket_pos = self.find_closing("(", ")", expr)
args_str = expr[expr.find("(") + 1 : end_bracket_pos].strip()
args = self.parse_function_args(args_str)
if func_name in self.ALL_FUNCTIONS:
self.validate_function_call(func_name, args)
Expand Down Expand Up @@ -335,19 +336,27 @@ def parse_function_args(self, args_str: str) -> List[str]:
current_arg = ""
paren_count = 0
in_quotes = False
curly_count = 0

for char in args_str:
if char == '"':
in_quotes = not in_quotes
current_arg += char

elif not in_quotes:
if char == "(":
paren_count += 1
current_arg += char
elif char == ")":
paren_count -= 1
current_arg += char
elif char == "," and paren_count == 0:
elif char == "{":
curly_count += 1
current_arg += char
elif char == "}":
curly_count -= 1
current_arg += char
elif char == "," and paren_count == 0 and curly_count == 0:
args.append(current_arg.strip())
current_arg = ""
else:
Expand All @@ -374,3 +383,19 @@ def check_balanced(self, expr: str, open_char: str, close_char: str) -> bool:
if count < 0:
return False
return count == 0

@staticmethod
def find_closing(opening: str, closing: str, expression: str):
deep = 0
in_string = False
start = expression.find(opening)
for idx, char in enumerate(expression[start:]):
if char == '"':
in_string = not in_string
elif not in_string:
if char == opening:
deep += 1
elif char == closing:
deep -= 1
if deep == 0:
return start + idx
12 changes: 12 additions & 0 deletions tests/providers/prometheus/test_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from rated_exporter_sdk.providers.prometheus.validation import QueryValidator


def test_can_validate_query():
query = """histogram_quantile(0.95, sum by(le, namespace) (rate(httpmetrics_handled_requests_histogram_bucket{type="http", service="rpcproxy", namespace!~"rpcproxy|rpc-.*"}[1m]))) * on(namespace) group_left(eth_network) (1*kube_namespace_labels{eth_network="testnet"})""" # noqa: E501
QueryValidator().validate_query(query)


def test_can_find_closing():
expression = 'histogram_quantile(0.95, sum by(le, namespace) (rate(httpmetrics_handled_requests_histogram_bucket{type="http", service="rpcproxy", namespace!~"rpcproxy|rpc-.*"}[1m]))) * on(namespace) group_left(eth_network) (1*kube_namespace_labels{eth_network="testnet"})' # noqa: E501
assert 167 == QueryValidator.find_closing("(", ")", expression)
assert expression[168:171] == " * "

0 comments on commit bed8319

Please sign in to comment.