From cbac5296c51eaf0a3b7f4c62cb3630c19d62227f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Jure=C4=8Dko?= Date: Mon, 15 May 2023 17:41:06 +0200 Subject: [PATCH] Delete old oteldd/httpclient --- .../buffer/dependencies/dependencies.go | 2 +- .../service/common/httpclient/httpclient.go | 70 ++++------- .../templates/api/dependencies/service.go | 2 +- internal/pkg/telemetry/oteldd/httpclient.go | 118 ------------------ 4 files changed, 28 insertions(+), 164 deletions(-) delete mode 100644 internal/pkg/telemetry/oteldd/httpclient.go diff --git a/internal/pkg/service/buffer/dependencies/dependencies.go b/internal/pkg/service/buffer/dependencies/dependencies.go index a08124937a..89e3136fc2 100644 --- a/internal/pkg/service/buffer/dependencies/dependencies.go +++ b/internal/pkg/service/buffer/dependencies/dependencies.go @@ -46,8 +46,8 @@ func NewServiceDeps( // Create base HTTP client for all API requests to other APIs httpClient := httpclient.New( + httpclient.WithTelemetry(tel), httpclient.WithUserAgent(userAgent), - httpclient.WithEnvs(envs), func(c *httpclient.Config) { if cfg.Debug { httpclient.WithDebugOutput(logger.DebugWriter())(c) diff --git a/internal/pkg/service/common/httpclient/httpclient.go b/internal/pkg/service/common/httpclient/httpclient.go index 2c0fdabdac..a35d0b1535 100644 --- a/internal/pkg/service/common/httpclient/httpclient.go +++ b/internal/pkg/service/common/httpclient/httpclient.go @@ -3,37 +3,33 @@ package httpclient import ( "io" - "net/http" - "strings" "github.com/keboola/go-client/pkg/client" - ddHttp "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http" - "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" - "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" + "github.com/keboola/go-client/pkg/client/trace" + "github.com/keboola/go-client/pkg/client/trace/otel" + "go.opentelemetry.io/contrib/propagators/b3" - "github.com/keboola/keboola-as-code/internal/pkg/env" - "github.com/keboola/keboola-as-code/internal/pkg/telemetry/oteldd" - "github.com/keboola/keboola-as-code/internal/pkg/utils/strhelper" + "github.com/keboola/keboola-as-code/internal/pkg/telemetry" ) type Config struct { userAgent string - envs env.Provider + telemetry telemetry.Telemetry debugWriter io.Writer dumpWriter io.Writer } type Option func(c *Config) -func WithEnvs(envs env.Provider) Option { +func WithUserAgent(v string) Option { return func(c *Config) { - c.envs = envs + c.userAgent = v } } -func WithUserAgent(v string) Option { +func WithTelemetry(v telemetry.Telemetry) Option { return func(c *Config) { - c.userAgent = v + c.telemetry = v } } @@ -59,48 +55,34 @@ func New(opts ...Option) client.Client { // Force HTTP2 transport transport := client.HTTP2Transport() - // DataDog low-level tracing (raw http requests) - if conf.envs != nil && oteldd.IsDataDogEnabled(conf.envs) { - transport = ddHttp.WrapRoundTripper( - transport, - ddHttp.WithBefore(func(request *http.Request, span ddtrace.Span) { - // We use "http.request" operation name for request to the API, - // so requests to other API must have different operation name. - span.SetOperationName("kac.api.client.http.request") - span.SetTag("http.host", request.URL.Host) - if dotPos := strings.IndexByte(request.URL.Host, '.'); dotPos > 0 { - // E.g. connection, encryption, scheduler ... - span.SetTag("http.hostPrefix", request.URL.Host[:dotPos]) - } - span.SetTag(ext.EventSampleRate, 1.0) - span.SetTag(ext.HTTPURL, request.URL.Redacted()) - span.SetTag("http.path", request.URL.Path) - span.SetTag("http.query", request.URL.Query().Encode()) - }), - ddHttp.RTWithResourceNamer(func(r *http.Request) string { - // Set resource name to request path - return strhelper.MustURLPathUnescape(r.URL.RequestURI()) - })) - } - // Create client cl := client.New(). WithTransport(transport). WithUserAgent(conf.userAgent) + // Enable telemetry + if conf.telemetry != nil { + cl = cl.WithTelemetry( + conf.telemetry.TracerProvider(), + conf.telemetry.MeterProvider(), + otel.WithRedactedHeaders("X-StorageAPI-Token", "X-KBC-ManageApiToken"), + otel.WithPropagators( + // DataDog supports multiple propagations: tracecontext, B3, legacy DataDog, ... + // W3C tracecontext propagator (propagation.TraceContext{}) is not working with the Storage API dd-trace-php , + // so the B3 propagator is used. + b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)), + ), + ) + } + // Log each HTTP client request/response as debug message if conf.debugWriter != nil { - cl = cl.AndTrace(client.LogTracer(conf.debugWriter)) + cl = cl.AndTrace(trace.LogTracer(conf.debugWriter)) } // Dump each HTTP client request/response body if conf.dumpWriter != nil { - cl = cl.AndTrace(client.DumpTracer(conf.dumpWriter)) - } - - // DataDog high-level tracing (api client requests) - if conf.envs != nil && oteldd.IsDataDogEnabled(conf.envs) { - cl = cl.AndTrace(oteldd.DDTraceFactory()) + cl = cl.AndTrace(trace.DumpTracer(conf.dumpWriter)) } return cl diff --git a/internal/pkg/service/templates/api/dependencies/service.go b/internal/pkg/service/templates/api/dependencies/service.go index 66ab4061c6..8e402e66d8 100644 --- a/internal/pkg/service/templates/api/dependencies/service.go +++ b/internal/pkg/service/templates/api/dependencies/service.go @@ -46,8 +46,8 @@ func NewServiceDeps( // Create base HTTP client for all API requests to other APIs httpClient := httpclient.New( + httpclient.WithTelemetry(tel), httpclient.WithUserAgent(userAgent), - httpclient.WithEnvs(envs), func(c *httpclient.Config) { if cfg.Debug { httpclient.WithDebugOutput(logger.DebugWriter())(c) diff --git a/internal/pkg/telemetry/oteldd/httpclient.go b/internal/pkg/telemetry/oteldd/httpclient.go deleted file mode 100644 index be1e38e3fb..0000000000 --- a/internal/pkg/telemetry/oteldd/httpclient.go +++ /dev/null @@ -1,118 +0,0 @@ -package oteldd - -import ( - "context" - "net/http" - "reflect" - "strings" - "time" - - "github.com/keboola/go-client/pkg/client" - "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" - ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" - - "github.com/keboola/keboola-as-code/internal/pkg/utils/strhelper" -) - -// DDTraceFactory provides TraceFactory for high-level tracing of the API client requests. -func DDTraceFactory() client.TraceFactory { - return func() *client.Trace { - t := &client.Trace{} - - // Api request - var ctx context.Context - var clientRequest client.HTTPRequest // high-level request - var resultType string - - var requestSpan ddtracer.Span - var parsingSpan ddtracer.Span - var retryDelaySpan ddtracer.Span - - t.GotRequest = func(c context.Context, r client.HTTPRequest) context.Context { - clientRequest = r - if v := reflect.TypeOf(clientRequest.ResultDef()); v != nil { - resultType = v.String() - } - requestSpan, ctx = ddtracer.StartSpanFromContext( - c, - "kac.api.client.request", - ddtracer.ResourceName(strhelper.MustURLPathUnescape(clientRequest.URL())), - ddtracer.SpanType("kac.api.client"), - ddtracer.AnalyticsRate(1.0), - ) - - // Set tags - requestSpan.SetTag("kac.api.client.request.method", clientRequest.Method()) - requestSpan.SetTag("kac.api.client.request.url", strhelper.MustURLPathUnescape(clientRequest.URL())) - requestSpan.SetTag("kac.api.client.request.result_type", resultType) - for k, v := range clientRequest.QueryParams() { - requestSpan.SetTag("kac.api.client.request.params.query."+k, v) - } - for k, v := range clientRequest.PathParams() { - requestSpan.SetTag("kac.api.client.request.params.path."+k, v) - } - - return ctx - } - t.HTTPRequestStart = func(r *http.Request) { - // Finish retry delay span - if retryDelaySpan != nil { - requestSpan.Finish() - retryDelaySpan = nil - } - - // Update client request span - requestSpan.SetTag("http.host", r.URL.Host) - if dotPos := strings.IndexByte(r.URL.Host, '.'); dotPos > 0 { - // E.g. connection, encryption, scheduler ... - requestSpan.SetTag("http.hostPrefix", r.URL.Host[:dotPos]) - } - requestSpan.SetTag(ext.HTTPMethod, r.Method) - requestSpan.SetTag(ext.HTTPURL, r.URL.Redacted()) - requestSpan.SetTag("http.path", r.URL.Path) - requestSpan.SetTag("http.query", r.URL.Query().Encode()) - } - t.HTTPRequestDone = func(response *http.Response, err error) { - if response != nil { - // Set status code - requestSpan.SetTag(ext.HTTPCode, response.StatusCode) - } - - if err == nil { - // Create span for body parsing, if the request was successful - parsingSpan, _ = ddtracer.StartSpanFromContext( - ctx, - "kac.api.client.request.parsing", - ddtracer.ResourceName(strhelper.MustURLPathUnescape(clientRequest.URL())), - ddtracer.SpanType("kac.api.client"), - ) - } - } - t.RequestProcessed = func(result any, err error) { - // Finish retry span, if any (retry was not performed, an error occurred) - if retryDelaySpan != nil { - requestSpan.Finish(ddtracer.WithError(err)) - retryDelaySpan = nil - } - // Finish parsing span, if any - if parsingSpan != nil { - parsingSpan.Finish(ddtracer.WithError(err)) - } - requestSpan.Finish(ddtracer.WithError(err)) - } - - // Retry - t.HTTPRequestRetry = func(attempt int, delay time.Duration) { - retryDelaySpan, _ = ddtracer.StartSpanFromContext( - ctx, - "kac.api.client.retry.delay", - ddtracer.ResourceName(strhelper.MustURLPathUnescape(clientRequest.URL())), - ddtracer.SpanType("kac.api.client"), - ddtracer.Tag("retry.attempt", attempt), - ddtracer.Tag("retry.delay_ms", delay.Milliseconds()), - ddtracer.Tag("retry.delay_string", delay.String()), - ) - } - return t - } -}