Skip to content
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

Fix panic in otelhttptrace #3892

Merged
merged 4 commits into from Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Fixed

- AWS XRay Remote Sampling to cap quotaBalance to 1x quota in `go.opentelemetry.io/contrib/samplers/aws/xray`. (#3651, #3652)
- Do not panic when the HTTP request has the "Expect: 100-continue" header in `go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace`. (#3892)

## [1.17.0/0.42.0/0.11.0] - 2023-05-23

Expand Down
Expand Up @@ -370,7 +370,7 @@ func (ct *clientTracer) got100Continue() {
func (ct *clientTracer) wait100Continue() {
span := ct.root
if ct.useSpans {
span = ct.span("http.receive")
span = ct.span("http.send")
}
span.AddEvent("GOT 100 - Wait")
}
Expand Down
Expand Up @@ -15,11 +15,13 @@
package test

import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"net/http/httptrace"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -504,3 +506,40 @@ func TestHTTPRequestWithTraceContext(t *testing.T) {
require.Equal(t, parent.SpanContext().TraceID(), getconn.SpanContext().TraceID())
require.Equal(t, parent.SpanContext().SpanID(), getconn.Parent().SpanID())
}

func TestHTTPRequestWithExpect100Continue(t *testing.T) {
fixture := prepareClientTraceTest(t)

ctx, span := otel.Tracer("oteltest").Start(context.Background(), "root")
ctx = httptrace.WithClientTrace(ctx, otelhttptrace.NewClientTrace(ctx))

req, err := http.NewRequestWithContext(ctx, http.MethodPost, fixture.URL, bytes.NewReader([]byte("test")))
require.NoError(t, err)

// Set Expect: 100-continue
req.Header.Set("Expect", "100-continue")
resp, err := fixture.Client.Do(req)
require.NoError(t, err)
require.NoError(t, resp.Body.Close())
span.End()

// Wait for http.send span as per https://pkg.go.dev/net/http/httptrace#ClientTrace:
// Functions may be called concurrently from different goroutines and some may be called
// after the request has completed
var httpSendSpan trace.ReadOnlySpan
require.Eventually(t, func() bool {
var ok bool
httpSendSpan, ok = getSpanFromRecorder(fixture.SpanRecorder, "http.send")
return ok
}, 5*time.Second, 10*time.Millisecond)

// Found http.send span must contain "GOT 100 - Wait" event
found := false
for _, v := range httpSendSpan.Events() {
if v.Name == "GOT 100 - Wait" {
found = true
break
}
}
require.True(t, found)
}