net/http.Client
HTTP client implementation.
Add field to Transport
Definition of
http.Transport
Flag tracer internal Transport instances
All of
- Struct literal
http.Transport
- Pointer or Value
- One of
- Import path
gopkg.in/
DataDog/ dd-trace-go.v1/ ddtrace/ tracer - Import path
gopkg.in/
DataDog/ dd-trace-go.v1/ profiler
Replace the expression using the template:
{{- .AST.Type -}}{
DD__tracer_internal: true,
{{ range .AST.Elts }}{{ . }},
{{ end }}
}
Instrument Transport.RoundTrip
Function body
- Function declaration
- Function name
RoundTrip
- Is method of
*http.Transport
Introduce new declarations:
// Using the following synthetic imports:
import (
context "context"
ddtrace "gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
)
//go:linkname __dd_appsec_RASPEnabled gopkg.in/DataDog/dd-trace-go.v1/internal/appsec.RASPEnabled
func __dd_appsec_RASPEnabled() bool
//go:linkname __dd_httpsec_ProtectRoundTrip gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec.ProtectRoundTrip
func __dd_httpsec_ProtectRoundTrip(context.Context, string) error
//go:linkname __dd_tracer_SpanType gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.SpanType
func __dd_tracer_SpanType(string) ddtrace.StartSpanOption
//go:linkname __dd_tracer_ResourceName gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.ResourceName
func __dd_tracer_ResourceName(string) ddtrace.StartSpanOption
//go:linkname __dd_tracer_Tag gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.Tag
func __dd_tracer_Tag(string, any) ddtrace.StartSpanOption
//go:linkname __dd_tracer_StartSpanFromContext gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.StartSpanFromContext
func __dd_tracer_StartSpanFromContext(context.Context, string, ...ddtrace.StartSpanOption) (ddtrace.Span, context.Context)
//go:linkname __dd_tracer_WithError gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.WithError
func __dd_tracer_WithError(error) ddtrace.FinishOption
//go:linkname __dd_tracer_Inject gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.Inject
func __dd_tracer_Inject(ddtrace.SpanContext, any) error
type __dd_tracer_HTTPHeadersCarrier Header
func (c __dd_tracer_HTTPHeadersCarrier) Set(key, val string) {
Header(c).Set(key, val)
}
Record link-time dependencies on:
Prepend statements produced by the following template:
// Using the following synthetic imports:
import (
ddtrace "gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
events "gopkg.in/DataDog/dd-trace-go.v1/appsec/events"
ext "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
fmt "fmt"
globalconfig "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
math "math"
namingschema "gopkg.in/DataDog/dd-trace-go.v1/internal/namingschema"
os "os"
strconv "strconv"
)
{{- /* Largely copied from https://github.com/DataDog/dd-trace-go/blob/v1.65.0-rc.2/contrib/net/http/roundtripper.go#L28-L104 */ -}}
{{- $t := .Function.Receiver -}}
{{- $req := .Function.Argument 0 -}}
{{- $res := .Function.Result 0 -}}
{{- $err := .Function.Result 1 -}}
if !{{ $t }}.DD__tracer_internal {
resourceName := fmt.Sprintf("%s %s", {{ $req }}.Method, {{ $req }}.URL.Path)
spanName := namingschema.OpName(namingschema.HTTPClient)
// Copy the URL so we don't modify the outgoing request
url := *{{ $req }}.URL
url.User = nil // Don't include userinfo in the http.url tag
opts := []ddtrace.StartSpanOption{
__dd_tracer_SpanType(ext.SpanTypeHTTP),
__dd_tracer_ResourceName(resourceName),
__dd_tracer_Tag(ext.HTTPMethod, {{ $req }}.Method),
__dd_tracer_Tag(ext.HTTPURL, url.String()),
__dd_tracer_Tag(ext.Component, "net/http"),
__dd_tracer_Tag(ext.SpanKind, ext.SpanKindClient),
__dd_tracer_Tag(ext.NetworkDestinationName, url.Hostname()),
}
if analyticsRate := globalconfig.AnalyticsRate(); !math.IsNaN(analyticsRate) {
opts = append(opts, __dd_tracer_Tag(ext.EventSampleRate, analyticsRate))
}
if port, err := strconv.Atoi(url.Port()); err == nil {
opts = append(opts, __dd_tracer_Tag(ext.NetworkDestinationPort, port))
}
span, ctx := __dd_tracer_StartSpanFromContext({{ $req }}.Context(), spanName, opts...)
{{ $req }} = {{ $req }}.Clone(ctx)
defer func() {
if !events.IsSecurityError({{ $err }}) {
span.Finish(__dd_tracer_WithError({{ $err }}))
} else {
span.Finish()
}
}()
if {{ $err }} = __dd_tracer_Inject(span.Context(), __dd_tracer_HTTPHeadersCarrier({{ $req }}.Header)); {{ $err }} != nil {
fmt.Fprintf(os.Stderr, "contrib/net/http.Roundtrip: failed to inject http headers: %v\n", {{ $err }})
}
if __dd_appsec_RASPEnabled() {
if err := __dd_httpsec_ProtectRoundTrip(ctx, {{ $req }}.URL.String()); err != nil {
return nil, err
}
}
defer func() {
if {{ $err }} != nil {
span.SetTag("http.errors", {{ $err }}.Error())
span.SetTag(ext.Error, {{ $err }})
} else {
span.SetTag(ext.HTTPCode, strconv.Itoa({{ $res }}.StatusCode))
if {{ $res }}.StatusCode >= 500 && {{ $res}}.StatusCode < 600 {
// Treat HTTP 5XX as errors
span.SetTag("http.errors", {{ $res }}.Status)
span.SetTag(ext.Error, fmt.Errorf("%d: %s", {{ $res }}.StatusCode, StatusText({{ $res }}.StatusCode)))
}
}
}()
}
Wire context through http.Get/Head/Post/PostForm
All of
- Not
- Import path
net/
http
- One of
- Call to
http.Get
- Call to
http.Head
- Call to
http.Post
- Call to
http.PostForm
Replace the expression using the template:
// Using the following synthetic imports:
import (
instrument "github.com/DataDog/orchestrion/instrument/net/http"
)
{{- $ctx := .Function.ArgumentOfType "context.Context" -}}
{{- $req := .Function.ArgumentOfType "*net/http.Request" }}
{{- if $ctx -}}
instrument.{{ .AST.Fun.Name }}(
{{ $ctx }},
{{ range .AST.Args }}{{ . }},
{{ end }}
)
{{- else if $req -}}
instrument.{{ .AST.Fun.Name }}(
{{ $req }}.Context(),
{{ range .AST.Args }}{{ . }},
{{ end }}
)
{{- else -}}
{{ . }}
{{- end -}}