Skip to content

Commit 7772f97

Browse files
authored
Include error message in traces when transport fails (Azure#21800)
Unwrap *url.Error types to avoid disclosure of unsanitized URLs. Skip generating trace info for no-op tracers.
1 parent 85e694f commit 7772f97

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed

sdk/azcore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
### Bugs Fixed
1010

1111
* Fixed an issue that could cause some allowed HTTP header values to not show up in logs.
12+
* Include error text instead of error type in traces when the transport returns an error.
1213

1314
### Other Changes
1415

16+
* Skip generating trace info for no-op tracers.
17+
1518
## 1.9.0-beta.1 (2023-10-05)
1619

1720
### Other Changes

sdk/azcore/arm/runtime/policy_trace_namespace.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
// httpTraceNamespacePolicy is a policy that adds the az.namespace attribute to the current Span
1919
func httpTraceNamespacePolicy(req *policy.Request) (resp *http.Response, err error) {
2020
rawTracer := req.Raw().Context().Value(shared.CtxWithTracingTracer{})
21-
if tracer, ok := rawTracer.(tracing.Tracer); ok {
21+
if tracer, ok := rawTracer.(tracing.Tracer); ok && tracer.Enabled() {
2222
rt, err := resource.ParseResourceType(req.Raw().URL.Path)
2323
if err == nil {
2424
// add the namespace attribute to the current span

sdk/azcore/runtime/policy_http_trace.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ package runtime
88

99
import (
1010
"context"
11+
"errors"
1112
"fmt"
1213
"net/http"
14+
"net/url"
1315
"strings"
1416

1517
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
@@ -44,7 +46,7 @@ type httpTracePolicy struct {
4446
// Do implements the pipeline.Policy interfaces for the httpTracePolicy type.
4547
func (h *httpTracePolicy) Do(req *policy.Request) (resp *http.Response, err error) {
4648
rawTracer := req.Raw().Context().Value(shared.CtxWithTracingTracer{})
47-
if tracer, ok := rawTracer.(tracing.Tracer); ok {
49+
if tracer, ok := rawTracer.(tracing.Tracer); ok && tracer.Enabled() {
4850
attributes := []tracing.Attribute{
4951
{Key: attrHTTPMethod, Value: req.Raw().Method},
5052
{Key: attrHTTPURL, Value: getSanitizedURL(*req.Raw().URL, h.allowedQP)},
@@ -74,9 +76,14 @@ func (h *httpTracePolicy) Do(req *policy.Request) (resp *http.Response, err erro
7476
span.SetAttributes(tracing.Attribute{Key: attrAZServiceReqID, Value: reqID})
7577
}
7678
} else if err != nil {
77-
// including the output from err.Error() might disclose URL query parameters.
78-
// so instead of attempting to sanitize the output, we simply output the error type.
79-
span.SetStatus(tracing.SpanStatusError, fmt.Sprintf("%T", err))
79+
var urlErr *url.Error
80+
if errors.As(err, &urlErr) {
81+
// calling *url.Error.Error() will include the unsanitized URL
82+
// which we don't want. in addition, we already have the HTTP verb
83+
// and sanitized URL in the trace so we aren't losing any info
84+
err = urlErr.Err
85+
}
86+
span.SetStatus(tracing.SpanStatusError, err.Error())
8087
}
8188
span.End()
8289
}()

sdk/azcore/runtime/policy_http_trace_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package runtime
88

99
import (
1010
"context"
11+
"errors"
1112
"io"
1213
"net"
1314
"net/http"
@@ -100,7 +101,22 @@ func TestHTTPTracePolicy(t *testing.T) {
100101
require.Error(t, err)
101102
require.ErrorIs(t, err, net.ErrClosed)
102103
require.EqualValues(t, tracing.SpanStatusError, spanStatus)
103-
require.EqualValues(t, "poll.errNetClosing", spanStatusStr)
104+
require.EqualValues(t, "use of closed network connection", spanStatusStr)
105+
106+
const urlErrText = "the endpoint is invalid"
107+
req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL())
108+
require.NoError(t, err)
109+
srv.AppendError(&url.Error{
110+
Op: http.MethodGet,
111+
URL: srv.URL(),
112+
Err: errors.New(urlErrText),
113+
})
114+
_, err = pl.Do(req)
115+
require.Error(t, err)
116+
var urlErr *url.Error
117+
require.False(t, errors.As(err, &urlErr))
118+
require.EqualValues(t, tracing.SpanStatusError, spanStatus)
119+
require.EqualValues(t, urlErrText, spanStatusStr)
104120
}
105121

106122
func TestStartSpan(t *testing.T) {

0 commit comments

Comments
 (0)