Skip to content

Commit 6f78ccd

Browse files
committed
TUN-6250: Add upstream response status code to tracing span attributes
1 parent 26a7b59 commit 6f78ccd

File tree

4 files changed

+44
-15
lines changed

4 files changed

+44
-15
lines changed

ingress/origin_proxy.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ingress
22

33
import (
4+
"fmt"
45
"net"
56
"net/http"
67

@@ -49,7 +50,13 @@ func (o *httpService) RoundTrip(req *http.Request) (*http.Response, error) {
4950
}
5051

5152
func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
52-
return o.resp, nil
53+
resp := &http.Response{
54+
StatusCode: o.code,
55+
Status: fmt.Sprintf("%d %s", o.code, http.StatusText(o.code)),
56+
Body: new(NopReadCloser),
57+
}
58+
59+
return resp, nil
5360
}
5461

5562
func (o *rawTCPService) EstablishConnection(dest string) (OriginConnection, error) {

ingress/origin_service.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,20 +238,15 @@ func (o helloWorld) MarshalJSON() ([]byte, error) {
238238
// statusCode is an OriginService that just responds with a given HTTP status.
239239
// Typical use-case is "user wants the catch-all rule to just respond 404".
240240
type statusCode struct {
241-
resp *http.Response
241+
code int
242242
}
243243

244244
func newStatusCode(status int) statusCode {
245-
resp := &http.Response{
246-
StatusCode: status,
247-
Status: fmt.Sprintf("%d %s", status, http.StatusText(status)),
248-
Body: new(NopReadCloser),
249-
}
250-
return statusCode{resp: resp}
245+
return statusCode{code: status}
251246
}
252247

253248
func (o *statusCode) String() string {
254-
return fmt.Sprintf("http_status:%d", o.resp.StatusCode)
249+
return fmt.Sprintf("http_status:%d", o.code)
255250
}
256251

257252
func (o *statusCode) start(

proxy/proxy.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/pkg/errors"
1212
"github.com/rs/zerolog"
1313
"go.opentelemetry.io/otel/attribute"
14-
"go.opentelemetry.io/otel/codes"
1514
"go.opentelemetry.io/otel/trace"
1615

1716
"github.com/cloudflare/cloudflared/carrier"
@@ -197,10 +196,11 @@ func (p *Proxy) proxyHTTPRequest(
197196
_, ttfbSpan := tr.Tracer().Start(tr.Context(), "ttfb_origin")
198197
resp, err := httpService.RoundTrip(roundTripReq)
199198
if err != nil {
200-
tracing.EndWithStatus(ttfbSpan, codes.Error, "")
199+
tracing.EndWithErrorStatus(ttfbSpan, err)
201200
return errors.Wrap(err, "Unable to reach the origin service. The service may be down or it may not be responding to traffic from cloudflared")
202201
}
203-
tracing.EndWithStatus(ttfbSpan, codes.Ok, resp.Status)
202+
203+
tracing.EndWithStatusCode(ttfbSpan, resp.StatusCode)
204204
defer resp.Body.Close()
205205

206206
// resp headers can be nil

tracing/tracing.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"math"
78
"net/http"
89
"os"
910
"runtime"
@@ -29,6 +30,9 @@ const (
2930
TracerContextNameOverride = "uber-trace-id"
3031

3132
IntCloudflaredTracingHeader = "cf-int-cloudflared-tracing"
33+
34+
MaxErrorDescriptionLen = 100
35+
traceHttpStatusCodeKey = "upstreamStatusCode"
3236
)
3337

3438
var (
@@ -130,12 +134,35 @@ func (cft *TracedRequest) AddSpans(headers http.Header, log *zerolog.Logger) {
130134
headers[CanonicalCloudflaredTracingHeader] = []string{enc}
131135
}
132136

133-
// EndWithStatus will set a status for the span and then end it.
134-
func EndWithStatus(span trace.Span, code codes.Code, status string) {
137+
// EndWithErrorStatus will set a status for the span and then end it.
138+
func EndWithErrorStatus(span trace.Span, err error) {
139+
endSpan(span, -1, codes.Error, err)
140+
}
141+
142+
// EndWithStatusCode will set a status for the span and then end it.
143+
func EndWithStatusCode(span trace.Span, statusCode int) {
144+
endSpan(span, statusCode, codes.Ok, nil)
145+
}
146+
147+
// EndWithErrorStatus will set a status for the span and then end it.
148+
func endSpan(span trace.Span, upstreamStatusCode int, spanStatusCode codes.Code, err error) {
135149
if span == nil {
136150
return
137151
}
138-
span.SetStatus(code, status)
152+
153+
if upstreamStatusCode > 0 {
154+
span.SetAttributes(attribute.Int(traceHttpStatusCodeKey, upstreamStatusCode))
155+
}
156+
157+
// add error to status buf cap description
158+
errDescription := ""
159+
if err != nil {
160+
errDescription = err.Error()
161+
l := int(math.Min(float64(len(errDescription)), MaxErrorDescriptionLen))
162+
errDescription = errDescription[:l]
163+
}
164+
165+
span.SetStatus(spanStatusCode, errDescription)
139166
span.End()
140167
}
141168

0 commit comments

Comments
 (0)