Skip to content

Commit

Permalink
[connector/datadog] support obfuscation in datadogconnector (#37457)
Browse files Browse the repository at this point in the history
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description
Support obfuscating SQL and Redis queries in APM stats in Datadog
Connector.

replace statement in otelcontribcol was necessary due to failing build
in pipeline. It doesn't appear that any modules use any affected
functions, but building otelcontribcol with ocb failed due to an API
change. Also opened an issue to bump the `receiver/awscontainerinsight`
dependency so that this replace can be removed in the future: #37486

<!-- Issue number (e.g. #1234) or full URL to issue, if applicable. -->
#### Link to tracking issue
Replaces #35401

<!--Describe what testing was performed and which tests were added.-->
#### Testing
Added TestObfuscate in connector_native_test.go

<!--Describe the documentation added.-->
#### Documentation
added release note and link to semantics on Datadog vendor website
<!--Please delete paragraphs that you did not use before submitting.-->
  • Loading branch information
jackgopack4 authored Jan 24, 2025
1 parent 705cac3 commit 8459bea
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 105 deletions.
35 changes: 35 additions & 0 deletions .chloggen/datadogconnector-add-stats-obfuscation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: datadogconnector

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Support obfuscating sql queries in APM stats

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [37457]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
Ensure that feature flags "enable_receive_resource_spans_v2" and "enable_operation_and_resource_name_logic_v2"
are also enabled on both Datadog Exporter and Datadog Connector so that span attributes are properly
mapped to span type and span resource in Datadog APM; otherwise spans and apm stats may not be
obfuscated and attributes on stats payloads may not match traces.
See https://docs.datadoghq.com/opentelemetry/schema_semantics/semantic_mapping/?tab=datadogexporter#mapping-opentelemetry-database-system-type-to-datadog-span-type
NOTE: Long/complex SQL queries may cause a performance impact on APM Stats calculation in Datadog Connector.
Consider implementing sampling in your pipeline prior to sending traces to Datadog Connector if you experience this.
# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
1 change: 1 addition & 0 deletions cmd/otelcontribcol/builder-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,4 @@ replaces:
- github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dorisexporter => ../../exporter/dorisexporter
- github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/redisstorageextension => ../../extension/storage/redisstorageextension
- github.com/open-telemetry/opentelemetry-collector-contrib/receiver/huaweicloudcesreceiver => ../../receiver/huaweicloudcesreceiver
- github.com/opencontainers/runc v1.1.14 => github.com/opencontainers/runc v1.2.4
17 changes: 14 additions & 3 deletions connector/datadogconnector/connector_native.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/DataDog/datadog-agent/comp/otelcol/otlp/components/statsprocessor"
"github.com/DataDog/datadog-agent/pkg/obfuscate"
pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/trace"
"github.com/DataDog/datadog-agent/pkg/trace/config"
"github.com/DataDog/datadog-agent/pkg/trace/stats"
Expand Down Expand Up @@ -48,6 +49,10 @@ type traceToMetricConnectorNative struct {
// resulting from ingested traces.
statsout chan *pb.StatsPayload

// obfuscator is used to obfuscate sensitive data from various span
// tags based on their type.
obfuscator *obfuscate.Obfuscator

// exit specifies the exit channel, which will be closed upon shutdown.
exit chan struct{}

Expand All @@ -73,6 +78,10 @@ func newTraceToMetricConnectorNative(set component.TelemetrySettings, cfg compon
}

tcfg := getTraceAgentCfg(set.Logger, cfg.(*Config).Traces, attributesTranslator)
oconf := tcfg.Obfuscation.Export(tcfg)
oconf.Statsd = metricsClient
oconf.Redis.Enabled = true

return &traceToMetricConnectorNative{
logger: set.Logger,
translator: trans,
Expand All @@ -82,6 +91,7 @@ func newTraceToMetricConnectorNative(set component.TelemetrySettings, cfg compon
concentrator: stats.NewConcentrator(tcfg, statsWriter, time.Now(), metricsClient),
statsout: statsout,
metricsConsumer: metricsConsumer,
obfuscator: obfuscate.NewObfuscator(oconf),
exit: make(chan struct{}),
}, nil
}
Expand All @@ -103,8 +113,9 @@ func (c *traceToMetricConnectorNative) Shutdown(context.Context) error {
return nil
}
c.logger.Info("Shutting down datadog connector")
c.logger.Info("Stopping concentrator")
// stop the concentrator and wait for the run loop to exit
c.logger.Info("Stopping obfuscator and concentrator")
// stop the obfuscator and concentrator and wait for the run loop to exit
c.obfuscator.Stop()
c.concentrator.Stop()
c.exit <- struct{}{} // signal exit
<-c.exit // wait for close
Expand All @@ -118,7 +129,7 @@ func (c *traceToMetricConnectorNative) Capabilities() consumer.Capabilities {
}

func (c *traceToMetricConnectorNative) ConsumeTraces(_ context.Context, traces ptrace.Traces) error {
inputs := stats.OTLPTracesToConcentratorInputs(traces, c.tcfg, c.ctagKeys, c.peerTagKeys)
inputs := stats.OTLPTracesToConcentratorInputsWithObfuscation(traces, c.tcfg, c.ctagKeys, c.peerTagKeys, c.obfuscator)
for _, input := range inputs {
c.concentrator.Add(input)
}
Expand Down
87 changes: 87 additions & 0 deletions connector/datadogconnector/connector_native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"
"time"

"github.com/DataDog/datadog-agent/pkg/obfuscate"
pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/trace"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -72,6 +73,8 @@ func creteConnectorNativeWithCfg(t *testing.T, cfg *Config) (*traceToMetricConne

connector, ok := tconn.(*traceToMetricConnectorNative)
require.True(t, ok)
oconf := obfuscate.Config{Redis: obfuscate.RedisConfig{Enabled: false}}
connector.obfuscator = obfuscate.NewObfuscator(oconf)
return connector, metricsSink
}

Expand Down Expand Up @@ -268,3 +271,87 @@ func testMeasuredAndClientKindNative(t *testing.T, enableOperationAndResourceNam
t.Errorf("Diff between APM stats -want +got:\n%v", diff)
}
}

func TestObfuscate(t *testing.T) {
cfg := NewFactory().CreateDefaultConfig().(*Config)
cfg.Traces.BucketInterval = time.Second

if err := featuregate.GlobalRegistry().Set("datadog.EnableReceiveResourceSpansV2", true); err != nil {
t.Fatal(err)
}
if err := featuregate.GlobalRegistry().Set("datadog.EnableOperationAndResourceNameV2", true); err != nil {
t.Fatal(err)
}

connector, metricsSink := creteConnectorNativeWithCfg(t, cfg)

err := connector.Start(context.Background(), componenttest.NewNopHost())
require.NoError(t, err)
defer func() {
require.NoError(t, connector.Shutdown(context.Background()))
}()

td := ptrace.NewTraces()
res := td.ResourceSpans().AppendEmpty().Resource()
res.Attributes().PutStr(semconv.AttributeServiceName, "svc")
res.Attributes().PutStr(semconv.AttributeDeploymentEnvironmentName, "my-env")

ss := td.ResourceSpans().At(0).ScopeSpans().AppendEmpty().Spans()
s := ss.AppendEmpty()
s.SetName("name")
s.SetKind(ptrace.SpanKindClient)
s.SetTraceID(testTraceID)
s.SetSpanID(testSpanID1)
s.Attributes().PutStr(semconv.AttributeDBSystem, semconv.AttributeDBSystemMySQL)
s.Attributes().PutStr(semconv.AttributeDBOperationName, "SELECT")
s.Attributes().PutStr(semconv.AttributeDBQueryText, "SELECT username FROM users WHERE id = 123") // id value 123 should be obfuscated

err = connector.ConsumeTraces(context.Background(), td)
require.NoError(t, err)

timeout := time.Now().Add(1 * time.Minute)
for time.Now().Before(timeout) {
if len(metricsSink.AllMetrics()) > 0 {
break
}
time.Sleep(100 * time.Millisecond)
}

metrics := metricsSink.AllMetrics()
require.Len(t, metrics, 1)

ch := make(chan []byte, 100)
tr := newTranslatorWithStatsChannel(t, zap.NewNop(), ch)
_, err = tr.MapMetrics(context.Background(), metrics[0], nil)
require.NoError(t, err)
msg := <-ch
sp := &pb.StatsPayload{}

err = proto.Unmarshal(msg, sp)
require.NoError(t, err)
assert.Len(t, sp.Stats, 1)
assert.Len(t, sp.Stats[0].Stats, 1)
assert.Equal(t, "my-env", sp.Stats[0].Env)
assert.Len(t, sp.Stats[0].Stats[0].Stats, 1)
cgss := sp.Stats[0].Stats[0].Stats
expected := []*pb.ClientGroupedStats{
{
Service: "svc",
Name: "mysql.query",
Resource: "SELECT username FROM users WHERE id = ?",
Type: "sql",
Hits: 1,
TopLevelHits: 1,
SpanKind: "client",
IsTraceRoot: pb.Trilean_TRUE,
PeerTags: []string{"db.system:mysql"},
},
}
if diff := cmp.Diff(
cgss,
expected,
protocmp.Transform(),
protocmp.IgnoreFields(&pb.ClientGroupedStats{}, "duration", "okSummary", "errorSummary")); diff != "" {
t.Errorf("Diff between APM stats -want +got:\n%v", diff)
}
}
24 changes: 13 additions & 11 deletions connector/datadogconnector/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ go 1.22.0
require (
github.com/DataDog/datadog-agent/comp/otelcol/otlp/components/metricsclient v0.61.0
github.com/DataDog/datadog-agent/comp/otelcol/otlp/components/statsprocessor v0.61.0
github.com/DataDog/datadog-agent/pkg/proto v0.63.0-devel
github.com/DataDog/datadog-agent/pkg/trace v0.61.0
github.com/DataDog/datadog-agent/pkg/obfuscate v0.63.0-devel.0.20250123185937-1feb84b482c8
github.com/DataDog/datadog-agent/pkg/proto v0.63.0-devel.0.20250123185937-1feb84b482c8
github.com/DataDog/datadog-agent/pkg/trace v0.63.0-devel.0.20250123185937-1feb84b482c8
github.com/DataDog/datadog-go/v5 v5.6.0
github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.24.0
github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/metrics v0.24.0
Expand Down Expand Up @@ -49,6 +50,7 @@ require (
github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface v0.61.0 // indirect
github.com/DataDog/datadog-agent/comp/core/log/def v0.61.0 // indirect
github.com/DataDog/datadog-agent/comp/core/secrets v0.61.0 // indirect
github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.0.0-20241217122454-175edb6c74f2 // indirect
github.com/DataDog/datadog-agent/comp/core/telemetry v0.61.0 // indirect
github.com/DataDog/datadog-agent/comp/def v0.61.0 // indirect
github.com/DataDog/datadog-agent/comp/logs/agent/config v0.61.0 // indirect
Expand Down Expand Up @@ -78,7 +80,6 @@ require (
github.com/DataDog/datadog-agent/pkg/logs/sources v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/logs/status/statusinterface v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/logs/status/utils v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/obfuscate v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/status/health v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/telemetry v0.61.0 // indirect
Expand All @@ -89,7 +90,7 @@ require (
github.com/DataDog/datadog-agent/pkg/util/fxutil v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/hostname/validate v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/http v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/log v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/log v0.63.0-devel.0.20250123185937-1feb84b482c8 // indirect
github.com/DataDog/datadog-agent/pkg/util/optional v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/pointer v0.61.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/scrubber v0.61.0 // indirect
Expand All @@ -101,7 +102,7 @@ require (
github.com/DataDog/datadog-agent/pkg/version v0.61.0 // indirect
github.com/DataDog/datadog-api-client-go/v2 v2.34.0 // indirect
github.com/DataDog/dd-sensitive-data-scanner/sds-go/go v0.0.0-20240816154533-f7f9beb53a42 // indirect
github.com/DataDog/go-sqllexer v0.0.16 // indirect
github.com/DataDog/go-sqllexer v0.0.20 // indirect
github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect
github.com/DataDog/gohai v0.0.0-20230524154621-4316413895ee // indirect
github.com/DataDog/opentelemetry-mapping-go/pkg/inframetadata v0.24.0 // indirect
Expand Down Expand Up @@ -136,7 +137,7 @@ require (
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect
github.com/containerd/cgroups/v3 v3.0.4 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/go-units v0.5.0 // indirect
Expand All @@ -158,10 +159,10 @@ require (
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.10.4 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/mock v1.7.0-rc.1 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
Expand Down Expand Up @@ -195,6 +196,7 @@ require (
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
Expand All @@ -208,10 +210,10 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders v0.118.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.118.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.118.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0-rc.3 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/openshift/api v3.9.0+incompatible // indirect
github.com/openshift/client-go v0.0.0-20210521082421-73d9475a9142 // indirect
github.com/outcaste-io/ristretto v0.2.1 // indirect
github.com/outcaste-io/ristretto v0.2.3 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
Expand All @@ -224,7 +226,7 @@ require (
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shirou/gopsutil/v4 v4.24.12 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
Expand Down
Loading

0 comments on commit 8459bea

Please sign in to comment.