Added OTEL instrumentation to Fleet's internal HTTP client. (#40568)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40564

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

- [x] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Added OpenTelemetry instrumentation to the internal HTTP client to
provide enhanced observability through distributed tracing and metrics
collection for HTTP operations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Victor Lyuboslavsky 2026-02-26 12:49:52 -06:00 committed by GitHub
parent 77eb458658
commit 2eeb11dc6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 6 deletions

View file

@ -0,0 +1 @@
* Added OTEL instrumentation to Fleet's internal HTTP client.

View file

@ -12,6 +12,7 @@ import (
"os"
"time"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"golang.org/x/oauth2"
)
@ -71,9 +72,11 @@ func NewClient(opts ...ClientOpt) *http.Client {
if co.noFollow {
cli.CheckRedirect = noFollowRedirect
}
var baseTransport http.RoundTripper
if co.tlsConf != nil {
cli.Transport = NewTransport(WithTLSConfig(co.tlsConf))
baseTransport = NewTransport(WithTLSConfig(co.tlsConf))
}
cli.Transport = otelhttp.NewTransport(baseTransport)
if co.cookieJar != nil {
cli.Jar = co.cookieJar
}
@ -125,11 +128,13 @@ func noFollowRedirect(*http.Request, []*http.Request) error {
// token for authentication (as OAuth2 static token).
func NewGithubClient() *http.Client {
if githubToken := os.Getenv("NETWORK_TEST_GITHUB_TOKEN"); githubToken != "" {
return oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(
cli := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(
&oauth2.Token{
AccessToken: githubToken,
},
))
cli.Transport = otelhttp.NewTransport(cli.Transport)
return cli
}
return NewClient()
}

View file

@ -3,18 +3,21 @@ package fleethttp
import (
"crypto/tls"
"net/http"
"reflect"
"testing"
"time"
"unsafe"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func TestClient(t *testing.T) {
cases := []struct {
name string
opts []ClientOpt
nilTransport bool
defaultInner bool
nilRedirect bool
timeout time.Duration
}{
@ -31,10 +34,14 @@ func TestClient(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
cli := NewClient(c.opts...)
if c.nilTransport {
assert.Nil(t, cli.Transport)
require.IsType(t, &otelhttp.Transport{}, cli.Transport, "outer transport should be otelhttp")
// Inspect the inner (base) transport wrapped by otelhttp via unsafe since the rt field is unexported.
rtField := reflect.ValueOf(cli.Transport).Elem().FieldByName("rt")
inner := *(*http.RoundTripper)(unsafe.Pointer(rtField.UnsafeAddr())) //nolint:gosec
if c.defaultInner {
assert.Equal(t, http.DefaultTransport, inner, "inner transport should be http.DefaultTransport")
} else {
assert.NotNil(t, cli.Transport)
assert.IsType(t, &http.Transport{}, inner, "inner transport should be a custom *http.Transport") //nolint:gocritic
}
if c.nilRedirect {
assert.Nil(t, cli.CheckRedirect)