Skip to content

Commit

Permalink
Merge branch 'main' into dario.castane/langplat-286/origin-detection
Browse files Browse the repository at this point in the history
  • Loading branch information
darccio authored Feb 4, 2025
2 parents 10ca778 + 998add0 commit 0ec9f09
Show file tree
Hide file tree
Showing 52 changed files with 1,310 additions and 316 deletions.
25 changes: 25 additions & 0 deletions .github/actions/add-codeowners/codeowners.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

for file in "$@"; do
temp_file="tempfile.xml"

# force write a new line at the end of the gotestsum-report.xml, or else
# the loop will skip the last line.
# fixes issue with a missing </testsuites>
echo -e "\n" >> $file

while read p; do
# we might try to report gotestsum-report.xml multiple times, so don't
# calculate codeowners more times than we need
if [[ "$p" =~ \<testcase && ! "$p" =~ "file=" ]]; then
class=$(echo "$p" | grep -o '.v1/[^"]*"')
file_name=$(echo "${class:3}" | sed 's/.$//') # trim off the edges to get the path
new_line=$(echo "$p" | sed "s|<testcase \([^>]*\)>|<testcase \1 file=\"$file_name\">|")
echo "$new_line" >> "$temp_file"
else
echo "$p" >> "$temp_file"
fi
done < $file

mv "$temp_file" $file
done
4 changes: 4 additions & 0 deletions .github/actions/dd-ci-upload/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ runs:
curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_${{ env.DD_CI_CLI_BUILD }}" --output datadog-ci
chmod +x datadog-ci
- name: Add CodeOwners to JUnit files
shell: bash
run: cd ./.github/actions/add-codeowners && ./codeowners.sh ${{ inputs.files }}

- name: Upload the JUnit files
shell: bash
run: |
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/unit-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ jobs:
image: redis:3.2
ports:
- 6379:6379
valkey:
image: valkey/valkey:8
env:
VALKEY_EXTRA_FLAGS: "--port 6380 --requirepass password-for-default"
ports:
- 6380:6380
elasticsearch2:
image: elasticsearch:2
env:
Expand Down
33 changes: 20 additions & 13 deletions contrib/database/sql/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,27 @@ var interval = 10 * time.Second

// pollDBStats calls (*DB).Stats on the db at a predetermined interval. It pushes the DBStats off to the statsd client.
// the caller should always ensure that db & statsd are non-nil
func pollDBStats(statsd internal.StatsdClient, db *sql.DB) {
func pollDBStats(statsd internal.StatsdClient, db *sql.DB, stop chan struct{}) {
log.Debug("DB stats will be gathered and sent every %v.", interval)
for range time.NewTicker(interval).C {
log.Debug("Reporting DB.Stats metrics...")
stat := db.Stats()
statsd.Gauge(MaxOpenConnections, float64(stat.MaxOpenConnections), []string{}, 1)
statsd.Gauge(OpenConnections, float64(stat.OpenConnections), []string{}, 1)
statsd.Gauge(InUse, float64(stat.InUse), []string{}, 1)
statsd.Gauge(Idle, float64(stat.Idle), []string{}, 1)
statsd.Gauge(WaitCount, float64(stat.WaitCount), []string{}, 1)
statsd.Timing(WaitDuration, stat.WaitDuration, []string{}, 1)
statsd.Gauge(MaxIdleClosed, float64(stat.MaxIdleClosed), []string{}, 1)
statsd.Gauge(MaxIdleTimeClosed, float64(stat.MaxIdleTimeClosed), []string{}, 1)
statsd.Gauge(MaxLifetimeClosed, float64(stat.MaxLifetimeClosed), []string{}, 1)
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
log.Debug("Reporting DB.Stats metrics...")
stat := db.Stats()
statsd.Gauge(MaxOpenConnections, float64(stat.MaxOpenConnections), []string{}, 1)
statsd.Gauge(OpenConnections, float64(stat.OpenConnections), []string{}, 1)
statsd.Gauge(InUse, float64(stat.InUse), []string{}, 1)
statsd.Gauge(Idle, float64(stat.Idle), []string{}, 1)
statsd.Gauge(WaitCount, float64(stat.WaitCount), []string{}, 1)
statsd.Timing(WaitDuration, stat.WaitDuration, []string{}, 1)
statsd.Gauge(MaxIdleClosed, float64(stat.MaxIdleClosed), []string{}, 1)
statsd.Gauge(MaxIdleTimeClosed, float64(stat.MaxIdleTimeClosed), []string{}, 1)
statsd.Gauge(MaxLifetimeClosed, float64(stat.MaxLifetimeClosed), []string{}, 1)
case <-stop:
return
}
}
}

