Replies: 9 comments 1 reply
-
Can you please create a Minimal, Reproducible Example that reproduces the issue you are encountering? |
Beta Was this translation helpful? Give feedback.
-
I'll do ya one better, here's a full program to just copy paste right in a main.go file. All you have to do is run it after running go mod tidy and such. |
Beta Was this translation helpful? Give feedback.
-
In the example you provided, the HTTP span has no parent, since no span is created before it. So the parent being empty/invalid is the expected behavior. If I create a span before making the HTTP request: diff --git a/tmp/main.go b/tmp/main.go
index 223283e..91668e8 100644
--- a/tmp/main.go
+++ b/tmp/main.go
@@ -25,8 +25,10 @@ func main() {
func issueRequests() error {
urls := []string{"https://www.google.com", "https://www.facebook.com", "https://www.yahoo.com"}
client := &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
+ tracer := otel.Tracer("main")
- ctx := context.TODO()
+ ctx, span := tracer.Start(context.Background(), "issueRequests")
+ defer span.End()
for _, v := range urls {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, v, nil)
if err != nil { Then, the span created by otelhttp has a parent, and that parent is indeed displayed by the exporter: JSON Output{
"Name": "HTTP GET",
"SpanContext": {
"TraceID": "f36f3a4ea90e9b994c19a3cd9dbbdfbe",
"SpanID": "a3a139a7ac43a6bf",
"TraceFlags": "01",
"TraceState": "",
"Remote": false
},
"Parent": {
"TraceID": "f36f3a4ea90e9b994c19a3cd9dbbdfbe",
"SpanID": "8d341b5494fe4f9e",
"TraceFlags": "01",
"TraceState": "",
"Remote": false
},
"SpanKind": 3,
"StartTime": "2024-10-17T11:05:40.829184+02:00",
"EndTime": "2024-10-17T11:05:40.946134625+02:00",
"Attributes": [
{
"Key": "http.method",
"Value": {
"Type": "STRING",
"Value": "GET"
}
},
{
"Key": "http.url",
"Value": {
"Type": "STRING",
"Value": "https://www.google.com"
}
},
{
"Key": "net.peer.name",
"Value": {
"Type": "STRING",
"Value": "www.google.com"
}
},
{
"Key": "http.status_code",
"Value": {
"Type": "INT64",
"Value": 200
}
}
],
"Events": null,
"Links": null,
"Status": {
"Code": "Unset",
"Description": ""
},
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"ChildSpanCount": 0,
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "unknown_service:main"
}
},
{
"Key": "telemetry.sdk.language",
"Value": {
"Type": "STRING",
"Value": "go"
}
},
{
"Key": "telemetry.sdk.name",
"Value": {
"Type": "STRING",
"Value": "opentelemetry"
}
},
{
"Key": "telemetry.sdk.version",
"Value": {
"Type": "STRING",
"Value": "1.31.0"
}
}
],
"InstrumentationScope": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"Version": "0.56.0",
"SchemaURL": ""
},
"InstrumentationLibrary": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"Version": "0.56.0",
"SchemaURL": ""
}
}
{
"Name": "HTTP GET",
"SpanContext": {
"TraceID": "f36f3a4ea90e9b994c19a3cd9dbbdfbe",
"SpanID": "92a4d6f4f87840e5",
"TraceFlags": "01",
"TraceState": "",
"Remote": false
},
"Parent": {
"TraceID": "f36f3a4ea90e9b994c19a3cd9dbbdfbe",
"SpanID": "8d341b5494fe4f9e",
"TraceFlags": "01",
"TraceState": "",
"Remote": false
},
"SpanKind": 3,
"StartTime": "2024-10-17T11:05:40.94616+02:00",
"EndTime": "2024-10-17T11:05:41.230872334+02:00",
"Attributes": [
{
"Key": "http.method",
"Value": {
"Type": "STRING",
"Value": "GET"
}
},
{
"Key": "http.url",
"Value": {
"Type": "STRING",
"Value": "https://www.facebook.com"
}
},
{
"Key": "net.peer.name",
"Value": {
"Type": "STRING",
"Value": "www.facebook.com"
}
},
{
"Key": "http.status_code",
"Value": {
"Type": "INT64",
"Value": 200
}
}
],
"Events": null,
"Links": null,
"Status": {
"Code": "Unset",
"Description": ""
},
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"ChildSpanCount": 0,
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "unknown_service:main"
}
},
{
"Key": "telemetry.sdk.language",
"Value": {
"Type": "STRING",
"Value": "go"
}
},
{
"Key": "telemetry.sdk.name",
"Value": {
"Type": "STRING",
"Value": "opentelemetry"
}
},
{
"Key": "telemetry.sdk.version",
"Value": {
"Type": "STRING",
"Value": "1.31.0"
}
}
],
"InstrumentationScope": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"Version": "0.56.0",
"SchemaURL": ""
},
"InstrumentationLibrary": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"Version": "0.56.0",
"SchemaURL": ""
}
} |
Beta Was this translation helpful? Give feedback.
-
Oh ok I see. None of the documentation samples pointed this out, so I was wondering if this was something I was missing. Appreciate it, thanks! |
Beta Was this translation helpful? Give feedback.
-
Is there any way to suppress logging for just the root span? I only want the children of the root span to be logged |
Beta Was this translation helpful? Give feedback.
-
You would have to setup a custom exporter, or processor to skip some spans from being exported. |
Beta Was this translation helpful? Give feedback.
-
Stderr is supposed to be used yes? Also, I have a dumb question: I've created and injected a custom log exporter by implementing the /sdk/log -> Exporter interface, and passing in the new impl to the logger provider, but I can't seem to figure out how to catch emitted logs. Are they emitted every time a consuming application writes log.Println(), or fmt.Printn()? |
Beta Was this translation helpful? Give feedback.
-
Not in production. Only for light debugging.
I invite you to look at the doc and implementation. You may want to have a look at the dice example, which is a sample app that emits every signal. |
Beta Was this translation helpful? Give feedback.
-
Figured this out. In case someone else should happen upon this thread, I'll explain what I was missing. The "Export" method wasn't being called b/c I didn't know that I had to use a logger (slog.Logger is what I used) that is instrumented with an OTEL handler. Once configured all calls to slogger.Log(..) will trigger the "Export" method (depending on your processor, simple will call export each time a record is created). I was thinking that all calls to the log.Println(..) would trigger this method, but it does not. |
Beta Was this translation helpful? Give feedback.
-
Description
OTELHTTP transport not propagating trace and span IDs, and is leaving the parent blank. The image shows the text details.
Environment
Steps To Reproduce
Inject transport inside of http.Client
http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
Use request with context
req = req.WithContext(ctx)
Fire off multiple requests with the same context and notice that new span and trace IDs are generated for each request.
Expected behavior
I would expect to have the trace and span IDs propagate down from first HTTP request to all subsequent requests. The parent trace should also be filled out.
Beta Was this translation helpful? Give feedback.
All reactions