diff --git a/enrichments/trace/config/config.go b/enrichments/trace/config/config.go index 2dd72d3..3ba2819 100644 --- a/enrichments/trace/config/config.go +++ b/enrichments/trace/config/config.go @@ -20,6 +20,7 @@ package config // Config configures the enrichment attributes produced. type Config struct { Resource ResourceConfig `mapstructure:"resource"` + Scope ScopeConfig `mapstructure:"scope"` Transaction ElasticTransactionConfig `mapstructure:"elastic_transaction"` Span ElasticSpanConfig `mapstructure:"elastic_span"` } @@ -30,6 +31,12 @@ type ResourceConfig struct { AgentVersion AttributeConfig `mapstructure:"agent_version"` } +// ScopeConfig configures the enrichment of scope attributes. +type ScopeConfig struct { + ServiceFrameworkName AttributeConfig `mapstructure:"service_framework_name"` + ServiceFrameworkVersion AttributeConfig `mapstructure:"service_framework_version"` +} + // ElasticTransactionConfig configures the enrichment attributes for the // spans which are identified as elastic transaction. type ElasticTransactionConfig struct { @@ -60,6 +67,10 @@ func Enabled() Config { AgentName: AttributeConfig{Enabled: true}, AgentVersion: AttributeConfig{Enabled: true}, }, + Scope: ScopeConfig{ + ServiceFrameworkName: AttributeConfig{Enabled: true}, + ServiceFrameworkVersion: AttributeConfig{Enabled: true}, + }, Transaction: ElasticTransactionConfig{ Root: AttributeConfig{Enabled: true}, Name: AttributeConfig{Enabled: true}, diff --git a/enrichments/trace/config/config_test.go b/enrichments/trace/config/config_test.go index 06f6f42..951f717 100644 --- a/enrichments/trace/config/config_test.go +++ b/enrichments/trace/config/config_test.go @@ -27,6 +27,7 @@ import ( func TestEnabled(t *testing.T) { config := Enabled() assertAllEnabled(t, reflect.ValueOf(config.Resource)) + assertAllEnabled(t, reflect.ValueOf(config.Scope)) assertAllEnabled(t, reflect.ValueOf(config.Transaction)) assertAllEnabled(t, reflect.ValueOf(config.Span)) } diff --git a/enrichments/trace/internal/elastic/attributes.go b/enrichments/trace/internal/elastic/attributes.go index ee4db48..ada8cdb 100644 --- a/enrichments/trace/internal/elastic/attributes.go +++ b/enrichments/trace/internal/elastic/attributes.go @@ -22,6 +22,10 @@ const ( AttributeAgentName = "agent.name" AttributeAgentVersion = "agent.version" + // scope attributes + AttributeServiceFrameworkName = "service.framework.name" + AttributeServiceFrameworkVersion = "service.framework.version" + // span attributes AttributeTransactionRoot = "transaction.root" AttributeTransactionName = "transaction.name" diff --git a/enrichments/trace/internal/elastic/scope.go b/enrichments/trace/internal/elastic/scope.go new file mode 100644 index 0000000..69a664c --- /dev/null +++ b/enrichments/trace/internal/elastic/scope.go @@ -0,0 +1,34 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package elastic + +import ( + "github.com/elastic/opentelemetry-lib/enrichments/trace/config" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// EnrichScope derives and adds Elastic specific scope attributes. +func EnrichScope(scope pcommon.InstrumentationScope, cfg config.Config) { + attrs := scope.Attributes() + if cfg.Scope.ServiceFrameworkName.Enabled { + if name := scope.Name(); name != "" { + attrs.PutStr(AttributeServiceFrameworkName, name) + attrs.PutStr(AttributeServiceFrameworkVersion, scope.Version()) + } + } +} diff --git a/enrichments/trace/internal/elastic/scope_test.go b/enrichments/trace/internal/elastic/scope_test.go new file mode 100644 index 0000000..7aa0500 --- /dev/null +++ b/enrichments/trace/internal/elastic/scope_test.go @@ -0,0 +1,84 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package elastic + +import ( + "testing" + + "github.com/elastic/opentelemetry-lib/enrichments/trace/config" + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func TestScopeEnrich(t *testing.T) { + for _, tc := range []struct { + name string + input pcommon.InstrumentationScope + config config.ScopeConfig + enrichedAttrs map[string]any + }{ + { + name: "all_disabled", + input: pcommon.NewInstrumentationScope(), + enrichedAttrs: map[string]any{}, + }, + { + name: "with_scope_name", + input: func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.SetName("test") + return scope + }(), + config: config.Enabled().Scope, + enrichedAttrs: map[string]any{ + AttributeServiceFrameworkName: "test", + AttributeServiceFrameworkVersion: "", + }, + }, + { + name: "with_scope_name_version", + input: func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.SetName("test") + scope.SetVersion("v1.0.0") + return scope + }(), + config: config.Enabled().Scope, + enrichedAttrs: map[string]any{ + AttributeServiceFrameworkName: "test", + AttributeServiceFrameworkVersion: "v1.0.0", + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + // Merge existing resource attrs with the attrs added + // by enrichment to get the expected attributes. + expectedAttrs := tc.input.Attributes().AsRaw() + for k, v := range tc.enrichedAttrs { + expectedAttrs[k] = v + } + + EnrichScope(tc.input, config.Config{ + Scope: tc.config, + }) + + assert.Empty(t, cmp.Diff(expectedAttrs, tc.input.Attributes().AsRaw())) + }) + } +} diff --git a/enrichments/trace/trace.go b/enrichments/trace/trace.go index 47cf1ef..f9271da 100644 --- a/enrichments/trace/trace.go +++ b/enrichments/trace/trace.go @@ -48,6 +48,7 @@ func (e *Enricher) Enrich(pt ptrace.Traces) { scopeSpans := resSpan.ScopeSpans() for j := 0; j < scopeSpans.Len(); j++ { scopeSpan := scopeSpans.At(j) + elastic.EnrichScope(scopeSpan.Scope(), e.Config) spans := scopeSpan.Spans() for k := 0; k < spans.Len(); k++ { elastic.EnrichSpan(spans.At(k), e.Config)