Expand Down
23 changes: 23 additions & 0 deletions contrib/database/sql/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
package sql

import (
"sync"
"testing"

"github.com/DataDog/datadog-go/v5/statsd"
"github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
)

Expand Down Expand Up @@ -64,3 +68,22 @@ func TestStatsTags(t *testing.T) {
})
resetGlobalConfig()
}

func TestPollDBStatsStop(t *testing.T) {
driverName := "postgres"
Register(driverName, &pq.Driver{}, WithServiceName("postgres-test"), WithAnalyticsRate(0.2))
defer unregister(driverName)
db, err := Open(driverName, "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
require.NoError(t, err)
defer db.Close()

var wg sync.WaitGroup
stop := make(chan struct{})
wg.Add(1)
go func() {
defer wg.Done()
pollDBStats(&statsd.NoOpClientDirect{}, db, stop)
}()
close(stop)
wg.Wait()
}
11 changes: 10 additions & 1 deletion contrib/database/sql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ type tracedConnector struct {
connector driver.Connector
driverName string
cfg *config
dbClose chan struct{}
}

func (t *tracedConnector) Connect(ctx context.Context) (driver.Conn, error) {
Expand Down Expand Up @@ -171,6 +172,13 @@ func (t *tracedConnector) Driver() driver.Driver {
return t.connector.Driver()
}

// Close closes the dbClose channel
// This method will be invoked when DB.Close() is called, which we expect to occur only once: https://cs.opensource.google/go/go/+/refs/tags/go1.23.4:src/database/sql/sql.go;l=918-950
func (t *tracedConnector) Close() error {
close(t.dbClose)
return nil
}

// from Go stdlib implementation of sql.Open
type dsnConnector struct {
dsn string
Expand Down Expand Up @@ -208,10 +216,11 @@ func OpenDB(c driver.Connector, opts ...Option) *sql.DB {
connector: c,
driverName: driverName,
cfg: cfg,
dbClose: make(chan struct{}),
}
db := sql.OpenDB(tc)
if cfg.dbStats && cfg.statsdClient != nil {
go pollDBStats(cfg.statsdClient, db)
go pollDBStats(cfg.statsdClient, db, tc.dbClose)
}
return db
}
Expand Down
8 changes: 7 additions & 1 deletion contrib/database/sql/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,13 @@ func TestOpenOptions(t *testing.T) {
var tg statsdtest.TestStatsdClient
Register(driverName, &pq.Driver{})
defer unregister(driverName)
_, err := Open(driverName, dsn, withStatsdClient(&tg), WithDBStats())
db, err := Open(driverName, dsn, withStatsdClient(&tg), WithDBStats())
require.NoError(t, err)

// The polling interval has been reduced to 500ms for the sake of this test, so at least one round of `pollDBStats` should be complete in 1s
deadline := time.Now().Add(1 * time.Second)
wantStats := []string{MaxOpenConnections, OpenConnections, InUse, Idle, WaitCount, WaitDuration, MaxIdleClosed, MaxIdleTimeClosed, MaxLifetimeClosed}
var calls1 []string
for {
if time.Now().After(deadline) {
t.Fatalf("Stats not collected in expected interval of %v", interval)
Expand All @@ -300,11 +301,16 @@ func TestOpenOptions(t *testing.T) {
}
}
// all expected stats have been collected; exit out of loop, test should pass
calls1 = calls
break
}
// not all stats have been collected yet, try again in 50ms
time.Sleep(50 * time.Millisecond)
}
// Close DB and assert the no further stats have been collected; db.Close should stop the pollDBStats goroutine.
db.Close()
time.Sleep(50 * time.Millisecond)
assert.Equal(t, calls1, tg.CallNames())
})
}

