Skip to content

Fix test_prometheus_metrics-t to handle Prometheus labels#5380

Open
renecannao wants to merge 1 commit intov3.0from
fix-prometheus-labels-test
Open

Fix test_prometheus_metrics-t to handle Prometheus labels#5380
renecannao wants to merge 1 commit intov3.0from
fix-prometheus-labels-test

Conversation

@renecannao
Copy link
Contributor

@renecannao renecannao commented Feb 15, 2026

Update parse_prometheus_metrics() to strip labels from metric names
(e.g., 'metric{protocol="mysql"}' -> 'metric') so tests can use
simple metric names without labels.

Fixes #5378

Summary by CodeRabbit

  • Bug Fixes
    • Fixed Prometheus metrics parsing to properly normalize metric names by removing inline label sets, ensuring consistent metric storage and retrieval.

Update parse_prometheus_metrics() to strip labels from metric names
(e.g., 'metric{protocol="mysql"}' -> 'metric') so tests can use
simple metric names without labels.

Fixes #5378
@gemini-code-assist
Copy link

Summary of Changes

Hello @renecannao, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the parse_prometheus_metrics utility to enhance test stability and readability. By stripping Prometheus labels from metric names during parsing, the change ensures that tests can consistently identify and validate metrics without being affected by the presence or variation of labels. This directly addresses an issue where tests failed due to unexpected labels in metric names.

Highlights

  • Prometheus Metric Parsing: The parse_prometheus_metrics utility function has been updated to automatically strip labels from Prometheus metric names. This allows tests to refer to metrics using their base names, simplifying test logic and improving reliability.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • test/tap/tap/utils.cpp
    • Implemented logic within parse_prometheus_metrics to identify and remove Prometheus labels (e.g., {protocol="mysql"}) from metric names, ensuring only the base metric name is used.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Feb 15, 2026

📝 Walkthrough

Walkthrough

Modified the Prometheus metrics parser to extract metric names without their label sets before storing them in the metrics map. The parser now strips inline labels (e.g., {label="value"}) from metric names, allowing test assertions to match metrics by base name only.

Changes

Cohort / File(s) Summary
Prometheus Metrics Parsing
test/tap/tap/utils.cpp
Updated parse_prometheus_metrics() to normalize metric names by removing inline label sets (e.g., metric{protocol="mysql"}metric) when inserting into the metrics map. Labels are now stripped before the value parsing and map insertion steps.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 Hark! A label-stripping deed so fine,
Metrics now align in perfect line,
No more braces causing test dismay,
Names shine clean in every way!

🚥 Pre-merge checks | ✅ 4 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (2 files):

⚔️ lib/MySQL_Monitor.cpp (content)
⚔️ test/tap/tap/utils.cpp (content)

These conflicts must be resolved before merging into v3.0.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing the test to handle Prometheus labels by stripping them from metric names.
Linked Issues check ✅ Passed The PR directly addresses the requirements from #5378 by implementing Option 2: modifying parse_prometheus_metrics() to strip label blocks from metric names.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the Prometheus metrics parsing issue described in #5378; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-prometheus-labels-test
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch fix-prometheus-labels-test
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly updates the parse_prometheus_metrics function to strip labels from metric names, allowing tests to use simple metric names. The implementation is correct and addresses the issue. I've added one suggestion to make the code more concise and improve maintainability.

Comment on lines +1859 to +1864
string metric_name = p_line_val.first;
size_t brace_pos = metric_name.find('{');
if (brace_pos != string::npos) {
metric_name = metric_name.substr(0, brace_pos);
}
metrics_map.insert({metric_name, stod(p_line_val.second)});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic to strip labels from the metric name can be made more concise. You can combine std::string::substr with std::string::find in a single expression. When find doesn't locate the character, it returns std::string::npos, and substr(0, std::string::npos) correctly returns a copy of the entire string. This simplifies the code by removing the conditional logic and intermediate variables.

            metrics_map.insert({p_line_val.first.substr(0, p_line_val.first.find('{')), stod(p_line_val.second)});

