-
Notifications
You must be signed in to change notification settings - Fork 2.7k
changelog: Support attributes filtering in /api/v3/traces endpoint #7631
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
base: main
Are you sure you want to change the base?
changelog: Support attributes filtering in /api/v3/traces endpoint #7631
Conversation
Signed-off-by: Divyansh Khatri <[email protected]>
cmd/query/app/apiv3/http_gateway.go
Outdated
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | ||
| // Pass the underlying JSON parsing error | ||
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | ||
| if h.tryParamError(w, err, paramAttributes) { | ||
| return nil, true | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bug in the error handling logic. When JSON unmarshal fails and h.tryParamError() returns true (indicating the error was handled), the function continues execution with an empty attributes map instead of returning. This could lead to unexpected behavior.
The code should be modified to return immediately after handling the error:
if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil {
// Pass the underlying JSON parsing error
err := fmt.Errorf("cannot parse attributes JSON: %w", err)
if h.tryParamError(w, err, paramAttributes) {
return nil, true
}
}Without a proper return statement, the function will continue processing with potentially invalid input data.
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | |
| // Pass the underlying JSON parsing error | |
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | |
| if h.tryParamError(w, err, paramAttributes) { | |
| return nil, true | |
| } | |
| } | |
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | |
| // Pass the underlying JSON parsing error | |
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | |
| if h.tryParamError(w, err, paramAttributes) { | |
| return nil, true | |
| } | |
| return nil, true | |
| } | |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
|
@albertteoh can I get a review on this PR? |
|
there have to be IDL changes first that document changes to the schema |
@yurishkuro I checked the proto file and the attributes field already exists in TraceQueryParameters (query_service.proto line 45). My PR is implementing the parsing logic that was missing in the HTTP gateway. |
|
ok, I see the IDL has the attributes, but where is it defined that the new param is supposed to be url-encoded JSON? |
You're right - the HTTP format isn't explicitly documented.I have made the PR and fixed a small error in CONTRIBUTING.md as well please review it. |
|
does this match how UI sends tags filter? |
Yes, this matches how the UI sends the tags filter.The UI sends: |
cmd/query/app/apiv3/http_gateway.go
Outdated
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | ||
| // Pass the underlying JSON parsing error | ||
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | ||
| if h.tryParamError(w, err, paramAttributes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tryParamError is used when you're not sure if err is not nil. Here you do, so should use tryHandleError
cmd/query/app/apiv3/http_gateway.go
Outdated
| } | ||
|
|
||
| func (h *HTTPGateway) parseFindTracesQuery(q url.Values, w http.ResponseWriter) (*querysvc.TraceQueryParams, bool) { | ||
| // Parse attributes first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move to a helper function
Codecov Report✅ All modified and coverable lines are covered by tests. ❌ Your project check has failed because the head coverage (40.32%) is below the target coverage (95.00%). You can increase the head coverage or adjust the target coverage.
Additional details and impacted files@@ Coverage Diff @@
## main #7631 +/- ##
===========================================
- Coverage 96.55% 40.32% -56.24%
===========================================
Files 384 212 -172
Lines 19473 11550 -7923
===========================================
- Hits 18803 4658 -14145
- Misses 486 6452 +5966
- Partials 184 440 +256
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Metrics Comparison SummaryTotal changes across all snapshots: 106 Detailed changes per snapshotsummary_metrics_snapshot_cassandra📊 Metrics Diff SummaryTotal Changes: 53
🆕 Added Metrics
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"}
...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"}
...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"}
...Total Changes: 53
❌ Removed Metrics
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"}
...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"}
...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"}
... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for filtering traces by attributes in the /api/v3/traces HTTP endpoint. Previously, the query.attributes parameter was ignored and always set to an empty map.
- Implemented parsing of
query.attributesJSON parameter in the HTTP handler - Added error handling for malformed attributes JSON
- Included comprehensive unit tests for the new functionality
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cmd/query/app/apiv3/http_gateway.go | Added parsing logic for query.attributes parameter with JSON unmarshaling and error handling |
| cmd/query/app/apiv3/http_gateway_test.go | Added test coverage for attributes parsing and malformed JSON handling |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cmd/query/app/apiv3/http_gateway.go
Outdated
| } | ||
| // Populate the pcommon.Map from the parsed map | ||
| for k, v := range attrMap { | ||
| attributes.PutStr(k, v) | ||
| } |
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling logic is incomplete. If tryParamError writes an error response and returns true, the function continues to execute lines 228-230 which populate the attributes map with data from an uninitialized attrMap. The function should return immediately after the tryParamError block when an error occurs.
| } | |
| // Populate the pcommon.Map from the parsed map | |
| for k, v := range attrMap { | |
| attributes.PutStr(k, v) | |
| } | |
| } else { | |
| // Populate the pcommon.Map from the parsed map | |
| for k, v := range attrMap { | |
| attributes.PutStr(k, v) | |
| } | |
| } |
cmd/query/app/apiv3/http_gateway.go
Outdated
| ServiceName: q.Get(paramServiceName), | ||
| OperationName: q.Get(paramOperationName), | ||
| Attributes: pcommon.NewMap(), // most curiously not supported by grpc-gateway | ||
| Attributes: attributes, |
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace detected after the comma. This should be removed to maintain code cleanliness.
| Attributes: attributes, | |
| Attributes: attributes, |
| gw.reader.AssertExpectations(t) | ||
| } | ||
|
|
||
|
|
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra blank line should be removed. The file should have only one blank line between function definitions.
Signed-off-by: Divyansh Khatri <[email protected]>
|
@yurishkuro I have addressed the feedback . |
| var attrMap map[string]string | ||
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | ||
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | ||
| h.tryHandleError(w, err, http.StatusBadRequest) | ||
| return attributes, true | ||
| } | ||
|
|
||
| for k, v := range attrMap { | ||
| attributes.PutStr(k, v) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation only supports string-typed attribute values by unmarshaling into map[string]string. This will cause JSON unmarshal errors when users provide valid JSON with numeric or boolean values (e.g., {"http.status_code": 200, "error": true} instead of {"http.status_code": "200", "error": "true"}). Trace attributes commonly include numeric status codes, boolean flags, and other non-string types.
To fix this, unmarshal into map[string]interface{} and use type assertions to handle different value types:
var attrMap map[string]interface{}
if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil {
err := fmt.Errorf("cannot parse attributes JSON: %w", err)
h.tryHandleError(w, err, http.StatusBadRequest)
return attributes, true
}
for k, v := range attrMap {
switch val := v.(type) {
case string:
attributes.PutStr(k, val)
case float64:
attributes.PutDouble(k, val)
case bool:
attributes.PutBool(k, val)
// Add other types as needed
}
}| var attrMap map[string]string | |
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | |
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | |
| h.tryHandleError(w, err, http.StatusBadRequest) | |
| return attributes, true | |
| } | |
| for k, v := range attrMap { | |
| attributes.PutStr(k, v) | |
| } | |
| var attrMap map[string]interface{} | |
| if err := json.Unmarshal([]byte(attrStr), &attrMap); err != nil { | |
| err := fmt.Errorf("cannot parse attributes JSON: %w", err) | |
| h.tryHandleError(w, err, http.StatusBadRequest) | |
| return attributes, true | |
| } | |
| for k, v := range attrMap { | |
| switch val := v.(type) { | |
| case string: | |
| attributes.PutStr(k, val) | |
| case float64: | |
| attributes.PutDouble(k, val) | |
| case bool: | |
| attributes.PutBool(k, val) | |
| // Add other types as needed | |
| } | |
| } |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
|
@yurishkuro I have made the changes you asked can you have a look? |
Which problem is this PR solving?
Description of the changes
This PR adds support for filtering by
query.attributesin the/api/v3/tracesHTTP endpoint. Previously, thequery.attributesparameter was ignored by the handler.cmd/query/app/apiv3/http_gateway.go:parseFindTracesQueryto read thequery.attributesparameter.TraceQueryParamsstruct.How was this change tested?
cmd/query/app/apiv3/http_gateway_test.go:TestHTTPGatewayFindTracesWithAttributes: Verifies that thequery.attributesare correctly parsed and passed to the query service.TestHTTPGatewayFindTracesErrorsto check for malformedquery.attributesJSON.Screenshot
Checklist
jaeger:make lint testjaeger-ui:npm run lintandnpm run testcc @yurishkuro