Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions contrib/go.uber.org/zap/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.

package zap_test

import (
"context"

"go.uber.org/zap"

zaptrace "github.com/DataDog/dd-trace-go/v2/contrib/go.uber.org/zap"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
)

func ExampleWithTraceFields() {
// start the DataDog tracer
tracer.Start()
defer tracer.Stop()

// create the application logger
logger, _ := zap.NewProduction()

// start a new span
span, ctx := tracer.StartSpanFromContext(context.Background(), "ExampleWithTraceCorrelation")
defer span.Finish()

// log a message using the context containing span information
zaptrace.WithTraceFields(ctx, logger).Info("this is a log with tracing information")
}
60 changes: 60 additions & 0 deletions contrib/go.uber.org/zap/zap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.

// Package zap provides functions to correlate logs and traces using go.uber.org/zap package (https://github.com/uber-go/zap).
package zap // import "github.com/DataDog/dd-trace-go/v2/contrib/go.uber.org/zap"

import (
"context"
"strconv"

"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
"github.com/DataDog/dd-trace-go/v2/instrumentation"
"github.com/DataDog/dd-trace-go/v2/instrumentation/options"

"go.uber.org/zap"
)

var instr *instrumentation.Instrumentation

type config struct {
log128bits bool
}

var cfg = newConfig()

func newConfig() *config {
return &config{
log128bits: options.GetBoolEnv("DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED", true),
}
}

func init() {
instr = instrumentation.Load(instrumentation.PackageUberZap)
}

// WithTraceFields looks for an active span in the provided context and if found, it returns a new *zap.Logger with
// traceID and spanID keys set.
func WithTraceFields(ctx context.Context, logger *zap.Logger) *zap.Logger {
span, ok := tracer.SpanFromContext(ctx)
if !ok {
return logger
}

var traceID string
if cfg.log128bits && span.Context().TraceID() != tracer.TraceIDZero {
traceID = span.Context().TraceID()
} else {
traceID = strconv.FormatUint(span.Context().TraceIDLower(), 10)
}

spanID := strconv.FormatUint(span.Context().SpanID(), 10)

return logger.With(
zap.String(ext.LogKeyTraceID, traceID),
zap.String(ext.LogKeySpanID, spanID),
)
}
86 changes: 86 additions & 0 deletions contrib/go.uber.org/zap/zap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.

package zap

import (
"context"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"

"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
"github.com/DataDog/dd-trace-go/v2/instrumentation/testutils"
)

func TestWithTraceFields(t *testing.T) {
tracer.Start(
tracer.WithLogger(testutils.DiscardLogger()),
)
defer tracer.Stop()

// start a new span
span, ctx := tracer.StartSpanFromContext(context.Background(), "test")
defer span.Finish()

observed, logs := observer.New(zapcore.InfoLevel)

logger := zap.New(observed)
logger = WithTraceFields(ctx, logger)
logger.Info("some message")

// By default, 128-bit trace IDs are enabled
traceID := span.Context().TraceID()
spanID := strconv.FormatUint(span.Context().SpanID(), 10)

require.Equal(t, 1, logs.Len())
infoLog := logs.All()[0]

require.Len(t, infoLog.Context, 2)
assert.Equal(t, "dd.trace_id", infoLog.Context[0].Key)
assert.Equal(t, traceID, infoLog.Context[0].String)
assert.Equal(t, "dd.span_id", infoLog.Context[1].Key)
assert.Equal(t, spanID, infoLog.Context[1].String)
}

func TestWithTraceFields128BitDisabled(t *testing.T) {
t.Setenv("DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED", "false")

// Re-initialize to account for race condition between setting env var in the test and reading it in the contrib
cfg = newConfig()

tracer.Start(
tracer.WithLogger(testutils.DiscardLogger()),
)
defer tracer.Stop()

// start a new span
span, ctx := tracer.StartSpanFromContext(context.Background(), "test")
defer span.Finish()

observed, logs := observer.New(zapcore.InfoLevel)

logger := zap.New(observed)
logger = WithTraceFields(ctx, logger)
logger.Info("some message")

// With 128-bit disabled, should use 64-bit trace ID
traceID := strconv.FormatUint(span.Context().TraceIDLower(), 10)
spanID := strconv.FormatUint(span.Context().SpanID(), 10)

require.Equal(t, 1, logs.Len())
infoLog := logs.All()[0]

require.Len(t, infoLog.Context, 2)
assert.Equal(t, "dd.trace_id", infoLog.Context[0].Key)
assert.Equal(t, traceID, infoLog.Context[0].String)
assert.Equal(t, "dd.span_id", infoLog.Context[1].Key)
assert.Equal(t, spanID, infoLog.Context[1].String)
}
1 change: 1 addition & 0 deletions ddtrace/tracer/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ var contribIntegrations = map[string]struct {
"github.com/uptrace/bun": {"Bun", false},
"github.com/urfave/negroni": {"Negroni", false},
"github.com/valyala/fasthttp": {"FastHTTP", false},
"go.uber.org/zap": {"go.uber.org/zap", false},
"github.com/valkey-io/valkey-go": {"Valkey", false},
}

