Skip to content

Commit

Permalink
Merge branch 'main' into rachel.yang/http-net-error-codes
Browse files Browse the repository at this point in the history
  • Loading branch information
rachelyangdog authored Dec 20, 2024
2 parents 040eb86 + 637ea72 commit 96ee850
Show file tree
Hide file tree
Showing 27 changed files with 336 additions and 162 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/system-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ jobs:
scenario: APPSEC_CORRUPTED_RULES
- weblog-variant: net-http
scenario: APPSEC_LOW_WAF_TIMEOUT
- weblog-variant: net-http
scenario: APPSEC_STANDALONE
- weblog-variant: net-http
scenario: APPSEC_CUSTOM_OBFUSCATION
# APM scenarios requiring specific environment settings
Expand Down
18 changes: 9 additions & 9 deletions contrib/google.golang.org/grpc/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,20 +520,20 @@ func TestStreamSendsErrorCode(t *testing.T) {
// to flush the spans
_, _ = stream.Recv()

containsErrorCode := false
spans := mt.FinishedSpans()

// check if at least one span has error code
// check if at least one span with spank.kind=server has error code
var span mocktracer.Span
for _, s := range spans {
if s.Tag(tagCode) == wantCode {
containsErrorCode = true
if s.Tag(tagCode) != wantCode {
continue
}
if s.Tag(ext.SpanKind) != ext.SpanKindServer {
continue
}
span = s
}
assert.True(t, containsErrorCode, "at least one span should contain error code, the spans were:\n%v", spans)

// ensure that last span contains error code also
gotLastSpanCode := spans[len(spans)-1].Tag(tagCode)
assert.Equal(t, wantCode, gotLastSpanCode, "last span should contain error code")
assert.NotNilf(t, span, "at least one span should contain error code, the spans were:\n%v", spans)
}

// fixtureServer a dummy implementation of our grpc fixtureServer.
Expand Down
6 changes: 3 additions & 3 deletions contrib/miekg/dns/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func startServer(t *testing.T, traced bool) (*dns.Server, func()) {
if traced {
h = dnstrace.WrapHandler(h)
}
addr := getFreeAddr(t).String()
addr := getAddr(t).String()
server := &dns.Server{
Addr: addr,
Net: "udp",
Expand Down Expand Up @@ -190,8 +190,8 @@ func assertClientSpan(t *testing.T, s mocktracer.Span) {
assert.Equal(t, ext.SpanKindClient, s.Tag(ext.SpanKind))
}

func getFreeAddr(t *testing.T) net.Addr {
li, err := net.Listen("tcp", "127.0.0.1:0")
func getAddr(t *testing.T) net.Addr {
li, err := net.Listen("tcp4", "127.0.0.1:2020")
if err != nil {
t.Fatal(err)
}
Expand Down
1 change: 0 additions & 1 deletion contrib/net/http/roundtripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"strings"

"gopkg.in/DataDog/dd-trace-go.v1/appsec/events"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
Expand Down
2 changes: 2 additions & 0 deletions ddtrace/tracer/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type startupInfo struct {
FeatureFlags []string `json:"feature_flags"`
PropagationStyleInject string `json:"propagation_style_inject"` // Propagation style for inject
PropagationStyleExtract string `json:"propagation_style_extract"` // Propagation style for extract
TracingAsTransport bool `json:"tracing_as_transport"` // Whether the tracer is disabled and other products are using it as a transport
}

// checkEndpoint tries to connect to the URL specified by endpoint.
Expand Down Expand Up @@ -147,6 +148,7 @@ func logStartup(t *tracer) {
FeatureFlags: featureFlags,
PropagationStyleInject: injectorNames,
PropagationStyleExtract: extractorNames,
TracingAsTransport: t.config.tracingAsTransport,
}
if _, _, err := samplingRulesFromEnv(); err != nil {
info.SamplingRulesError = fmt.Sprintf("%s", err)
Expand Down
10 changes: 5 additions & 5 deletions ddtrace/tracer/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestStartupLog(t *testing.T) {
tp.Ignore("appsec: ", telemetry.LogPrefix)
logStartup(tracer)
require.Len(t, tp.Logs(), 2)
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"","service":"tracer\.test(\.exe)?","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":false,"analytics_enabled":false,"sample_rate":"NaN","sample_rate_limit":"disabled","trace_sampling_rules":null,"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":null,"tags":{"runtime-id":"[^"]*"},"runtime_metrics_enabled":false,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"","architecture":"[^"]*","global_service":"","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":((true)|(false)),"Stats":((true)|(false)),"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext"}`, tp.Logs()[1])
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"","service":"tracer\.test(\.exe)?","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":false,"analytics_enabled":false,"sample_rate":"NaN","sample_rate_limit":"disabled","trace_sampling_rules":null,"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":null,"tags":{"runtime-id":"[^"]*"},"runtime_metrics_enabled":false,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"","architecture":"[^"]*","global_service":"","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":((true)|(false)),"Stats":((true)|(false)),"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext","tracing_as_transport":false}`, tp.Logs()[1])
})

t.Run("configured", func(t *testing.T) {
Expand Down Expand Up @@ -65,7 +65,7 @@ func TestStartupLog(t *testing.T) {
tp.Ignore("appsec: ", telemetry.LogPrefix)
logStartup(tracer)
require.Len(t, tp.Logs(), 2)
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"configuredEnv","service":"configured.service","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":true,"analytics_enabled":true,"sample_rate":"0\.123000","sample_rate_limit":"100","trace_sampling_rules":\[{"service":"mysql","sample_rate":0\.75}\],"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":{"initial_service":"new_service"},"tags":{"runtime-id":"[^"]*","tag":"value","tag2":"NaN"},"runtime_metrics_enabled":true,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"2.3.4","architecture":"[^"]*","global_service":"configured.service","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":false,"Stats":false,"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":true,"metadata":{"version":"v1"}},"feature_flags":\["discovery"\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext"}`, tp.Logs()[1])
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"configuredEnv","service":"configured.service","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":true,"analytics_enabled":true,"sample_rate":"0\.123000","sample_rate_limit":"100","trace_sampling_rules":\[{"service":"mysql","sample_rate":0\.75}\],"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":{"initial_service":"new_service"},"tags":{"runtime-id":"[^"]*","tag":"value","tag2":"NaN"},"runtime_metrics_enabled":true,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"2.3.4","architecture":"[^"]*","global_service":"configured.service","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":false,"Stats":false,"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":true,"metadata":{"version":"v1"}},"feature_flags":\["discovery"\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext","tracing_as_transport":false}`, tp.Logs()[1])
})

t.Run("limit", func(t *testing.T) {
Expand Down Expand Up @@ -95,7 +95,7 @@ func TestStartupLog(t *testing.T) {
tp.Ignore("appsec: ", telemetry.LogPrefix)
logStartup(tracer)
require.Len(t, tp.Logs(), 2)
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"configuredEnv","service":"configured.service","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":true,"analytics_enabled":true,"sample_rate":"0\.123000","sample_rate_limit":"1000.001","trace_sampling_rules":\[{"service":"mysql","sample_rate":0\.75}\],"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":{"initial_service":"new_service"},"tags":{"runtime-id":"[^"]*","tag":"value","tag2":"NaN"},"runtime_metrics_enabled":true,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"2.3.4","architecture":"[^"]*","global_service":"configured.service","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":false,"Stats":false,"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext"}`, tp.Logs()[1])
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"configuredEnv","service":"configured.service","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":true,"analytics_enabled":true,"sample_rate":"0\.123000","sample_rate_limit":"1000.001","trace_sampling_rules":\[{"service":"mysql","sample_rate":0\.75}\],"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":{"initial_service":"new_service"},"tags":{"runtime-id":"[^"]*","tag":"value","tag2":"NaN"},"runtime_metrics_enabled":true,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"2.3.4","architecture":"[^"]*","global_service":"configured.service","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":false,"Stats":false,"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext","tracing_as_transport":false}`, tp.Logs()[1])
})

t.Run("errors", func(t *testing.T) {
Expand All @@ -110,7 +110,7 @@ func TestStartupLog(t *testing.T) {
logStartup(tracer)
require.Len(t, tp.Logs(), 2)
fmt.Println(tp.Logs()[1])
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"","service":"tracer\.test(\.exe)?","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":false,"analytics_enabled":false,"sample_rate":"NaN","sample_rate_limit":"100","trace_sampling_rules":\[{"service":"some\.service","sample_rate":0\.234}\],"span_sampling_rules":null,"sampling_rules_error":"\\n\\tat index 1: ignoring rule {Service:other.service Rate:2}: rate is out of \[0\.0, 1\.0] range","service_mappings":null,"tags":{"runtime-id":"[^"]*"},"runtime_metrics_enabled":false,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"","architecture":"[^"]*","global_service":"","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":((true)|(false)),"Stats":((true)|(false)),"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext"}`, tp.Logs()[1])
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"","service":"tracer\.test(\.exe)?","agent_url":"http://localhost:9/v0.4/traces","agent_error":"Post .*","debug":false,"analytics_enabled":false,"sample_rate":"NaN","sample_rate_limit":"100","trace_sampling_rules":\[{"service":"some\.service","sample_rate":0\.234}\],"span_sampling_rules":null,"sampling_rules_error":"\\n\\tat index 1: ignoring rule {Service:other.service Rate:2}: rate is out of \[0\.0, 1\.0] range","service_mappings":null,"tags":{"runtime-id":"[^"]*"},"runtime_metrics_enabled":false,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"","architecture":"[^"]*","global_service":"","lambda_mode":"false","appsec":((true)|(false)),"agent_features":{"DropP0s":((true)|(false)),"Stats":((true)|(false)),"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext","tracing_as_transport":false}`, tp.Logs()[1])
})

t.Run("lambda", func(t *testing.T) {
Expand All @@ -123,7 +123,7 @@ func TestStartupLog(t *testing.T) {
tp.Ignore("appsec: ", telemetry.LogPrefix)
logStartup(tracer)
assert.Len(tp.Logs(), 1)
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"","service":"tracer\.test(\.exe)?","agent_url":"http://localhost:9/v0.4/traces","agent_error":"","debug":false,"analytics_enabled":false,"sample_rate":"NaN","sample_rate_limit":"disabled","trace_sampling_rules":null,"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":null,"tags":{"runtime-id":"[^"]*"},"runtime_metrics_enabled":false,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"","architecture":"[^"]*","global_service":"","lambda_mode":"true","appsec":((true)|(false)),"agent_features":{"DropP0s":false,"Stats":false,"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext"}`, tp.Logs()[0])
assert.Regexp(logPrefixRegexp+` INFO: DATADOG TRACER CONFIGURATION {"date":"[^"]*","os_name":"[^"]*","os_version":"[^"]*","version":"[^"]*","lang":"Go","lang_version":"[^"]*","env":"","service":"tracer\.test(\.exe)?","agent_url":"http://localhost:9/v0.4/traces","agent_error":"","debug":false,"analytics_enabled":false,"sample_rate":"NaN","sample_rate_limit":"disabled","trace_sampling_rules":null,"span_sampling_rules":null,"sampling_rules_error":"","service_mappings":null,"tags":{"runtime-id":"[^"]*"},"runtime_metrics_enabled":false,"runtime_metrics_v2_enabled":false,"profiler_code_hotspots_enabled":((false)|(true)),"profiler_endpoints_enabled":((false)|(true)),"dd_version":"","architecture":"[^"]*","global_service":"","lambda_mode":"true","appsec":((true)|(false)),"agent_features":{"DropP0s":false,"Stats":false,"StatsdPort":(0|8125)},"integrations":{.*},"partial_flush_enabled":false,"partial_flush_min_spans":1000,"orchestrion":{"enabled":false},"feature_flags":\[\],"propagation_style_inject":"datadog,tracecontext","propagation_style_extract":"datadog,tracecontext","tracing_as_transport":false}`, tp.Logs()[0])
})

t.Run("integrations", func(t *testing.T) {
Expand Down
42 changes: 42 additions & 0 deletions ddtrace/tracer/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ var (

// defaultMaxTagsHeaderLen specifies the default maximum length of the X-Datadog-Tags header value.
defaultMaxTagsHeaderLen = 128

// defaultRateLimit specifies the default trace rate limit used when DD_TRACE_RATE_LIMIT is not set.
defaultRateLimit = 100.0
)

// config holds the tracer configuration.
Expand Down Expand Up @@ -298,6 +301,12 @@ type config struct {

// logDirectory is directory for tracer logs specified by user-setting DD_TRACE_LOG_DIRECTORY. default empty/unused
logDirectory string

// tracingAsTransport specifies whether the tracer is running in transport-only mode, where traces are only sent when other products request it.
tracingAsTransport bool

// traceRateLimitPerSecond specifies the rate limit for traces.
traceRateLimitPerSecond float64
}

// orchestrionConfig contains Orchestrion configuration.
Expand Down Expand Up @@ -344,6 +353,22 @@ func newConfig(opts ...StartOption) *config {
c.globalSampleRate = sampleRate
c.httpClientTimeout = time.Second * 10 // 10 seconds

c.traceRateLimitPerSecond = defaultRateLimit
origin := telemetry.OriginDefault
if v, ok := os.LookupEnv("DD_TRACE_RATE_LIMIT"); ok {
l, err := strconv.ParseFloat(v, 64)
if err != nil {
log.Warn("DD_TRACE_RATE_LIMIT invalid, using default value %f: %v", defaultRateLimit, err)
} else if l < 0.0 {
log.Warn("DD_TRACE_RATE_LIMIT negative, using default value %f", defaultRateLimit)
} else {
c.traceRateLimitPerSecond = l
origin = telemetry.OriginEnvVar
}
}

reportTelemetryOnAppStarted(telemetry.Configuration{Name: "trace_rate_limit", Value: c.traceRateLimitPerSecond, Origin: origin})

if v := os.Getenv("OTEL_LOGS_EXPORTER"); v != "" {
log.Warn("OTEL_LOGS_EXPORTER is not supported")
}
Expand Down Expand Up @@ -562,6 +587,23 @@ func newConfig(opts ...StartOption) *config {
// This allows persisting the initial value of globalTags for future resets and updates.
globalTagsOrigin := c.globalTags.cfgOrigin
c.initGlobalTags(c.globalTags.get(), globalTagsOrigin)

// TODO: change the name once APM Platform RFC is approved
if internal.BoolEnv("DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED", false) {
// Enable tracing as transport layer mode
// This means to stop sending trace metrics, send one trace per minute and those force-kept by other products
// using the tracer as transport layer for their data. And finally adding the _dd.apm.enabled=0 tag to all traces
// to let the backend know that it needs to keep APM UI disabled.
c.globalSampleRate = 1.0
c.traceRateLimitPerSecond = 1.0 / 60
c.tracingAsTransport = true
WithGlobalTag("_dd.apm.enabled", 0)(c)
// Disable runtime metrics. In `tracingAsTransport` mode, we'll still
// tell the agent we computed them, so it doesn't do it either.
c.runtimeMetrics = false
c.runtimeMetricsV2 = false
}

return c
}

Expand Down
Loading

0 comments on commit 96ee850

Please sign in to comment.