From ca104e404a4d00bd071d2e88b5d2abd108381d8e Mon Sep 17 00:00:00 2001 From: ericmustin Date: Thu, 20 May 2021 17:40:37 -0400 Subject: [PATCH 01/10] [exporter/datadog]: add span remap option --- exporter/datadogexporter/config/config.go | 16 ++++ .../datadogexporter/config/config_test.go | 10 +++ exporter/datadogexporter/translate_traces.go | 36 ++++++++- .../datadogexporter/translate_traces_test.go | 78 +++++++++++++++---- 4 files changed, 122 insertions(+), 18 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index 3eb4598f5957..fec7382940f4 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -104,6 +104,13 @@ type TracesConfig struct { // all entries must be surrounded by double quotes and separated by commas. // ignore_resources: ["(GET|POST) /healthcheck"] IgnoreResources []string `mapstructure:"ignore_resources"` + + // SpanNameRemappings is the list of current_datadog_span_name:updated_datadog_span_name to use to remap + // automatically generated Datadog Span Operation Names to an updated value. This can be used to shorten + // or modify span names to something more user friendly in the case of instrumentation libraries with + // particularly verbos names + // span_name_remappings: [io.opentelemetry.javaagent.spring.client spring.client, instrumentation::express.server express] + SpanNameRemappings []string `mapstructure:"span_name_remappings"` } // TagsConfig defines the tag-related configuration @@ -243,5 +250,14 @@ func (c *Config) Validate() error { } } } + + if c.Traces.SpanNameRemappings != nil { + for _, entry := range c.Traces.SpanNameRemappings { + SpanNameAndUpdatedName := strings.Split(entry, " ") + if len(SpanNameAndUpdatedName) != 2 { + return fmt.Errorf("'%s' is not valid entry for span name remapping, entry should consist of two space seperated strings", entry) + } + } + } return nil } diff --git a/exporter/datadogexporter/config/config_test.go b/exporter/datadogexporter/config/config_test.go index 0cb62845e7fd..19fc3bc1d9f1 100644 --- a/exporter/datadogexporter/config/config_test.go +++ b/exporter/datadogexporter/config/config_test.go @@ -155,3 +155,13 @@ func TestIgnoreResourcesValidation(t *testing.T) { require.NoError(t, noErr) require.Error(t, err) } + +func TestSpanNameRemappingsValidation(t *testing.T) { + validCfg := Config{Traces: TracesConfig{SpanNameRemappings: []string{"old.opentelemetryspan.name updated.name"}}} + invalidCfg := Config{Traces: TracesConfig{SpanNameRemappings: []string{"oldname:newname"}}} + + noErr := validCfg.Validate() + err := invalidCfg.Validate() + require.NoError(t, noErr) + require.Error(t, err) +} diff --git a/exporter/datadogexporter/translate_traces.go b/exporter/datadogexporter/translate_traces.go index 6ecd78e67125..d61fc5018b42 100644 --- a/exporter/datadogexporter/translate_traces.go +++ b/exporter/datadogexporter/translate_traces.go @@ -74,6 +74,9 @@ func convertToDatadogTd(td pdata.Traces, fallbackHost string, calculator *sublay var runningMetrics []datadog.Metric pushTime := pdata.TimestampFromTime(time.Now()) + + spanNameMap := generateSpanNameMap(cfg) + for i := 0; i < resourceSpans.Len(); i++ { rs := resourceSpans.At(i) host, ok := metadata.HostnameFromAttributes(rs.Resource().Attributes()) @@ -81,7 +84,7 @@ func convertToDatadogTd(td pdata.Traces, fallbackHost string, calculator *sublay host = fallbackHost } - payload := resourceSpansToDatadogSpans(rs, calculator, host, cfg, blk) + payload := resourceSpansToDatadogSpans(rs, calculator, host, cfg, blk, spanNameMap) traces = append(traces, &payload) ms := metrics.DefaultMetrics("traces", host, uint64(pushTime)) @@ -118,7 +121,7 @@ func aggregateTracePayloadsByEnv(tracePayloads []*pb.TracePayload) []*pb.TracePa } // converts a Trace's resource spans into a trace payload -func resourceSpansToDatadogSpans(rs pdata.ResourceSpans, calculator *sublayerCalculator, hostname string, cfg *config.Config, blk *Denylister) pb.TracePayload { +func resourceSpansToDatadogSpans(rs pdata.ResourceSpans, calculator *sublayerCalculator, hostname string, cfg *config.Config, blk *Denylister, spanNameMap map[string]string) pb.TracePayload { // get env tag env := utils.NormalizeTag(cfg.Env) @@ -151,7 +154,7 @@ func resourceSpansToDatadogSpans(rs pdata.ResourceSpans, calculator *sublayerCal extractInstrumentationLibraryTags(ils.InstrumentationLibrary(), datadogTags) spans := ils.Spans() for j := 0; j < spans.Len(); j++ { - span := spanToDatadogSpan(spans.At(j), resourceServiceName, datadogTags, cfg) + span := spanToDatadogSpan(spans.At(j), resourceServiceName, datadogTags, cfg, spanNameMap) var apiTrace *pb.APITrace var ok bool @@ -214,6 +217,7 @@ func spanToDatadogSpan(s pdata.Span, serviceName string, datadogTags map[string]string, cfg *config.Config, + spanNameMap map[string]string, ) *pb.Span { tags := aggregateSpanTags(s, datadogTags) @@ -275,7 +279,7 @@ func spanToDatadogSpan(s pdata.Span, span := &pb.Span{ TraceID: decodeAPMTraceID(s.TraceID().Bytes()), SpanID: decodeAPMSpanID(s.SpanID().Bytes()), - Name: getDatadogSpanName(s, tags), + Name: remapDatadogSpanName(getDatadogSpanName(s, tags), spanNameMap), Resource: resourceName, Service: normalizedServiceName, Start: int64(startTime), @@ -630,3 +634,27 @@ func eventsToString(evts pdata.SpanEventSlice) string { eventArrayBytes, _ := json.Marshal(&eventArray) return string(eventArrayBytes) } + +func generateSpanNameMap(cfg *config.Config) map[string]string { + // we can preset the size to be at most the number of remapping entries + spanNameMap := make(map[string]string, len(cfg.Traces.SpanNameRemappings)) + for _, entry := range cfg.Traces.SpanNameRemappings { + spanNameRemapTuple := strings.Split(entry, " ") + spanNameMap[spanNameRemapTuple[0]] = spanNameRemapTuple[1] + } + + return spanNameMap +} + +// remapDatadogSpanName allows users to map their datadog span operation names to +// another string as they see fit. It's unclear if this should be a set of regexes or simple string +// matching. It's also unclear if we should expose arbitrary remapping, ie, allowing users to map +// to some other dyanmic attribute or value on the span. This would probably cause issues in metric +// computation +func remapDatadogSpanName(name string, spanNameMap map[string]string) string { + if updatedSpanName := spanNameMap[name]; updatedSpanName != "" { + return updatedSpanName + } + + return name +} diff --git a/exporter/datadogexporter/translate_traces_test.go b/exporter/datadogexporter/translate_traces_test.go index a4d5f7201908..a5f5abf2de6a 100644 --- a/exporter/datadogexporter/translate_traces_test.go +++ b/exporter/datadogexporter/translate_traces_test.go @@ -235,7 +235,7 @@ func TestBasicTracesTranslation(t *testing.T) { rs := NewResourceSpansData(mockTraceID, mockSpanID, mockParentSpanID, pdata.StatusCodeUnset, false, mockEndTime) // translate mocks to datadog traces - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -308,7 +308,7 @@ func TestBasicTracesDenylist(t *testing.T) { rs := NewResourceSpansData(mockTraceID, mockSpanID, mockParentSpanID, pdata.StatusCodeUnset, false, mockEndTime) // translate mocks to datadog traces - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -340,7 +340,7 @@ func TestTracesTranslationErrorsAndResource(t *testing.T) { }, } - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -422,7 +422,7 @@ func TestTracesTranslationErrorsFromEventsUsesLast(t *testing.T) { }, } - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) // Ensure the error type is copied over from the last error event logged assert.Equal(t, attribs[conventions.AttributeExceptionType].StringVal(), datadogPayload.Traces[0].Spans[0].Meta[ext.ErrorType]) @@ -477,7 +477,7 @@ func TestTracesTranslationErrorsFromEventsBounds(t *testing.T) { }, } - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) // Ensure the error type is copied over assert.Equal(t, attribs[conventions.AttributeExceptionType].StringVal(), datadogPayload.Traces[0].Spans[0].Meta[ext.ErrorType]) @@ -534,7 +534,7 @@ func TestTracesTranslationOkStatus(t *testing.T) { }, } - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -585,7 +585,7 @@ func TestTracesTranslationConfig(t *testing.T) { } // translate mocks to datadog traces - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -624,7 +624,7 @@ func TestTracesTranslationNoIls(t *testing.T) { } // translate mocks to datadog traces - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -675,9 +675,9 @@ func TestTracesTranslationInvalidService(t *testing.T) { } // translate mocks to datadog traces - datadogPayloadInvalidService := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfgInvalidService, denylister) - datadogPayloadEmptyService := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfgEmptyService, denylister) - datadogPayloadStartWithInvalidService := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfgStartWithInvalidService, denylister) + datadogPayloadInvalidService := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfgInvalidService, denylister, map[string]string{}) + datadogPayloadEmptyService := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfgEmptyService, denylister, map[string]string{}) + datadogPayloadStartWithInvalidService := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfgStartWithInvalidService, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayloadInvalidService) @@ -712,7 +712,7 @@ func TestTracesTranslationServicePeerName(t *testing.T) { span.Attributes().InsertString(conventions.AttributePeerService, "my_peer_service_name") // translate mocks to datadog traces - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -788,7 +788,7 @@ func TestTracesTranslationTruncatetag(t *testing.T) { span.Attributes().InsertString(conventions.AttributeExceptionStacktrace, RandStringBytes(5500)) // translate mocks to datadog traces - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &config.Config{}, denylister, map[string]string{}) // ensure we return the correct type assert.IsType(t, pb.TracePayload{}, datadogPayload) @@ -1184,7 +1184,7 @@ func TestStatsAggregations(t *testing.T) { // translate mocks to datadog traces cfg := config.Config{} - datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister) + datadogPayload := resourceSpansToDatadogSpans(rs, calculator, hostname, &cfg, denylister, map[string]string{}) statsOutput := computeAPMStats(&datadogPayload, calculator, time.Now().UTC().UnixNano()) @@ -1290,3 +1290,53 @@ func TestNormalizeTag(t *testing.T) { }) } } + +// ensure that sanitization of trace payloads occurs +func TestSpanNameMapping(t *testing.T) { + mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} + mockSpanID := [8]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8} + mockParentSpanID := [8]byte{0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8} + endTime := time.Now().Round(time.Second) + pdataEndTime := pdata.TimestampFromTime(endTime) + startTime := endTime.Add(-90 * time.Second) + pdataStartTime := pdata.TimestampFromTime(startTime) + + calculator := newSublayerCalculator() + denylister := NewDenylister([]string{}) + + traces := pdata.NewTraces() + traces.ResourceSpans().Resize(1) + rs := traces.ResourceSpans().At(0) + resource := rs.Resource() + resource.Attributes().InitFromMap(map[string]pdata.AttributeValue{ + "deployment.environment": pdata.NewAttributeValueString("UpperCase"), + }) + rs.InstrumentationLibrarySpans().Resize(1) + ilss := rs.InstrumentationLibrarySpans().At(0) + instrumentationLibrary := ilss.InstrumentationLibrary() + instrumentationLibrary.SetName("flash") + instrumentationLibrary.SetVersion("v1") + span := ilss.Spans().AppendEmpty() + + traceID := pdata.NewTraceID(mockTraceID) + spanID := pdata.NewSpanID(mockSpanID) + parentSpanID := pdata.NewSpanID(mockParentSpanID) + span.SetTraceID(traceID) + span.SetSpanID(spanID) + span.SetParentSpanID(parentSpanID) + span.SetName("End-To-End Here") + span.SetKind(pdata.SpanKindServer) + span.SetStartTimestamp(pdataStartTime) + span.SetEndTimestamp(pdataEndTime) + + config := config.Config{Traces: config.TracesConfig{SpanNameRemappings: []string{"flash.server bang.client"}}} + + outputTraces, _ := convertToDatadogTd(traces, "test-host", calculator, &config, denylister) + aggregatedTraces := aggregateTracePayloadsByEnv(outputTraces) + + obfuscator := obfuscate.NewObfuscator(obfuscatorConfig) + obfuscatePayload(obfuscator, aggregatedTraces) + assert.Equal(t, 1, len(aggregatedTraces)) + + assert.Equal(t, "bang.client", aggregatedTraces[0].Traces[0].Spans[0].Name) +} From 14f69d683241a87419b2cd068d98a8d0d64b219c Mon Sep 17 00:00:00 2001 From: ericmustin Date: Thu, 20 May 2021 18:04:48 -0400 Subject: [PATCH 02/10] [exporter/datadog]: add documentation around span_name_remappings config option --- exporter/datadogexporter/config/config.go | 11 ++++++----- exporter/datadogexporter/example/config.yaml | 12 +++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index fec7382940f4..808dfaec4384 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -105,11 +105,12 @@ type TracesConfig struct { // ignore_resources: ["(GET|POST) /healthcheck"] IgnoreResources []string `mapstructure:"ignore_resources"` - // SpanNameRemappings is the list of current_datadog_span_name:updated_datadog_span_name to use to remap - // automatically generated Datadog Span Operation Names to an updated value. This can be used to shorten - // or modify span names to something more user friendly in the case of instrumentation libraries with - // particularly verbos names - // span_name_remappings: [io.opentelemetry.javaagent.spring.client spring.client, instrumentation::express.server express] + // SpanNameRemappings is the list of datadog span names and preferred names to map to. This can be used to + // automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to + // shorten or modify span names to something more user friendly in the case of instrumentation libraries with + // particularly verbose names. All entries must be surrounded by double quotes and be seperated by commas, with each entry + // between old and updated name seperated by a space. + // span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] SpanNameRemappings []string `mapstructure:"span_name_remappings"` } diff --git a/exporter/datadogexporter/example/config.yaml b/exporter/datadogexporter/example/config.yaml index e4865b713be3..1880576ea2fb 100644 --- a/exporter/datadogexporter/example/config.yaml +++ b/exporter/datadogexporter/example/config.yaml @@ -120,7 +120,17 @@ exporters: ## A blacklist of regular expressions can be provided to disable certain traces based on their resource name ## all entries must be surrounded by double quotes and separated by commas. # - # ignore_resources: ["(GET|POST) /healthcheck"] + # ignore_resources: ["(GET|POST) /healthcheck"] + + ## @param span_name_remappings - list of strings - optional + ## A list of Datadog span operation names and preferred names to update those names to. This can be used to + ## automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to + ## shorten or modify span names to something more user friendly in the case of instrumentation libraries with + ## particularly verbose names. All entries must be surrounded by double quotes and be seperated by commas, with each entry + ## between old and updated name seperated by a space. + # + # span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] + service: pipelines: From 046c2261c2aafb2965228c66ef080410d1cd04b9 Mon Sep 17 00:00:00 2001 From: ericmustin Date: Thu, 20 May 2021 18:35:55 -0400 Subject: [PATCH 03/10] [exporter/datadog]: spelling and linting and other assorted small joys --- exporter/datadogexporter/config/config.go | 6 +++--- exporter/datadogexporter/example/config.yaml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index 808dfaec4384..4fbd8532c946 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -108,8 +108,8 @@ type TracesConfig struct { // SpanNameRemappings is the list of datadog span names and preferred names to map to. This can be used to // automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to // shorten or modify span names to something more user friendly in the case of instrumentation libraries with - // particularly verbose names. All entries must be surrounded by double quotes and be seperated by commas, with each entry - // between old and updated name seperated by a space. + // particularly verbose names. All entries must be surrounded by double quotes and be separated by commas, with each entry + // between old and updated name separated by a space. // span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] SpanNameRemappings []string `mapstructure:"span_name_remappings"` } @@ -256,7 +256,7 @@ func (c *Config) Validate() error { for _, entry := range c.Traces.SpanNameRemappings { SpanNameAndUpdatedName := strings.Split(entry, " ") if len(SpanNameAndUpdatedName) != 2 { - return fmt.Errorf("'%s' is not valid entry for span name remapping, entry should consist of two space seperated strings", entry) + return fmt.Errorf("'%s' is not valid entry for span name remapping, entry should consist of two space separated strings", entry) } } } diff --git a/exporter/datadogexporter/example/config.yaml b/exporter/datadogexporter/example/config.yaml index 1880576ea2fb..4fc91c50b3a3 100644 --- a/exporter/datadogexporter/example/config.yaml +++ b/exporter/datadogexporter/example/config.yaml @@ -126,8 +126,8 @@ exporters: ## A list of Datadog span operation names and preferred names to update those names to. This can be used to ## automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to ## shorten or modify span names to something more user friendly in the case of instrumentation libraries with - ## particularly verbose names. All entries must be surrounded by double quotes and be seperated by commas, with each entry - ## between old and updated name seperated by a space. + ## particularly verbose names. All entries must be surrounded by double quotes and be separated by commas, with each entry + ## between old and updated name separated by a space. # # span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] From 939843762fe99fa0ac9b95085070b5ad7a20dd88 Mon Sep 17 00:00:00 2001 From: Eric Mustin Date: Fri, 21 May 2021 09:39:45 -0400 Subject: [PATCH 04/10] Update exporter/datadogexporter/translate_traces.go Co-authored-by: Pablo Baeyens --- exporter/datadogexporter/translate_traces.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/exporter/datadogexporter/translate_traces.go b/exporter/datadogexporter/translate_traces.go index d61fc5018b42..4f58dc41b22d 100644 --- a/exporter/datadogexporter/translate_traces.go +++ b/exporter/datadogexporter/translate_traces.go @@ -647,10 +647,7 @@ func generateSpanNameMap(cfg *config.Config) map[string]string { } // remapDatadogSpanName allows users to map their datadog span operation names to -// another string as they see fit. It's unclear if this should be a set of regexes or simple string -// matching. It's also unclear if we should expose arbitrary remapping, ie, allowing users to map -// to some other dyanmic attribute or value on the span. This would probably cause issues in metric -// computation +// another string as they see fit. func remapDatadogSpanName(name string, spanNameMap map[string]string) string { if updatedSpanName := spanNameMap[name]; updatedSpanName != "" { return updatedSpanName From 0b5605b643ecb551e5c3090529834b2b14d26ab5 Mon Sep 17 00:00:00 2001 From: ericmustin Date: Tue, 25 May 2021 15:54:31 -0400 Subject: [PATCH 05/10] [exporter/datadog]: update span remapping to use a map --- exporter/datadogexporter/config/config.go | 12 +++++++----- exporter/datadogexporter/config/config_test.go | 4 ++-- exporter/datadogexporter/translate_traces.go | 13 +------------ exporter/datadogexporter/translate_traces_test.go | 7 +++++-- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index 4fbd8532c946..afec11676b7d 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -111,7 +111,7 @@ type TracesConfig struct { // particularly verbose names. All entries must be surrounded by double quotes and be separated by commas, with each entry // between old and updated name separated by a space. // span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] - SpanNameRemappings []string `mapstructure:"span_name_remappings"` + SpanNameRemappings map[string]string `mapstructure:"span_name_remappings"` } // TagsConfig defines the tag-related configuration @@ -253,10 +253,12 @@ func (c *Config) Validate() error { } if c.Traces.SpanNameRemappings != nil { - for _, entry := range c.Traces.SpanNameRemappings { - SpanNameAndUpdatedName := strings.Split(entry, " ") - if len(SpanNameAndUpdatedName) != 2 { - return fmt.Errorf("'%s' is not valid entry for span name remapping, entry should consist of two space separated strings", entry) + for key, value := range c.Traces.SpanNameRemappings { + if value == "" { + return fmt.Errorf("'%s' is not valid value for span name remapping", value) + } + if key == "" { + return fmt.Errorf("'%s' is not valid key for span name remapping", key) } } } diff --git a/exporter/datadogexporter/config/config_test.go b/exporter/datadogexporter/config/config_test.go index 19fc3bc1d9f1..90e1c57fb3fa 100644 --- a/exporter/datadogexporter/config/config_test.go +++ b/exporter/datadogexporter/config/config_test.go @@ -157,8 +157,8 @@ func TestIgnoreResourcesValidation(t *testing.T) { } func TestSpanNameRemappingsValidation(t *testing.T) { - validCfg := Config{Traces: TracesConfig{SpanNameRemappings: []string{"old.opentelemetryspan.name updated.name"}}} - invalidCfg := Config{Traces: TracesConfig{SpanNameRemappings: []string{"oldname:newname"}}} + validCfg := Config{Traces: TracesConfig{SpanNameRemappings: map[string]string{"old.opentelemetryspan.name":"updated.name"}}} + invalidCfg := Config{Traces: TracesConfig{SpanNameRemappings: map[string]string{"oldname": ""}} noErr := validCfg.Validate() err := invalidCfg.Validate() diff --git a/exporter/datadogexporter/translate_traces.go b/exporter/datadogexporter/translate_traces.go index f6cd3b68aac1..b343cf271a5b 100644 --- a/exporter/datadogexporter/translate_traces.go +++ b/exporter/datadogexporter/translate_traces.go @@ -76,7 +76,7 @@ func convertToDatadogTd(td pdata.Traces, fallbackHost string, calculator *sublay var runningMetrics []datadog.Metric pushTime := pdata.TimestampFromTime(time.Now()) - spanNameMap := generateSpanNameMap(cfg) + spanNameMap := cfg.Traces.SpanNameRemappings for i := 0; i < resourceSpans.Len(); i++ { rs := resourceSpans.At(i) @@ -636,17 +636,6 @@ func eventsToString(evts pdata.SpanEventSlice) string { return string(eventArrayBytes) } -func generateSpanNameMap(cfg *config.Config) map[string]string { - // we can preset the size to be at most the number of remapping entries - spanNameMap := make(map[string]string, len(cfg.Traces.SpanNameRemappings)) - for _, entry := range cfg.Traces.SpanNameRemappings { - spanNameRemapTuple := strings.Split(entry, " ") - spanNameMap[spanNameRemapTuple[0]] = spanNameRemapTuple[1] - } - - return spanNameMap -} - // remapDatadogSpanName allows users to map their datadog span operation names to // another string as they see fit. It's unclear if this should be a set of regexes or simple string // matching. It's also unclear if we should expose arbitrary remapping, ie, allowing users to map diff --git a/exporter/datadogexporter/translate_traces_test.go b/exporter/datadogexporter/translate_traces_test.go index 79440e869645..6101abb7d217 100644 --- a/exporter/datadogexporter/translate_traces_test.go +++ b/exporter/datadogexporter/translate_traces_test.go @@ -1320,6 +1320,9 @@ func TestSpanNameMapping(t *testing.T) { calculator := newSublayerCalculator() denylister := NewDenylister([]string{}) + buildInfo := component.BuildInfo{ + Version: "1.0", + } traces := pdata.NewTraces() traces.ResourceSpans().Resize(1) @@ -1346,9 +1349,9 @@ func TestSpanNameMapping(t *testing.T) { span.SetStartTimestamp(pdataStartTime) span.SetEndTimestamp(pdataEndTime) - config := config.Config{Traces: config.TracesConfig{SpanNameRemappings: []string{"flash.server bang.client"}}} + config := config.Config{Traces: config.TracesConfig{SpanNameRemappings: map[string]string{"flash.server": "bang.client"}}} - outputTraces, _ := convertToDatadogTd(traces, "test-host", calculator, &config, denylister) + outputTraces, _ := convertToDatadogTd(traces, "test-host", calculator, &config, denylister, buildInfo) aggregatedTraces := aggregateTracePayloadsByEnv(outputTraces) obfuscator := obfuscate.NewObfuscator(obfuscatorConfig) From dfb5585994d9a90ab285d0e10c3496d41becf32c Mon Sep 17 00:00:00 2001 From: ericmustin Date: Tue, 25 May 2021 15:56:29 -0400 Subject: [PATCH 06/10] [exporter/datadog]: linting span remapper --- exporter/datadogexporter/config/config.go | 2 +- exporter/datadogexporter/config/config_test.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index afec11676b7d..baccb045cfa7 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -258,7 +258,7 @@ func (c *Config) Validate() error { return fmt.Errorf("'%s' is not valid value for span name remapping", value) } if key == "" { - return fmt.Errorf("'%s' is not valid key for span name remapping", key) + return fmt.Errorf("'%s' is not valid key for span name remapping", key) } } } diff --git a/exporter/datadogexporter/config/config_test.go b/exporter/datadogexporter/config/config_test.go index 90e1c57fb3fa..029ad72d3e21 100644 --- a/exporter/datadogexporter/config/config_test.go +++ b/exporter/datadogexporter/config/config_test.go @@ -157,9 +157,8 @@ func TestIgnoreResourcesValidation(t *testing.T) { } func TestSpanNameRemappingsValidation(t *testing.T) { - validCfg := Config{Traces: TracesConfig{SpanNameRemappings: map[string]string{"old.opentelemetryspan.name":"updated.name"}}} - invalidCfg := Config{Traces: TracesConfig{SpanNameRemappings: map[string]string{"oldname": ""}} - + validCfg := Config{Traces: TracesConfig{SpanNameRemappings: map[string]string{"old.opentelemetryspan.name": "updated.name"}}} + invalidCfg := Config{Traces: TracesConfig{SpanNameRemappings: map[string]string{"oldname": ""}}} noErr := validCfg.Validate() err := invalidCfg.Validate() require.NoError(t, noErr) From 4e923104b964c1c04ac8f545f9f7172016e14a43 Mon Sep 17 00:00:00 2001 From: ericmustin Date: Tue, 25 May 2021 16:36:31 -0400 Subject: [PATCH 07/10] [exporter/datadog]: add config formatting --- exporter/datadogexporter/config/config.go | 2 +- exporter/datadogexporter/example/config.yaml | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index baccb045cfa7..8111a03d0344 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -105,7 +105,7 @@ type TracesConfig struct { // ignore_resources: ["(GET|POST) /healthcheck"] IgnoreResources []string `mapstructure:"ignore_resources"` - // SpanNameRemappings is the list of datadog span names and preferred names to map to. This can be used to + // SpanNameRemappings is the map of datadog span names and preferred name to map to. This can be used to // automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to // shorten or modify span names to something more user friendly in the case of instrumentation libraries with // particularly verbose names. All entries must be surrounded by double quotes and be separated by commas, with each entry diff --git a/exporter/datadogexporter/example/config.yaml b/exporter/datadogexporter/example/config.yaml index 4fc91c50b3a3..04c72dc52afe 100644 --- a/exporter/datadogexporter/example/config.yaml +++ b/exporter/datadogexporter/example/config.yaml @@ -122,14 +122,15 @@ exporters: # # ignore_resources: ["(GET|POST) /healthcheck"] - ## @param span_name_remappings - list of strings - optional - ## A list of Datadog span operation names and preferred names to update those names to. This can be used to + ## @param span_name_remappings - map of key/value pairs - optional + ## A map of Datadog span operation name keys and preferred name valuues to update those names to. This can be used to ## automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to ## shorten or modify span names to something more user friendly in the case of instrumentation libraries with - ## particularly verbose names. All entries must be surrounded by double quotes and be separated by commas, with each entry - ## between old and updated name separated by a space. + ## particularly verbose names. # - # span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] + # span_name_remappings: + # io.opentelemetry.javaagent.spring.client: spring.client + # instrumentation::express.server: express service: From b565b12149fdba8662d726e1f213b454259cad41 Mon Sep 17 00:00:00 2001 From: ericmustin Date: Wed, 2 Jun 2021 11:42:58 -0400 Subject: [PATCH 08/10] [exporter/datadog]: update span name remappings, make some details private --- exporter/datadogexporter/config/config.go | 9 +++-- exporter/datadogexporter/denylister.go | 8 ++--- exporter/datadogexporter/denylister_test.go | 8 ++--- exporter/datadogexporter/traces_exporter.go | 2 +- exporter/datadogexporter/translate_traces.go | 2 +- .../datadogexporter/translate_traces_test.go | 36 +++++++++---------- 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index 8111a03d0344..5e970a89cf36 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -106,11 +106,10 @@ type TracesConfig struct { IgnoreResources []string `mapstructure:"ignore_resources"` // SpanNameRemappings is the map of datadog span names and preferred name to map to. This can be used to - // automatically map Datadog Span Operation Names to an updated value, and is useful when a user wants to - // shorten or modify span names to something more user friendly in the case of instrumentation libraries with - // particularly verbose names. All entries must be surrounded by double quotes and be separated by commas, with each entry - // between old and updated name separated by a space. - // span_name_remappings: ["io.opentelemetry.javaagent.spring.client spring.client", "instrumentation::express.server express"] + // automatically map Datadog Span Operation Names to an updated value. All entries should be key/value pairs. + // span_name_remappings: + // io.opentelemetry.javaagent.spring.client: spring.client + // instrumentation::express.server: express SpanNameRemappings map[string]string `mapstructure:"span_name_remappings"` } diff --git a/exporter/datadogexporter/denylister.go b/exporter/datadogexporter/denylister.go index 7584f6bfae8b..ab17d62add6f 100644 --- a/exporter/datadogexporter/denylister.go +++ b/exporter/datadogexporter/denylister.go @@ -27,9 +27,9 @@ type Denylister struct { list []*regexp.Regexp } -// Allows returns true if the Denylister permits this span. +// allows returns true if the Denylister permits this span. // From: https://github.com/DataDog/datadog-agent/blob/a6872e436681ea2136cf8a67465e99fdb4450519/pkg/trace/filters/blacklister.go#L21-L29 -func (f *Denylister) Allows(span *pb.Span) bool { +func (f *Denylister) allows(span *pb.Span) bool { for _, entry := range f.list { if entry.MatchString(span.Resource) { return false @@ -38,10 +38,10 @@ func (f *Denylister) Allows(span *pb.Span) bool { return true } -// NewDenylister creates a new Denylister based on the given list of +// newDenylister creates a new Denylister based on the given list of // regular expressions. // From: https://github.com/DataDog/datadog-agent/blob/a6872e436681ea2136cf8a67465e99fdb4450519/pkg/trace/filters/blacklister.go#L41-L45 -func NewDenylister(exprs []string) *Denylister { +func newDenylister(exprs []string) *Denylister { return &Denylister{list: compileRules(exprs)} } diff --git a/exporter/datadogexporter/denylister_test.go b/exporter/datadogexporter/denylister_test.go index f6bcc42dcc71..13776ac9fa30 100644 --- a/exporter/datadogexporter/denylister_test.go +++ b/exporter/datadogexporter/denylister_test.go @@ -68,16 +68,16 @@ func TestDenylister(t *testing.T) { for _, test := range tests { span := testSpan() span.Resource = test.resource - filter := NewDenylister(test.filter) + filter := newDenylister(test.filter) - assert.Equal(t, test.expectation, filter.Allows(span)) + assert.Equal(t, test.expectation, filter.allows(span)) } } func TestCompileRules(t *testing.T) { - filter := NewDenylister([]string{"\n{6}"}) + filter := newDenylister([]string{"\n{6}"}) for i := 0; i < 100; i++ { span := testSpan() - assert.True(t, filter.Allows(span)) + assert.True(t, filter.allows(span)) } } diff --git a/exporter/datadogexporter/traces_exporter.go b/exporter/datadogexporter/traces_exporter.go index 2e85bb0717cb..7b05f8d65fca 100644 --- a/exporter/datadogexporter/traces_exporter.go +++ b/exporter/datadogexporter/traces_exporter.go @@ -87,7 +87,7 @@ func newTracesExporter(ctx context.Context, params component.ExporterCreateParam obfuscator := obfuscate.NewObfuscator(obfuscatorConfig) // a denylist for dropping ignored resources - denylister := NewDenylister(cfg.Traces.IgnoreResources) + denylister := newDenylister(cfg.Traces.IgnoreResources) calculator := &sublayerCalculator{sc: stats.NewSublayerCalculator()} exporter := &traceExporter{ diff --git a/exporter/datadogexporter/translate_traces.go b/exporter/datadogexporter/translate_traces.go index 7d66832f5ed9..fd77ad4a82b1 100644 --- a/exporter/datadogexporter/translate_traces.go +++ b/exporter/datadogexporter/translate_traces.go @@ -192,7 +192,7 @@ func resourceSpansToDatadogSpans(rs pdata.ResourceSpans, calculator *sublayerCal // Root span is used to carry some trace-level metadata, such as sampling rate and priority. rootSpan := utils.GetRoot(apiTrace) - if !blk.Allows(rootSpan) { + if !blk.allows(rootSpan) { // drop trace by not adding to payload if it's root span matches denylist continue } diff --git a/exporter/datadogexporter/translate_traces_test.go b/exporter/datadogexporter/translate_traces_test.go index 6101abb7d217..560f4f0628ff 100644 --- a/exporter/datadogexporter/translate_traces_test.go +++ b/exporter/datadogexporter/translate_traces_test.go @@ -138,7 +138,7 @@ func TestConvertToDatadogTd(t *testing.T) { traces := pdata.NewTraces() traces.ResourceSpans().AppendEmpty() calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) buildInfo := component.BuildInfo{ Version: "1.0", } @@ -151,7 +151,7 @@ func TestConvertToDatadogTd(t *testing.T) { func TestConvertToDatadogTdNoResourceSpans(t *testing.T) { traces := pdata.NewTraces() calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) buildInfo := component.BuildInfo{ Version: "1.0", } @@ -184,7 +184,7 @@ func TestRunningTraces(t *testing.T) { Version: "1.0", } - _, runningMetrics := convertToDatadogTd(td, "fallbackHost", newSublayerCalculator(), &config.Config{}, NewDenylister([]string{}), buildInfo) + _, runningMetrics := convertToDatadogTd(td, "fallbackHost", newSublayerCalculator(), &config.Config{}, newDenylister([]string{}), buildInfo) runningHostnames := []string{} for _, metric := range runningMetrics { @@ -201,7 +201,7 @@ func TestRunningTraces(t *testing.T) { func TestObfuscation(t *testing.T) { calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) buildInfo := component.BuildInfo{ Version: "1.0", } @@ -236,7 +236,7 @@ func TestObfuscation(t *testing.T) { func TestBasicTracesTranslation(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -309,7 +309,7 @@ func TestBasicTracesDenylist(t *testing.T) { calculator := newSublayerCalculator() // adding some regex bits to the resource name, but this should drop the trace - denylister := NewDenylister([]string{".nd-To-E.d H.re"}) + denylister := newDenylister([]string{".nd-To-E.d H.re"}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -334,7 +334,7 @@ func TestBasicTracesDenylist(t *testing.T) { func TestTracesTranslationErrorsAndResource(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -388,7 +388,7 @@ func TestTracesTranslationErrorsAndResource(t *testing.T) { func TestTracesTranslationErrorsFromEventsUsesLast(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -452,7 +452,7 @@ func TestTracesTranslationErrorsFromEventsUsesLast(t *testing.T) { func TestTracesTranslationErrorsFromEventsBounds(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -528,7 +528,7 @@ func TestTracesTranslationErrorsFromEventsBounds(t *testing.T) { func TestTracesTranslationOkStatus(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -578,7 +578,7 @@ func TestTracesTranslationOkStatus(t *testing.T) { func TestTracesTranslationConfig(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -626,7 +626,7 @@ func TestTracesTranslationConfig(t *testing.T) { func TestTracesTranslationNoIls(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) rs := pdata.NewResourceSpans() @@ -651,7 +651,7 @@ func TestTracesTranslationNoIls(t *testing.T) { func TestTracesTranslationInvalidService(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -710,7 +710,7 @@ func TestTracesTranslationInvalidService(t *testing.T) { func TestTracesTranslationServicePeerName(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -785,7 +785,7 @@ func TestTracesTranslationServicePeerName(t *testing.T) { func TestTracesTranslationTruncatetag(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -1182,7 +1182,7 @@ func TestTracePayloadAggr(t *testing.T) { func TestStatsAggregations(t *testing.T) { hostname := "testhostname" calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) // generate mock trace, span and parent span ids mockTraceID := [16]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} @@ -1219,7 +1219,7 @@ func TestStatsAggregations(t *testing.T) { // ensure that sanitization of trace payloads occurs func TestSanitization(t *testing.T) { calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) buildInfo := component.BuildInfo{ Version: "1.0", } @@ -1319,7 +1319,7 @@ func TestSpanNameMapping(t *testing.T) { pdataStartTime := pdata.TimestampFromTime(startTime) calculator := newSublayerCalculator() - denylister := NewDenylister([]string{}) + denylister := newDenylister([]string{}) buildInfo := component.BuildInfo{ Version: "1.0", } From 762034b3428f87d286ea8800e00599ee50a235f3 Mon Sep 17 00:00:00 2001 From: ericmustin Date: Wed, 2 Jun 2021 11:48:15 -0400 Subject: [PATCH 09/10] [exporter/datadog]: make more details of denylister private --- exporter/datadogexporter/denylister.go | 10 +++++----- exporter/datadogexporter/traces_exporter.go | 2 +- exporter/datadogexporter/translate_traces.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/exporter/datadogexporter/denylister.go b/exporter/datadogexporter/denylister.go index ab17d62add6f..6b0a1a7689eb 100644 --- a/exporter/datadogexporter/denylister.go +++ b/exporter/datadogexporter/denylister.go @@ -20,16 +20,16 @@ import ( "github.com/DataDog/datadog-agent/pkg/trace/exportable/pb" ) -// Denylister holds a list of regular expressions which will match resources +// denylister holds a list of regular expressions which will match resources // on spans that should be dropped. // From: https://github.com/DataDog/datadog-agent/blob/a6872e436681ea2136cf8a67465e99fdb4450519/pkg/trace/filters/blacklister.go#L15-L19 -type Denylister struct { +type denylister struct { list []*regexp.Regexp } // allows returns true if the Denylister permits this span. // From: https://github.com/DataDog/datadog-agent/blob/a6872e436681ea2136cf8a67465e99fdb4450519/pkg/trace/filters/blacklister.go#L21-L29 -func (f *Denylister) allows(span *pb.Span) bool { +func (f *denylister) allows(span *pb.Span) bool { for _, entry := range f.list { if entry.MatchString(span.Resource) { return false @@ -41,8 +41,8 @@ func (f *Denylister) allows(span *pb.Span) bool { // newDenylister creates a new Denylister based on the given list of // regular expressions. // From: https://github.com/DataDog/datadog-agent/blob/a6872e436681ea2136cf8a67465e99fdb4450519/pkg/trace/filters/blacklister.go#L41-L45 -func newDenylister(exprs []string) *Denylister { - return &Denylister{list: compileRules(exprs)} +func newDenylister(exprs []string) *denylister { + return &denylister{list: compileRules(exprs)} } // compileRules compiles as many rules as possible from the list of expressions. diff --git a/exporter/datadogexporter/traces_exporter.go b/exporter/datadogexporter/traces_exporter.go index 7b05f8d65fca..932d8a85ba1c 100644 --- a/exporter/datadogexporter/traces_exporter.go +++ b/exporter/datadogexporter/traces_exporter.go @@ -56,7 +56,7 @@ type traceExporter struct { obfuscator *obfuscate.Obfuscator calculator *sublayerCalculator client *datadog.Client - denylister *Denylister + denylister *denylister } var ( diff --git a/exporter/datadogexporter/translate_traces.go b/exporter/datadogexporter/translate_traces.go index fd77ad4a82b1..671bad73cc22 100644 --- a/exporter/datadogexporter/translate_traces.go +++ b/exporter/datadogexporter/translate_traces.go @@ -64,7 +64,7 @@ const ( ) // converts Traces into an array of datadog trace payloads grouped by env -func convertToDatadogTd(td pdata.Traces, fallbackHost string, calculator *sublayerCalculator, cfg *config.Config, blk *Denylister, buildInfo component.BuildInfo) ([]*pb.TracePayload, []datadog.Metric) { +func convertToDatadogTd(td pdata.Traces, fallbackHost string, calculator *sublayerCalculator, cfg *config.Config, blk *denylister, buildInfo component.BuildInfo) ([]*pb.TracePayload, []datadog.Metric) { // TODO: // do we apply other global tags, like version+service, to every span or only root spans of a service // should globalTags['service'] take precedence over a trace's resource.service.name? I don't believe so, need to confirm @@ -122,7 +122,7 @@ func aggregateTracePayloadsByEnv(tracePayloads []*pb.TracePayload) []*pb.TracePa } // converts a Trace's resource spans into a trace payload -func resourceSpansToDatadogSpans(rs pdata.ResourceSpans, calculator *sublayerCalculator, hostname string, cfg *config.Config, blk *Denylister, spanNameMap map[string]string) pb.TracePayload { +func resourceSpansToDatadogSpans(rs pdata.ResourceSpans, calculator *sublayerCalculator, hostname string, cfg *config.Config, blk *denylister, spanNameMap map[string]string) pb.TracePayload { // get env tag env := utils.NormalizeTag(cfg.Env) From 0bc5fabbcdbbcc7e030f6e17e473e1597e6dfba1 Mon Sep 17 00:00:00 2001 From: ericmustin Date: Wed, 2 Jun 2021 13:26:27 -0400 Subject: [PATCH 10/10] [expoter/datadog]: also make traceconnection private --- exporter/datadogexporter/trace_connection.go | 18 +++++++++--------- exporter/datadogexporter/traces_exporter.go | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/exporter/datadogexporter/trace_connection.go b/exporter/datadogexporter/trace_connection.go index 4ca28bacd3dc..12c215338fc3 100644 --- a/exporter/datadogexporter/trace_connection.go +++ b/exporter/datadogexporter/trace_connection.go @@ -29,13 +29,13 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/utils" ) -// TraceEdgeConnection is used to send data to trace edge -type TraceEdgeConnection interface { +// traceEdgeConnection is used to send data to trace edge +type traceEdgeConnection interface { SendTraces(ctx context.Context, trace *pb.TracePayload, maxRetries int) error SendStats(ctx context.Context, stats *stats.Payload, maxRetries int) error } -type traceEdgeConnection struct { +type traceEdgeConnectionImpl struct { traceURL string statsURL string apiKey string @@ -49,10 +49,10 @@ const ( traceEdgeRetryInterval time.Duration = 10 * time.Second ) -// createTraceEdgeConnection returns a new TraceEdgeConnection -func createTraceEdgeConnection(rootURL, apiKey string, buildInfo component.BuildInfo) TraceEdgeConnection { +// createTraceEdgeConnection returns a new traceEdgeConnection +func createTraceEdgeConnection(rootURL, apiKey string, buildInfo component.BuildInfo) traceEdgeConnection { - return &traceEdgeConnection{ + return &traceEdgeConnectionImpl{ traceURL: rootURL + "/api/v0.2/traces", statsURL: rootURL + "/api/v0.2/stats", buildInfo: buildInfo, @@ -69,7 +69,7 @@ type Payload struct { } // SendTraces serializes a trace payload to protobuf and sends it to Trace Edge -func (con *traceEdgeConnection) SendTraces(ctx context.Context, trace *pb.TracePayload, maxRetries int) error { +func (con *traceEdgeConnectionImpl) SendTraces(ctx context.Context, trace *pb.TracePayload, maxRetries int) error { binary, marshallErr := proto.Marshal(trace) if marshallErr != nil { return fmt.Errorf("failed to serialize trace payload to protobuf: %w", marshallErr) @@ -108,7 +108,7 @@ func (con *traceEdgeConnection) SendTraces(ctx context.Context, trace *pb.TraceP } // SendStats serializes a stats payload to json and sends it to Trace Edge -func (con *traceEdgeConnection) SendStats(ctx context.Context, sts *stats.Payload, maxRetries int) error { +func (con *traceEdgeConnectionImpl) SendStats(ctx context.Context, sts *stats.Payload, maxRetries int) error { var b bytes.Buffer err := stats.EncodePayload(&b, sts) if err != nil { @@ -145,7 +145,7 @@ func (con *traceEdgeConnection) SendStats(ctx context.Context, sts *stats.Payloa } // sendPayloadToTraceEdge sends a payload to Trace Edge -func (con *traceEdgeConnection) sendPayloadToTraceEdge(ctx context.Context, apiKey string, payload *Payload, url string) (bool, error) { +func (con *traceEdgeConnectionImpl) sendPayloadToTraceEdge(ctx context.Context, apiKey string, payload *Payload, url string) (bool, error) { // Create the request to be sent to the API req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload.Bytes)) diff --git a/exporter/datadogexporter/traces_exporter.go b/exporter/datadogexporter/traces_exporter.go index d04d222f6d20..e5832cd4c08c 100644 --- a/exporter/datadogexporter/traces_exporter.go +++ b/exporter/datadogexporter/traces_exporter.go @@ -35,7 +35,7 @@ type traceExporter struct { params component.ExporterCreateParams cfg *config.Config ctx context.Context - edgeConnection TraceEdgeConnection + edgeConnection traceEdgeConnection obfuscator *obfuscate.Obfuscator client *datadog.Client denylister *denylister