Expand Down
2 changes: 1 addition & 1 deletion ddtrace/tracer/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func TestAgentIntegration(t *testing.T) {
defer clearIntegrationsForTests()

cfg.loadContribIntegrations(nil)
assert.Equal(t, 55, len(cfg.integrations))
assert.Equal(t, 56, len(cfg.integrations))
for integrationName, v := range cfg.integrations {
assert.False(t, v.Instrumented, "integrationName=%s", integrationName)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
go.uber.org/goleak v1.3.0
go.uber.org/zap v1.27.0
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0
golang.org/x/mod v0.29.0
Expand Down Expand Up @@ -98,7 +99,6 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/mock v0.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/text v0.30.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
Expand Down
5 changes: 5 additions & 0 deletions instrumentation/instrumentation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ func TestInstrumentation_AnalyticsRate(t *testing.T) {
t.Skip("Lambda contrib does not implement analytics functionality")
return
}
// Skip logging integrations - they don't generate spans, just correlate logs with traces
if pkg == PackageSirupsenLogrus || pkg == PackageLogSlog || pkg == PackageUberZap {
t.Skip("Logging integrations do not implement analytics functionality")
return
}

instr := Load(pkg)

Expand Down
5 changes: 5 additions & 0 deletions instrumentation/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const (
PackageUptraceBun Package = "uptrace/bun"
PackageLogSlog Package = "log/slog"
PackageModelContextProtocolGoSDK Package = "modelcontextprotocol/go-sdk"
PackageUberZap Package = "go.uber.org/zap"

PackageValkeyIoValkeyGo Package = "valkey-io/valkey-go"
PackageEnvoyProxyGoControlPlane Package = "envoyproxy/go-control-plane"
Expand Down Expand Up @@ -815,6 +816,10 @@ var packages = map[Package]PackageInfo{
TracedPackage: "log/slog",
IsStdLib: true,
},
PackageUberZap: {
TracedPackage: "go.uber.org/zap",
EnvVarPrefix: "ZAP",
},
PackageValkeyIoValkeyGo: {
TracedPackage: "github.com/valkey-io/valkey-go",
EnvVarPrefix: "VALKEY",
Expand Down
3 changes: 2 additions & 1 deletion internal/env/supported_configurations.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 14 additions & 11 deletions internal/env/supported_configurations.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@
"DD_CIVISIBILITY_SUBTEST_FEATURES_ENABLED": [
"A"
],
"DD_CIVISIBILITY_USE_NOOP_TRACER": [
"DD_CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT": [
"A"
],
"DD_CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT": [
"DD_CIVISIBILITY_USE_NOOP_TRACER": [
"A"
],
"DD_CUSTOM_TRACE_ID": [
Expand Down Expand Up @@ -219,6 +219,9 @@
"DD_LOGGING_RATE": [
"A"
],
"DD_METRICS_OTEL_ENABLED": [
"A"
],
"DD_PIPELINE_EXECUTION_ID": [
"A"
],
Expand Down Expand Up @@ -633,34 +636,34 @@
"DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH": [
"A"
],
"DD_TRACE__ANALYTICS_ENABLED": [
"DD_TRACE_ZAP_ANALYTICS_ENABLED": [
"A"
],
"DD_VERSION": [
"DD_TRACE__ANALYTICS_ENABLED": [
"A"
],
"DD_METRICS_OTEL_ENABLED": [
"DD_VERSION": [
"A"
],
"OTEL_EXPORTER_OTLP_ENDPOINT": [
"A"
],
"OTEL_EXPORTER_OTLP_METRICS_HEADERS": [
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": [
"A"
],
"OTEL_EXPORTER_OTLP_PROTOCOL": [
"OTEL_EXPORTER_OTLP_METRICS_HEADERS": [
"A"
],
"OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": [
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": [
"A"
],
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": [
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": [
"A"
],
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": [
"OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": [
"A"
],
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": [
"OTEL_EXPORTER_OTLP_PROTOCOL": [
"A"
],
"OTEL_LOGS_EXPORTER": [
Expand Down
Loading