Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9a07a3c
feat(contrib/go.uber.org/zap): add integration
rarguelloF May 5, 2026
79a2a87
feat(contrib/go.uber.org/zap): add ContextProvider fallback for any t…
rarguelloF May 12, 2026
96228cd
Merge branch 'main' into rarguelloF/IDMPL-361/support-zap
rarguelloF May 18, 2026
e76ae1d
fix(contrib/go.uber.org/zap): preserve variadic spread when wrapping …
rarguelloF May 19, 2026
8495c53
Merge remote-tracking branch 'origin/main' into rarguelloF/IDMPL-361/…
rarguelloF Jul 9, 2026
550cd2f
fix(contrib/go.uber.org/zap): tidy go.mod and regenerate integration …
rarguelloF Jul 9, 2026
5c94b01
Merge branch 'main' into rarguelloF/IDMPL-361/support-zap
rarguelloF Jul 9, 2026
03b1f69
fix(contrib/go.uber.org/zap): use context.Context/*http.Request match…
rarguelloF Jul 9, 2026
d51457a
fix(contrib/go.uber.org/zap): register instrumentation telemetry package
rarguelloF Jul 9, 2026
8ed4110
fix(contrib/go.uber.org/zap): document DD_TRACE_ZAP_ANALYTICS_ENABLED…
rarguelloF Jul 10, 2026
f396e79
fix(contrib/go.uber.org/zap): require core module v2.11.0-dev to matc…
rarguelloF Jul 13, 2026
59d0aca
fix(contrib/go.uber.org/zap): register zap in tracer integration repo…
rarguelloF Jul 13, 2026
15affb8
fix(contrib/go.uber.org/zap): honor DD_TRACE_128_BIT_TRACEID_LOGGING_…
rarguelloF Jul 13, 2026
2d88fdd
fix(contrib/go.uber.org/zap): avoid panic on nil *http.Request when l…
rarguelloF Jul 13, 2026
057b7a6
fix(contrib/go.uber.org/zap): weave generic Log/Logf/Logw/Logln entry…
rarguelloF Jul 13, 2026
18d3aa4
docs: update supported integrations documentation
rarguelloF Jul 13, 2026
f643950
Merge branch 'main' into rarguelloF/IDMPL-361/support-zap
rarguelloF Jul 15, 2026
0b4d960
chore: regenerate module files after merging main
rarguelloF Jul 16, 2026
9cbbab7
Merge branch 'main' into rarguelloF/IDMPL-361/support-zap
rarguelloF Jul 16, 2026
e19f7e5
run make generate
rarguelloF Jul 16, 2026
9f26eee
Merge branch 'main' into rarguelloF/IDMPL-361/support-zap
rarguelloF Jul 23, 2026
60e8639
test(contrib/go.uber.org/zap): restore config in cleanup and add benc…
rarguelloF Jul 23, 2026
83f03f2
chore(contrib/go.uber.org/zap): regenerate module files after merging…
rarguelloF Jul 23, 2026
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
82 changes: 82 additions & 0 deletions contrib/go.uber.org/zap/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
module github.com/DataDog/dd-trace-go/contrib/go.uber.org/zap/v2

go 1.25.0

require (
github.com/DataDog/dd-trace-go/v2 v2.11.0-dev
github.com/stretchr/testify v1.11.1
go.uber.org/zap v1.28.0
)

require (
github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/obfuscate v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/proto v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/trace v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/trace/log v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/trace/stats v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-agent/pkg/trace/traceutil v0.82.0-rc.2 // indirect
github.com/DataDog/datadog-go/v5 v5.9.0 // indirect
github.com/DataDog/go-libddwaf/v5 v5.0.0 // indirect
github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20260217080614-b0f4edc38a6d // indirect
github.com/DataDog/go-sqllexer v0.2.3 // indirect
github.com/DataDog/go-tuf v1.1.1-0.5.2 // indirect
github.com/DataDog/sketches-go v1.4.8 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-version v1.9.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.6 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/linkdata/deadlock v0.5.5 // indirect
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect
github.com/minio/simdjson-go v0.4.5 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/outcaste-io/ristretto v0.2.3 // indirect
github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/puzpuzpuz/xsync/v4 v4.5.0 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.11.0 // indirect
github.com/shirou/gopsutil/v4 v4.26.6 // indirect
github.com/tinylib/msgp v1.6.4 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/trailofbits/go-mutexasserts v0.0.0-20250514102930-c1f3d2e37561 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/collector/component v1.61.0 // indirect
go.opentelemetry.io/collector/featuregate v1.61.0 // indirect
go.opentelemetry.io/collector/pdata v1.61.0 // indirect
go.opentelemetry.io/collector/pdata/pprofile v0.155.0 // indirect
go.opentelemetry.io/otel v1.44.0 // indirect
go.opentelemetry.io/otel/metric v1.44.0 // indirect
go.opentelemetry.io/otel/trace v1.44.0 // indirect
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
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.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 // indirect
golang.org/x/mod v0.36.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260618152121-87f3d3e198d3 // indirect
google.golang.org/protobuf v1.36.12-0.20260116114154-8c4c4ae446ca // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/DataDog/dd-trace-go/v2 => ../../..
247 changes: 247 additions & 0 deletions contrib/go.uber.org/zap/go.sum

Large diffs are not rendered by default.

220 changes: 220 additions & 0 deletions contrib/go.uber.org/zap/orchestrion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# 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 2023-present Datadog, Inc.
---
# yaml-language-server: $schema=https://datadoghq.dev/orchestrion/schema.json
meta:
name: github.com/DataDog/dd-trace-go/contrib/go.uber.org/zap/v2
description: Structured, leveled logging for Go.

aspects:
- id: Logger.Debug|Info|Warn|Error|DPanic|Panic|Fatal|Log
join-point:
all-of:
- not:
import-path: github.com/DataDog/dd-trace-go/contrib/go.uber.org/zap/v2
- one-of:
- method-call:
receiver: "go.uber.org/zap.Logger"
name: Debug

- method-call:
receiver: "go.uber.org/zap.Logger"
name: Info

- method-call:
receiver: "go.uber.org/zap.Logger"
name: Warn

- method-call:
receiver: "go.uber.org/zap.Logger"
name: Error

- method-call:
receiver: "go.uber.org/zap.Logger"
name: DPanic

- method-call:
receiver: "go.uber.org/zap.Logger"
name: Panic

- method-call:
receiver: "go.uber.org/zap.Logger"
name: Fatal

- method-call:
receiver: "go.uber.org/zap.Logger"
name: Log

advice:
- wrap-expression:
imports:
__ddzap: github.com/DataDog/dd-trace-go/contrib/go.uber.org/zap/v2
template: |-
{{- $ctx := .Function.ArgumentOfType "context.Context" -}}
{{- if eq $ctx "" -}}
{{- $ctx = .Function.ArgumentThatImplements "context.Context" -}}
{{- end -}}
{{- $req := .Function.ArgumentOfType "*net/http.Request" -}}
{{- $ellipsis := .AST.Ellipsis -}}
{{- if $ctx -}}
{{ .AST.Fun.X }}.With(__ddzap.TraceFields({{ $ctx }})...).{{ .AST.Fun.Name }}({{ range $i, $a := .AST.Args }}{{ if $i }}, {{ end }}{{ $a }}{{ end }}{{ if $ellipsis }}...{{ end }})
{{- else if $req -}}
{{ .AST.Fun.X }}.With(__ddzap.TraceFieldsFromRequest({{ $req }})...).{{ .AST.Fun.Name }}({{ range $i, $a := .AST.Args }}{{ if $i }}, {{ end }}{{ $a }}{{ end }}{{ if $ellipsis }}...{{ end }})
{{- else -}}
{{ . }}
{{- end -}}

- id: SugaredLogger.Debug|Info|Warn|Error|DPanic|Panic|Fatal|Log|Logf|Logw|Logln
join-point:
all-of:
- not:
import-path: github.com/DataDog/dd-trace-go/contrib/go.uber.org/zap/v2
- one-of:
- method-call:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a call-out: these method-call won't match against a promoted method for an embedded *zap.Logger. Should we support the embedded/wrapped pattern?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good catch. We would need to add support in Orchestrion itself though. I will follow-up how feasible this is to implement.

receiver: "go.uber.org/zap.SugaredLogger"
name: Debug

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Info

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Warn

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Error

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: DPanic

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Panic

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Fatal

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Debugf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Infof

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Warnf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Errorf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: DPanicf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Panicf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Fatalf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Debugw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Infow

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Warnw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Errorw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: DPanicw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Panicw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Fatalw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Debugln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Infoln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Warnln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Errorln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: DPanicln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Panicln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Fatalln

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Log

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Logf

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Logw

- method-call:
receiver: "go.uber.org/zap.SugaredLogger"
name: Logln

advice:
- wrap-expression:
imports:
__ddzap: github.com/DataDog/dd-trace-go/contrib/go.uber.org/zap/v2
template: |-
{{- $ctx := .Function.ArgumentOfType "context.Context" -}}
{{- if eq $ctx "" -}}
{{- $ctx = .Function.ArgumentThatImplements "context.Context" -}}
{{- end -}}
{{- $req := .Function.ArgumentOfType "*net/http.Request" -}}
{{- $ellipsis := .AST.Ellipsis -}}
{{- if $ctx -}}
{{ .AST.Fun.X }}.Desugar().With(__ddzap.TraceFields({{ $ctx }})...).Sugar().{{ .AST.Fun.Name }}({{ range $i, $a := .AST.Args }}{{ if $i }}, {{ end }}{{ $a }}{{ end }}{{ if $ellipsis }}...{{ end }})
{{- else if $req -}}
{{ .AST.Fun.X }}.Desugar().With(__ddzap.TraceFieldsFromRequest({{ $req }})...).Sugar().{{ .AST.Fun.Name }}({{ range $i, $a := .AST.Args }}{{ if $i }}, {{ end }}{{ $a }}{{ end }}{{ if $ellipsis }}...{{ end }})
{{- else -}}
{{ . }}
{{- end -}}
85 changes: 85 additions & 0 deletions contrib/go.uber.org/zap/zap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// 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 2023-present Datadog, Inc.

// Package zap provides Datadog trace/log correlation helpers for go.uber.org/zap.
//
// # Manual use
//
// Call TraceFields with the current context to obtain zap.Field values for the
// active span, then pass them to any Logger method:
//
// logger.Info("handling request",
// zap.String("url", req.URL.Path),
// ddzap.TraceFields(ctx)...,
// )
//
// # Automatic use via Orchestrion
//
// When built with Orchestrion, call sites of (*zap.Logger) and (*zap.SugaredLogger)
// log methods are automatically rewritten to inject trace fields whenever a
// context.Context (or a value implementing it) or a *http.Request is in scope.
package zap

import (
"context"
"net/http"
"strconv"

"go.uber.org/zap"

"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"
)

var instr *instrumentation.Instrumentation

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

type config struct {
log128bits bool
}

var cfg = newConfig()

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

// TraceFields returns zap.Field values carrying the Datadog trace and span IDs
// from the active span in ctx. Returns nil when no span is active.
func TraceFields(ctx context.Context) []zap.Field {
span, ok := tracer.SpanFromContext(ctx)
if !ok {
return nil
}
var traceID string
if cfg.log128bits && span.Context().TraceID() != tracer.TraceIDZero {
traceID = span.Context().TraceID()
} else {
traceID = strconv.FormatUint(span.Context().TraceIDLower(), 10)
}
return []zap.Field{
zap.String(ext.LogKeyTraceID, traceID),
zap.String(ext.LogKeySpanID, strconv.FormatUint(span.Context().SpanID(), 10)),
}
}

// TraceFieldsFromRequest returns TraceFields for req's context, or nil when req
// is nil. Orchestrion uses this as a fallback trace source when a *http.Request
// is in scope but no context.Context is: a nil req would otherwise panic on
// req.Context() in an instrumented build where the original, uninstrumented log
// call would have logged normally.
func TraceFieldsFromRequest(req *http.Request) []zap.Field {
if req == nil {
return nil
}
return TraceFields(req.Context())
}
Loading
Loading