TUN-6250: Add upstream response status code to tracing span attributes

This commit is contained in:
João Oliveirinha 2022-05-18 12:11:38 +01:00
parent 26a7b59f6f
commit 6f78ccde04
4 changed files with 44 additions and 15 deletions

View File

@ -1,6 +1,7 @@
package ingress package ingress
import ( import (
"fmt"
"net" "net"
"net/http" "net/http"
@ -49,7 +50,13 @@ func (o *httpService) RoundTrip(req *http.Request) (*http.Response, error) {
} }
func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) { func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
return o.resp, nil resp := &http.Response{
StatusCode: o.code,
Status: fmt.Sprintf("%d %s", o.code, http.StatusText(o.code)),
Body: new(NopReadCloser),
}
return resp, nil
} }
func (o *rawTCPService) EstablishConnection(dest string) (OriginConnection, error) { func (o *rawTCPService) EstablishConnection(dest string) (OriginConnection, error) {

View File

@ -238,20 +238,15 @@ func (o helloWorld) MarshalJSON() ([]byte, error) {
// statusCode is an OriginService that just responds with a given HTTP status. // statusCode is an OriginService that just responds with a given HTTP status.
// Typical use-case is "user wants the catch-all rule to just respond 404". // Typical use-case is "user wants the catch-all rule to just respond 404".
type statusCode struct { type statusCode struct {
resp *http.Response code int
} }
func newStatusCode(status int) statusCode { func newStatusCode(status int) statusCode {
resp := &http.Response{ return statusCode{code: status}
StatusCode: status,
Status: fmt.Sprintf("%d %s", status, http.StatusText(status)),
Body: new(NopReadCloser),
}
return statusCode{resp: resp}
} }
func (o *statusCode) String() string { func (o *statusCode) String() string {
return fmt.Sprintf("http_status:%d", o.resp.StatusCode) return fmt.Sprintf("http_status:%d", o.code)
} }
func (o *statusCode) start( func (o *statusCode) start(

View File

@ -11,7 +11,6 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"github.com/cloudflare/cloudflared/carrier" "github.com/cloudflare/cloudflared/carrier"
@ -197,10 +196,11 @@ func (p *Proxy) proxyHTTPRequest(
_, ttfbSpan := tr.Tracer().Start(tr.Context(), "ttfb_origin") _, ttfbSpan := tr.Tracer().Start(tr.Context(), "ttfb_origin")
resp, err := httpService.RoundTrip(roundTripReq) resp, err := httpService.RoundTrip(roundTripReq)
if err != nil { if err != nil {
tracing.EndWithStatus(ttfbSpan, codes.Error, "") tracing.EndWithErrorStatus(ttfbSpan, err)
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") 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")
} }
tracing.EndWithStatus(ttfbSpan, codes.Ok, resp.Status)
tracing.EndWithStatusCode(ttfbSpan, resp.StatusCode)
defer resp.Body.Close() defer resp.Body.Close()
// resp headers can be nil // resp headers can be nil

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math"
"net/http" "net/http"
"os" "os"
"runtime" "runtime"
@ -29,6 +30,9 @@ const (
TracerContextNameOverride = "uber-trace-id" TracerContextNameOverride = "uber-trace-id"
IntCloudflaredTracingHeader = "cf-int-cloudflared-tracing" IntCloudflaredTracingHeader = "cf-int-cloudflared-tracing"
MaxErrorDescriptionLen = 100
traceHttpStatusCodeKey = "upstreamStatusCode"
) )
var ( var (
@ -130,12 +134,35 @@ func (cft *TracedRequest) AddSpans(headers http.Header, log *zerolog.Logger) {
headers[CanonicalCloudflaredTracingHeader] = []string{enc} headers[CanonicalCloudflaredTracingHeader] = []string{enc}
} }
// EndWithStatus will set a status for the span and then end it. // EndWithErrorStatus will set a status for the span and then end it.
func EndWithStatus(span trace.Span, code codes.Code, status string) { func EndWithErrorStatus(span trace.Span, err error) {
endSpan(span, -1, codes.Error, err)
}
// EndWithStatusCode will set a status for the span and then end it.
func EndWithStatusCode(span trace.Span, statusCode int) {
endSpan(span, statusCode, codes.Ok, nil)
}
// EndWithErrorStatus will set a status for the span and then end it.
func endSpan(span trace.Span, upstreamStatusCode int, spanStatusCode codes.Code, err error) {
if span == nil { if span == nil {
return return
} }
span.SetStatus(code, status)
if upstreamStatusCode > 0 {
span.SetAttributes(attribute.Int(traceHttpStatusCodeKey, upstreamStatusCode))
}
// add error to status buf cap description
errDescription := ""
if err != nil {
errDescription = err.Error()
l := int(math.Min(float64(len(errDescription)), MaxErrorDescriptionLen))
errDescription = errDescription[:l]
}
span.SetStatus(spanStatusCode, errDescription)
span.End() span.End()
} }