Skip to content

Conversation

@chinmay3012
Copy link
Contributor

@chinmay3012 chinmay3012 commented Dec 8, 2025

Which problem is this PR solving?

Description of the changes

  • Modified the query parser to preserve the otel.status_code tag in trace query parameters instead of deleting it.
  • Previously, the parser correctly injected error=true when otel.status_code=ERROR, but it removed the original otel.status_code tag. This logic prevented users from filtering by other status codes (e.g., OK) or relying on the storage backend to handle otel.status_code directly.
  • This change ensures that otel.status_code is passed through to the backend, enabling precise filtering while maintaining backward compatibility for the error=true mapping.

How was this change tested?

  • Updated unit tests in
    cmd/query/app/query_parser_test.go
    to verify that otel.status_code is present in the
    Tags
    map for both ERROR and OK values.
  • Validated that otel.status_code=ERROR still triggers the addition of error=true (preserving existing behavior) while keeping the original tag.

@chinmay3012 chinmay3012 requested a review from a team as a code owner December 8, 2025 20:37
@dosubot dosubot bot added the bug label Dec 8, 2025
Chinmay Mehrotra added 3 commits December 9, 2025 02:10
Preserve the otel.status_code tag in query parameters instead of deleting it. This allows filtering by specific status codes (e.g., OK) while maintaining backward compatibility for implicit error=true mapping.

Signed-off-by: Chinmay Mehrotra <[email protected]>
@codecov
Copy link

codecov bot commented Dec 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.63%. Comparing base (b728d61) to head (79dc287).
⚠️ Report is 83 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7717      +/-   ##
==========================================
+ Coverage   95.59%   95.63%   +0.03%     
==========================================
  Files         311      311              
  Lines       15517    15520       +3     
==========================================
+ Hits        14833    14842       +9     
+ Misses        535      531       -4     
+ Partials      149      147       -2     
Flag Coverage Δ
badger_v1 9.89% <ø> (ø)
badger_v2 2.07% <ø> (ø)
cassandra-4.x-v1-manual 14.07% <ø> (ø)
cassandra-4.x-v2-auto 2.05% <ø> (ø)
cassandra-4.x-v2-manual 2.05% <ø> (ø)
cassandra-5.x-v1-manual 14.07% <ø> (ø)
cassandra-5.x-v2-auto 2.05% <ø> (ø)
cassandra-5.x-v2-manual 2.05% <ø> (ø)
clickhouse 1.98% <ø> (ø)
elasticsearch-6.x-v1 18.78% <ø> (ø)
elasticsearch-7.x-v1 18.82% <ø> (?)
elasticsearch-8.x-v1 18.98% <ø> (ø)
elasticsearch-8.x-v2 2.07% <ø> (ø)
elasticsearch-9.x-v2 2.07% <ø> (?)
grpc_v1 9.68% <ø> (ø)
grpc_v2 2.07% <ø> (ø)
kafka-3.x-v2 2.07% <ø> (ø)
memory_v2 2.07% <ø> (ø)
opensearch-1.x-v1 18.87% <ø> (ø)
opensearch-2.x-v1 18.87% <ø> (ø)
opensearch-2.x-v2 2.07% <ø> (ø)
opensearch-3.x-v2 2.07% <ø> (ø)
query 2.07% <ø> (ø)
tailsampling-processor 0.59% <ø> (ø)
unittests 94.20% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link

github-actions bot commented Dec 8, 2025

Metrics Comparison Summary

Total changes across all snapshots: 53

Detailed changes per snapshot

summary_metrics_snapshot_cassandra

📊 Metrics Diff Summary

Total Changes: 53

  • 🆕 Added: 0 metrics
  • ❌ Removed: 53 metrics
  • 🔄 Modified: 0 metrics

❌ Removed Metrics

  • http_server_request_body_size_bytes (18 variants)
View diff sample
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="+Inf",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="0",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="10",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="100",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="1000",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="10000",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="25",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
...
- `http_server_request_duration_seconds` (17 variants)
View diff sample
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="+Inf",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="0.005",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="0.01",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="0.025",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="0.05",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="0.075",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_request_duration_seconds{http_request_method="GET",http_response_status_code="503",le="0.1",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
...
- `http_server_response_body_size_bytes` (18 variants)
View diff sample
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="+Inf",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="0",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="10",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="100",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="1000",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="10000",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
-http_server_response_body_size_bytes{http_request_method="GET",http_response_status_code="503",le="25",network_protocol_name="http",network_protocol_version="1.1",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_schema_url="",otel_scope_version="0.63.0",server_address="localhost",server_port="13133",url_scheme="http"}
...

➡️ View full metrics file

@chinmay3012
Copy link
Contributor Author

I wanted to share a quick update : I've been diving deeper into the jaeger codebase and have successfully addressed a few key issues:

  • Fixed UI Filtering Bug (PR [Bug]: filter by tags not works in Jaeger-UI #7696 #7717): I diagnosed and fixed the issue where filtering by otel.status_code was failing.
  • Technical Detail: The query parser was deleting the tag after processing ERROR status. I modified the logic to preserve the otel.status_code tag in the query parameters, enabling correct filtering for all status codes (like OK) while maintaining backward compatibility for error=true.
  • I also added comprehensive unit tests to cover these edge cases.
  • CI/CD Maintenance: I noticed the
    ci-unit-tests-go-tip.yml
    workflow was failing due to missing tools.
  • I fixed the environment setup to ensure unit tests run correctly on the latest Go versions, helping maintain build stability.
    I have ensured all my commits are DCO signed and compliant with the contribution guidelines. I am enjoying working with the Jaeger architecture and am eager to tackle more complex challenges for the GSoC project.

}

if val, ok := tags[otelsemconv.OtelStatusCode]; ok {
if val == "ERROR" {
Copy link
Member

Choose a reason for hiding this comment

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

we should make it case insensitive

if val, ok := tags[otelsemconv.OtelStatusCode]; ok {
if val == "ERROR" {
tags["error"] = "true"
}
Copy link
Member

Choose a reason for hiding this comment

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

what happens if user explicitly types otel.status_code:OK? You'd still return spans with errors?

Use strings.EqualFold to handle cases like 'Error' or 'error' correctly. Also added a test case for mixed case input.

Signed-off-by: Chinmay Mehrotra <[email protected]>
@chinmay3012
Copy link
Contributor Author

Thanks for the review! I've updated the PR to handle the status code check case-insensitively as requested.
By preserving the otel.status_code tag in the query parameters (instead of deleting it), we pass it down to the storage backend.
If the user queries otel.status_code=OK, this tag is sent to the backend. Assuming the storage backend indexes and supports filtering by this tag (which the issue implies it should), the query will only return spans matching that specific tag value.
This effectively filters out ERROR spans because they would have otel.status_code=ERROR, which doesn't match OK.
Previously, since the tag was deleted by the parser, the backend received no filter for it, which is why it returned everything (including errors).
This change allows users to filter by any status code supported by the backend, while keeping the existing logic that maps ERROR to error=true for backward compatibility.

@yurishkuro
Copy link
Member

yurishkuro commented Jan 7, 2026

I believe the original issue has been resolved.

@yurishkuro yurishkuro closed this Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: filter by tags not works in Jaeger-UI

2 participants