Skip to content

feat: detect and validate inner queries in default_zero() functions #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

ianchesal
Copy link
Contributor

  • Add query parsing to detect default_zero() usage and extract inner queries
  • Validate inner queries separately to catch metrics masked by default_zero()
  • Support nested default_zero() calls with proper parentheses matching
  • Fail linting when default_zero() masks invalid metrics or syntax errors
  • Add comprehensive test suite with edge cases and nested scenarios
  • Enhance logging with debug info for query analysis and validation

BREAKING CHANGE: Linter now fails for invalid metrics wrapped in default_zero()
that previously passed validation

Resolves issue where default_zero() masked invalid metrics in CI pipelines

- Add query parsing to detect default_zero() usage and extract inner queries
- Validate inner queries separately to catch metrics masked by default_zero()
- Support nested default_zero() calls with proper parentheses matching
- Fail linting when default_zero() masks invalid metrics or syntax errors
- Add comprehensive test suite with edge cases and nested scenarios
- Enhance logging with debug info for query analysis and validation

BREAKING CHANGE: Linter now fails for invalid metrics wrapped in default_zero()
that previously passed validation

Resolves issue where default_zero() masked invalid metrics in CI pipelines
@ianchesal ianchesal requested a review from a team as a code owner June 6, 2025 14:30
@ianchesal ianchesal self-assigned this Jun 6, 2025
@@ -0,0 +1,67 @@
# Enhanced default_zero() Validation
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Goose added this file. Not sure we like it? Up to you @kuzmik.

Copy link
Contributor

Choose a reason for hiding this comment

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

Does it do anything with the agent/LLMs performance or is this for humans?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i don't think it helps the LLM at all

@ianchesal
Copy link
Contributor Author

Process I used:

  • First I told it to summarize the repo:
> summarize this repository for me
  • And then I told it what I wanted it to do:
you are an expert in golang and datadog query writing. you can write clear datadog query yaml and exceptionally high quality golang software. we want to improve ths query linting that this golang code does on datadog metrics. specifically, when using `default_zero()` on an invalid metric, the linter will pass. we'd like the linter to fail if `default_zero()` is being called on an invalid metric. when you update the golang code to implement this lint check, add tests that prove that you've solved the problem as well.

It was on auto-pilot mode (I think they call it "smart approval") and did not stop to ask me for anything until it was done generating the code, the tests, running the tests, and writing a summary of what it had done.

I was using goose and sonnet-4 for the LLM.

…tion

- Add MetricInfo struct to track individual metrics with positioning and nesting info
- Enhance QueryAnalysis to support complex queries with IsComplexQuery flag and Metrics slice
- Implement isComplexQuery() to detect mathematical operations and multiple metrics
- Add extractAllMetrics() to parse and extract all metrics from complex expressions
- Add extractDefaultZeroMetrics() with overlap prevention for nested default_zero() calls
- Add extractRemainingMetrics() to find metrics not wrapped in default_zero()
- Enhance main validation logic to validate each metric individually in complex queries
- Add comprehensive test coverage for multi-metric scenarios
- Support complex queries like: (default_zero(default_zero(avg:metric1{tag}))+default_zero(avg:metric2{tag}))/default_zero(avg:metric3{tag})
- Maintain full backward compatibility with existing single-metric functionality
- Prevent invalid metrics from hiding behind default_zero() in mathematical expressions

Test files added:
- datadogmetric-multi-metric-complex.yaml: nested default_zero with multiple metrics
- datadogmetric-multi-metric-simple.yaml: simple addition of two metrics
- datadogmetric-mixed-metrics.yaml: mixed default_zero and non-default_zero metrics

All tests pass via 'make dockertest' with real Datadog API validation.
@ianchesal
Copy link
Contributor Author

@kuzmik @4ndypanda the second commit to find multiple instances really blew up the complexity of the go code. I didn't read it very closely TBH. Would definitely not trust it without a good read from one of you.

The first commit to catch the simpler cases seems good to me though.

@4ndypanda
Copy link
Contributor

@kuzmik @4ndypanda the second commit to find multiple instances really blew up the complexity of the go code. I didn't read it very closely TBH. Would definitely not trust it without a good read from one of you.

The first commit to catch the simpler cases seems good to me though.

Looks like the agent is solving the problem by extracting all the individual metrics in the query, removing the default_zero(...) function wrapping them, and validating each one. But I can't tell from the code generated if it is exhaustive. E.g. maybe the query is invalid despite all the metrics being valid.

Seems like an easier implementation is just replacing all default_zero( with just ( since having redundant parenthesis is fine in a query. So going from (default_zero(default_zero(A))+default_zero(B))/default_zero(C) to ( ( (A) ) + (B) ) / (C) (I added spaces so it is easier to see).

@ianchesal
Copy link
Contributor Author

@kuzmik @4ndypanda would you like me to have it do the replace all default_zero() with () idea instead?

@ianchesal
Copy link
Contributor Author

Going to try this with Claude instead.

@ianchesal ianchesal closed this Jun 9, 2025
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.

3 participants