Expand Down
4 changes: 2 additions & 2 deletions contrib/go-redis/redis.v7/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func additionalTagOptions(client redis.UniversalClient) []ddtrace.StartSpanOptio
opt := clientOptions.Options()
if opt.Addr == "FailoverClient" {
additionalTags = []ddtrace.StartSpanOption{
tracer.Tag("out.db", strconv.Itoa(opt.DB)),
tracer.Tag(ext.TargetDB, strconv.Itoa(opt.DB)),
tracer.Tag(ext.RedisDatabaseIndex, opt.DB),
}
} else {
Expand All @@ -91,7 +91,7 @@ func additionalTagOptions(client redis.UniversalClient) []ddtrace.StartSpanOptio
additionalTags = []ddtrace.StartSpanOption{
tracer.Tag(ext.TargetHost, host),
tracer.Tag(ext.TargetPort, port),
tracer.Tag("out.db", strconv.Itoa(opt.DB)),
tracer.Tag(ext.TargetDB, strconv.Itoa(opt.DB)),
tracer.Tag(ext.RedisDatabaseIndex, opt.DB),
}
}
Expand Down
4 changes: 2 additions & 2 deletions contrib/go-redis/redis.v8/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func additionalTagOptions(client redis.UniversalClient) []ddtrace.StartSpanOptio
opt := clientOptions.Options()
if opt.Addr == "FailoverClient" {
additionalTags = []ddtrace.StartSpanOption{
tracer.Tag("out.db", strconv.Itoa(opt.DB)),
tracer.Tag(ext.TargetDB, strconv.Itoa(opt.DB)),
tracer.Tag(ext.RedisDatabaseIndex, opt.DB),
}
} else {
Expand All @@ -90,7 +90,7 @@ func additionalTagOptions(client redis.UniversalClient) []ddtrace.StartSpanOptio
additionalTags = []ddtrace.StartSpanOption{
tracer.Tag(ext.TargetHost, host),
tracer.Tag(ext.TargetPort, port),
tracer.Tag("out.db", strconv.Itoa(opt.DB)),
tracer.Tag(ext.TargetDB, strconv.Itoa(opt.DB)),
tracer.Tag(ext.RedisDatabaseIndex, opt.DB),
}
}
Expand Down
4 changes: 2 additions & 2 deletions contrib/go-redis/redis/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (c *Pipeliner) execWithContext(ctx context.Context) ([]redis.Cmder, error)
tracer.ResourceName("redis"),
tracer.Tag(ext.TargetHost, p.host),
tracer.Tag(ext.TargetPort, p.port),
tracer.Tag("out.db", strconv.Itoa(p.db)),
tracer.Tag(ext.TargetDB, strconv.Itoa(p.db)),
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindClient),
tracer.Tag(ext.DBSystem, ext.DBSystemRedis),
Expand Down Expand Up @@ -202,7 +202,7 @@ func createWrapperFromClient(tc *Client) func(oldProcess func(cmd redis.Cmder) e
tracer.ResourceName(parts[0]),
tracer.Tag(ext.TargetHost, p.host),
tracer.Tag(ext.TargetPort, p.port),
tracer.Tag("out.db", strconv.Itoa(p.db)),
tracer.Tag(ext.TargetDB, strconv.Itoa(p.db)),
tracer.Tag("redis.raw_command", raw),
tracer.Tag("redis.args_length", strconv.Itoa(length)),
tracer.Tag(ext.Component, componentName),
Expand Down
16 changes: 15 additions & 1 deletion contrib/gorm.io/gorm.v1/orchestrion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,18 @@ aspects:
join-point:
function-call: gorm.io/gorm.Open
advice:
- replace-function: gopkg.in/DataDog/dd-trace-go.v1/contrib/gorm.io/gorm.v1.Open
- wrap-expression:
imports:
gorm: gorm.io/gorm
gormtrace: gopkg.in/DataDog/dd-trace-go.v1/contrib/gorm.io/gorm.v1
template: |-
func() (*gorm.DB, error) {
db, err := {{ . }}
if err != nil {
return nil, err
}
if err := db.Use(gormtrace.NewTracePlugin()); err != nil {
return nil, err
}
return db, nil
}()
13 changes: 13 additions & 0 deletions contrib/internal/httptrace/httptrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import (
"context"
"fmt"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
"gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry"
"net/http"
"strconv"
"strings"
"sync"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
Expand All @@ -27,6 +29,8 @@ var (
cfg = newConfig()
)

var reportTelemetryConfigOnce sync.Once

type inferredSpanCreatedCtxKey struct{}

type FinishSpanFunc = func(status int, errorFn func(int) bool, opts ...tracer.FinishOption)
Expand All @@ -37,6 +41,15 @@ func StartRequestSpan(r *http.Request, opts ...ddtrace.StartSpanOption) (tracer.
// Append our span options before the given ones so that the caller can "overwrite" them.
// TODO(): rework span start option handling (https://github.com/DataDog/dd-trace-go/issues/1352)

// we cannot track the configuration in newConfig because it's called during init() and the the telemetry client
// is not initialized yet
reportTelemetryConfigOnce.Do(func() {
telemetry.GlobalClient.ConfigChange([]telemetry.Configuration{
{Name: "inferred_proxy_services_enabled", Value: cfg.inferredProxyServicesEnabled},
})
log.Debug("internal/httptrace: telemetry.ConfigChange called with cfg: %v:", cfg)
})

var ipTags map[string]string
if cfg.traceClientIP {
ipTags, _ = httpsec.ClientIPTags(r.Header, true, r.RemoteAddr)
Expand Down
1 change: 1 addition & 0 deletions contrib/jackc/pgx.v5/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var interval = 10 * time.Second

// pollPoolStats calls (*pgxpool).Stats on the pool at a predetermined interval. It pushes the pool Stats off to the statsd client.
func pollPoolStats(statsd internal.StatsdClient, pool *pgxpool.Pool) {
// TODO: Create stop condition for pgx on db.Close
log.Debug("contrib/jackc/pgx.v5: Traced pool connection found: Pool stats will be gathered and sent every %v.", interval)
for range time.NewTicker(interval).C {
log.Debug("contrib/jackc/pgx.v5: Reporting pgxpool.Stat metrics...")
Expand Down
11 changes: 10 additions & 1 deletion contrib/net/http/orchestrion.client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ aspects:
ddtrace: gopkg.in/DataDog/dd-trace-go.v1/ddtrace
os: os
links:
- gopkg.in/DataDog/dd-trace-go.v1/internal
- gopkg.in/DataDog/dd-trace-go.v1/internal/appsec
- gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec
- gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer
Expand Down Expand Up @@ -87,6 +88,12 @@ aspects:
//go:linkname __dd_httptrace_GetErrorCodesFromInput gopkg.in/DataDog/dd-trace-go.v1/contrib/internal/httptrace.GetErrorCodesFromInput
func __dd_httptrace_GetErrorCodesFromInput(string) func(int) bool
//go:linkname __dd_httptrace_UrlFromRequest gopkg.in/DataDog/dd-trace-go.v1/contrib/internal/httptrace.UrlFromRequest
func __dd_httptrace_UrlFromRequest(*Request, bool) string
//go:linkname __dd_internal_BoolEnv gopkg.in/DataDog/dd-trace-go.v1/internal.BoolEnv
func __dd_internal_BoolEnv(string, bool) bool
type __dd_tracer_HTTPHeadersCarrier Header
func (c __dd_tracer_HTTPHeadersCarrier) Set(key, val string) {
Header(c).Set(key, val)
Expand All @@ -97,6 +104,8 @@ aspects:
return statusCode >= 400 && statusCode < 500
}
var __dd_queryStringEnabled = __dd_internal_BoolEnv("DD_TRACE_HTTP_CLIENT_TAG_QUERY_STRING", true)
func init() {
v := os.Getenv("DD_TRACE_HTTP_CLIENT_ERROR_STATUSES")
if fn := __dd_httptrace_GetErrorCodesFromInput(v); fn != nil {
Expand Down Expand Up @@ -130,7 +139,7 @@ aspects:
__dd_tracer_SpanType(ext.SpanTypeHTTP),
__dd_tracer_ResourceName(resourceName),
__dd_tracer_Tag(ext.HTTPMethod, {{ $req }}.Method),
__dd_tracer_Tag(ext.HTTPURL, url.String()),
__dd_tracer_Tag(ext.HTTPURL, __dd_httptrace_UrlFromRequest({{ $req }}, __dd_queryStringEnabled)),
__dd_tracer_Tag(ext.Component, "net/http"),
__dd_tracer_Tag(ext.SpanKind, ext.SpanKindClient),
__dd_tracer_Tag(ext.NetworkDestinationName, url.Hostname()),
Expand Down
4 changes: 2 additions & 2 deletions contrib/redis/go-redis.v9/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func additionalTagOptions(client redis.UniversalClient) []ddtrace.StartSpanOptio
opt := clientOptions.Options()
if opt.Addr == "FailoverClient" {
additionalTags = []ddtrace.StartSpanOption{
tracer.Tag("out.db", strconv.Itoa(opt.DB)),
tracer.Tag(ext.TargetDB, strconv.Itoa(opt.DB)),
}
} else {
host, port, err := net.SplitHostPort(opt.Addr)
Expand All @@ -89,7 +89,7 @@ func additionalTagOptions(client redis.UniversalClient) []ddtrace.StartSpanOptio
additionalTags = []ddtrace.StartSpanOption{
tracer.Tag(ext.TargetHost, host),
tracer.Tag(ext.TargetPort, port),
tracer.Tag("out.db", strconv.Itoa(opt.DB)),
tracer.Tag(ext.TargetDB, strconv.Itoa(opt.DB)),
}
}
} else if clientOptions, ok := client.(clusterOptions); ok {
Expand Down
Loading

0 comments on commit 0ec9f09

Please sign in to comment.