@sonarqubecloud
Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@test/tap/tap/utils.cpp`:
- Around line 1858-1864: parse_prometheus_metrics() currently strips labels from
metric names and uses map::insert which drops duplicate label variants, breaking
tests that call extract_metric_tags() on the returned keys; revert to preserving
the full metric key (use p_line_val.first directly instead of stripping into
metric_name) and replace the insert call with an assignment/emplace that records
every variant (e.g., use metrics_map[p_line_val.first] = stod(p_line_val.second)
or a multimap/vector if you need to keep multiple values) so
extract_metric_tags() can find the '{' and labels and duplicates are not
silently lost.
🧹 Nitpick comments (1)
test/tap/tap/utils.cpp (1)

1855-1855: Avoid unnecessary string copy in range-based for loop.

ln is copied on each iteration. Use a const reference instead.

Suggested fix
-	for (const string ln : lines) {
+	for (const string& ln : lines) {

Comment on lines +1858 to +1864
// Strip labels from metric name (e.g., "metric{label=\"value\"}" -> "metric")
string metric_name = p_line_val.first;
size_t brace_pos = metric_name.find('{');
if (brace_pos != string::npos) {
metric_name = metric_name.substr(0, brace_pos);
}
metrics_map.insert({metric_name, stod(p_line_val.second)});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find where parse_prometheus_metrics is called
rg -n 'parse_prometheus_metrics' --type=cpp -B2 -A2

Repository: sysown/proxysql

Length of output: 1737


🏁 Script executed:

# Find test files that might consume this function
fd -e cpp -e hpp | head -20

Repository: sysown/proxysql

Length of output: 640


🏁 Script executed:

# Look for Prometheus metrics output in tests
rg -n 'prometheus\|metrics_map' --type=cpp -B2 -A2 | head -100

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Look at test_prometheus_metrics-t.cpp to see how metrics_vals is used
cat test/tap/tests/test_prometheus_metrics-t.cpp | head -100

Repository: sysown/proxysql

Length of output: 2862


🏁 Script executed:

# Look at reg_test_4556-ssl_error_queue-t.cpp to see how m_id_val is used
rg -n 'const map.*m_id_val|m_id_val\[' test/tap/tests/reg_test_4556-ssl_error_queue-t.cpp -A3

Repository: sysown/proxysql

Length of output: 261


🏁 Script executed:

# Search for any test data or fixtures that contain Prometheus metrics format
rg -n 'metric{|protocol=|label=' test/tap/tests/ --type=cpp -C2

Repository: sysown/proxysql

Length of output: 172


🏁 Script executed:

# Search for Prometheus metrics with labels in test files
rg 'proxysql_.*{' test/tap/tests/ --type=cpp -C2

Repository: sysown/proxysql

Length of output: 146


🏁 Script executed:

# Look at what the Prometheus output looks like - search for "# HELP\|# TYPE"
rg 'HELP|TYPE' test/tap/tests/ --type=cpp -C2 | head -50

Repository: sysown/proxysql

Length of output: 3686


🏁 Script executed:

# Check the actual usage of metrics_vals after parsing
rg -n 'metrics_vals\.find\|metrics_vals\[' test/tap/tests/test_prometheus_metrics-t.cpp -A2 -B2

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Look for any fixtures or test data files that might have prometheus output
find test/tap -name "*prometheus*" -o -name "*metrics*" | grep -v '\\.o$'

Repository: sysown/proxysql

Length of output: 273


🏁 Script executed:

# Look at parse_prometheus_metrics implementation completely
sed -n '1851,1870p' test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 711


🏁 Script executed:

# Look for how metrics are looked up - they search for base metric names
rg 'proxysql_' test/tap/tests/test_prometheus_metrics-t.cpp | head -20

Repository: sysown/proxysql

Length of output: 1671


🏁 Script executed:

# Look at the disabled test which might have test data
head -150 test/tap/tests/test_admin_prometheus_metrics_dump-t_disabled_gh3571.cpp

Repository: sysown/proxysql

Length of output: 2674


🏁 Script executed:

# Search for actual metric values in the test to understand structure
rg -n 'find\(' test/tap/tests/test_prometheus_metrics-t.cpp -A1 -B1 | head -40

Repository: sysown/proxysql

Length of output: 1787


🏁 Script executed:

# Check if extract_metric_tags is called and used with the returned map from parse_prometheus_metrics
rg -n 'extract_metric_tags\(' test/tap/tests/test_prometheus_metrics-t.cpp -A2 -B2

Repository: sysown/proxysql

Length of output: 1165


🏁 Script executed:

# Look at the full extract_metric_tags function
rg -n 'extract_metric_tags' test/tap/tap/utils.cpp -A15

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Check what the actual Prometheus output format is - look at the comment/example
rg -n 'HELP\|# TYPE' test/tap/tap/utils.cpp -B2 -A2

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Look at the complete extract_metric_tags function to see what it returns when labels are missing
sed -n '277,310p' test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 1012


🏁 Script executed:

# Check what happens when extract_metric_tags finds no labels - does it return empty or what?
rg -n 'extract_metric_tags' test/tap/tap/utils.cpp -A20 | head -40

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Look at the specific line where metric_tags.at("hostgroup") is called
sed -n '360,370p' test/tap/tests/test_prometheus_metrics-t.cpp

Repository: sysown/proxysql

Length of output: 489


🏁 Script executed:

# Look at the complete extract_metric_tags implementation to confirm what it returns
sed -n '277,300p' test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 791


🏁 Script executed:

# Check if there's any initialization or default behavior after find returns npos
sed -n '275,310p' test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 1096


🏁 Script executed:

# Use ast-grep to find the extract_metric_tags function definition
ast-grep --pattern $'map<string,string> extract_metric_tags($_) {
  $$$
}'

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Look at utils.cpp around line 277 where extract_metric_tags should be
head -320 test/tap/tap/utils.cpp | tail -50

Repository: sysown/proxysql

Length of output: 1546


🏁 Script executed:

# Search for the exact location of extract_metric_tags function
rg -n 'map<string,string> extract_metric_tags' test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Once we know the line number, read that section
rg -n 'map<string,string> extract_metric_tags' test/tap/tap/utils.cpp -A25

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Search for extract_metric_tags without the full signature
rg -n 'extract_metric_tags' test/tap/tap/utils.cpp | head -5

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Look at the line numbers from earlier results - they showed line 277 has it
sed -n '277,320p' test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 1362


🏁 Script executed:

# Try searching in the header file
rg -n 'extract_metric_tags' test/tap/tap/utils.h -A10

Repository: sysown/proxysql

Length of output: 41


🏁 Script executed:

# Search for it anywhere in the tap directory
find test/tap -name "*.cpp" -o -name "*.h" | xargs grep -l 'extract_metric_tags'

Repository: sysown/proxysql

Length of output: 103


🏁 Script executed:

# Get file size and search more carefully
wc -l test/tap/tap/utils.cpp

Repository: sysown/proxysql

Length of output: 86


🏁 Script executed:

# Search for extract_metric_tags in the test file
rg -n 'extract_metric_tags' test/tap/tests/test_prometheus_metrics-t.cpp -B2 -A15

Repository: sysown/proxysql

Length of output: 2974


🏁 Script executed:

# Also check if extract_metric_tags is defined in the test file or just used
grep -n 'extract_metric_tags' test/tap/tests/test_prometheus_metrics-t.cpp

Repository: sysown/proxysql

Length of output: 373


🏁 Script executed:

# Look for the function definition in test_prometheus_metrics-t.cpp
sed -n '250,330p' test/tap/tests/test_prometheus_metrics-t.cpp

Repository: sysown/proxysql

Length of output: 2511


🏁 Script executed:

# Confirm the call to metric_tags.at("hostgroup") on line 363
# If extract_metric_tags returns empty map (because labels are stripped), 
# .at("hostgroup") will throw std::out_of_range exception
sed -n '360,365p' test/tap/tests/test_prometheus_metrics-t.cpp

Repository: sysown/proxysql

Length of output: 330


🏁 Script executed:

# Check if proxysql_connpool_conns metric actually has hostgroup labels in Prometheus output
# Look for any documentation or comments about metric format
rg -n 'proxysql_connpool_conns' test/tap/ -C3 | head -40

Repository: sysown/proxysql

Length of output: 3590


🏁 Script executed:

# Check the git log to see what the original code did before the labels were stripped
git log --oneline test/tap/tap/utils.cpp | head -5

Repository: sysown/proxysql

Length of output: 125


🏁 Script executed:

# Look at the commit that mentions handling Prometheus labels
git show 195bbfb5 --stat

Repository: sysown/proxysql

Length of output: 50371


🏁 Script executed:

# Check what changed in that commit for parse_prometheus_metrics
git show 195bbfb5 test/tap/tap/utils.cpp | head -80

Repository: sysown/proxysql

Length of output: 2745


🏁 Script executed:

# Verify that extract_metric_tags is actually called on the parsed metrics
# and will fail when labels are stripped
grep -n 'extract_metric_tags' test/tap/tests/test_prometheus_metrics-t.cpp

Repository: sysown/proxysql

Length of output: 373


🏁 Script executed:

# Look at what extract_metric_tags returns when it doesn't find '{'
sed -n '277,290p' test/tap/tests/test_prometheus_metrics-t.cpp

Repository: sysown/proxysql

Length of output: 560


This change breaks test assertions by stripping labels that extract_metric_tags() requires.

parse_prometheus_metrics() now strips all labels from metric names, but the test code at lines 362–363 calls extract_metric_tags(p_metric_val.first) expecting the labels to be present. Since extract_metric_tags() searches for { in the metric name and returns an empty map when none is found, the subsequent .at("hostgroup") call will throw std::out_of_range, causing test failures.

The same issue occurs at lines 466 and 640 where other tests call extract_metric_tags() on the returned metrics map expecting labels to be intact.

Additionally, if any Prometheus metric is emitted with multiple label variants (e.g., proxysql_connpool_conns{hostgroup="0"} 5 and proxysql_connpool_conns{hostgroup="1"} 10), map::insert() silently drops all but the first occurrence, losing data.

The label-stripping approach conflicts with the test expectations. Consider either preserving the full metric names with labels in the returned map or refactoring the tests to work without label information.

🤖 Prompt for AI Agents
In `@test/tap/tap/utils.cpp` around lines 1858 - 1864, parse_prometheus_metrics()
currently strips labels from metric names and uses map::insert which drops
duplicate label variants, breaking tests that call extract_metric_tags() on the
returned keys; revert to preserving the full metric key (use p_line_val.first
directly instead of stripping into metric_name) and replace the insert call with
an assignment/emplace that records every variant (e.g., use
metrics_map[p_line_val.first] = stod(p_line_val.second) or a multimap/vector if
you need to keep multiple values) so extract_metric_tags() can find the '{' and
labels and duplicates are not silently lost.

@mirostauder
Copy link
Contributor

retest this please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test_prometheus_metrics-t fails due to Prometheus labels not being included in metric keys

2 participants