-
Notifications
You must be signed in to change notification settings - Fork 15
feat(golang): implement /otel_drop_in_extract_and_make_distant_call endpoint #7264
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,9 +27,12 @@ import ( | |
| httptrace "github.com/DataDog/dd-trace-go/contrib/net/http/v2" | ||
| dd_logrus "github.com/DataDog/dd-trace-go/contrib/sirupsen/logrus/v2" | ||
| "github.com/DataDog/dd-trace-go/v2/appsec" | ||
| ddotel "github.com/DataDog/dd-trace-go/v2/ddtrace/opentelemetry" | ||
| _ "github.com/DataDog/dd-trace-go/v2/ddtrace/opentelemetry/metric" | ||
| "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" | ||
| "github.com/DataDog/dd-trace-go/v2/profiler" | ||
| "go.opentelemetry.io/otel" | ||
| "go.opentelemetry.io/otel/propagation" | ||
| ) | ||
|
|
||
| func main() { | ||
|
|
@@ -195,6 +198,63 @@ func main() { | |
| w.Write(jsonResponse) | ||
| }) | ||
|
|
||
| mux.HandleFunc("/otel_drop_in_extract_and_make_distant_call", func(w http.ResponseWriter, r *http.Request) { | ||
| url := r.URL.Query().Get("url") | ||
| if url == "" { | ||
| w.Write([]byte("OK")) | ||
| return | ||
| } | ||
|
|
||
| // Extract the incoming trace context via the OTel propagation API and start a new span. | ||
| // We intentionally use context.Background() instead of r.Context(): r.Context() already | ||
| // carries the server span created by the HTTP middleware, which would cause the dd-trace-go | ||
| // OTel bridge to parent otel_extract_distant_call to that span rather than creating a | ||
| // fresh root with a span link (the expected restart behavior). | ||
| otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) | ||
| propagator := otel.GetTextMapPropagator() | ||
| ctx := propagator.Extract(context.Background(), propagation.HeaderCarrier(r.Header)) | ||
|
|
||
| p := ddotel.NewTracerProvider() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When this endpoint is hit, Useful? React with 👍 / 👎. |
||
| otel.SetTracerProvider(p) | ||
| otelTracer := p.Tracer("") | ||
| ctx, span := otelTracer.Start(ctx, "otel_extract_distant_call") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎. |
||
| defer span.End() | ||
|
|
||
| req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) | ||
| if ddSpan, ok := tracer.SpanFromContext(ctx); ok { | ||
| tracer.Inject(ddSpan.Context(), tracer.HTTPHeadersCarrier(req.Header)) | ||
| } | ||
| propagator.Inject(ctx, propagation.HeaderCarrier(req.Header)) | ||
|
|
||
| res, err := http.DefaultClient.Do(req) | ||
| if err != nil { | ||
| logrus.Fatalln("client.Do", err) | ||
| } | ||
| defer res.Body.Close() | ||
|
|
||
| requestHeaders := make(map[string]string, len(req.Header)) | ||
| for key, values := range req.Header { | ||
| requestHeaders[strings.ToLower(key)] = strings.Join(values, ",") | ||
| } | ||
|
|
||
| responseHeaders := make(map[string]string, len(res.Header)) | ||
| for key, values := range res.Header { | ||
| responseHeaders[key] = strings.Join(values, ",") | ||
| } | ||
|
|
||
| jsonResponse, err := json.Marshal(struct { | ||
| URL string `json:"url"` | ||
| StatusCode int `json:"status_code"` | ||
| RequestHeaders map[string]string `json:"request_headers"` | ||
| ResponseHeaders map[string]string `json:"response_headers"` | ||
| }{URL: url, StatusCode: res.StatusCode, RequestHeaders: requestHeaders, ResponseHeaders: responseHeaders}) | ||
| if err != nil { | ||
| logrus.Fatalln(err) | ||
| } | ||
| w.Header().Set("Content-Type", "application/json") | ||
| w.Write(jsonResponse) | ||
| }) | ||
|
|
||
| mux.HandleFunc("/headers/", headers) | ||
| mux.HandleFunc("/headers", headers) | ||
|
|
||
|
|
||
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 conflicting-header cases in
Test_ExtractBehavior_Restart_Otelsend both Datadog and W3C headers while the scenario configures extraction asdatadog,tracecontext,baggage, and the assertions expect the restart span link to come from the Datadog context. This line replaces the OTel propagator with onlyTraceContextandBaggage, so the OTel extraction ignoresx-datadog-*and cannot produce the expected Datadog restart link when the traceparent differs. The same W3C-only propagator was added to each Go weblog handler.Useful? React with 👍 / 👎.