diff --git a/exporter/azuremonitorexporter/contracts_utils.go b/exporter/azuremonitorexporter/contracts_utils.go index dd837775f140..188f04e13794 100644 --- a/exporter/azuremonitorexporter/contracts_utils.go +++ b/exporter/azuremonitorexporter/contracts_utils.go @@ -40,6 +40,13 @@ func applyCloudTagsToEnvelope(envelope *contracts.Envelope, resourceAttributes p if serviceInstance, exists := resourceAttributes.Get(conventions.AttributeServiceInstanceID); exists { envelope.Tags[contracts.CloudRoleInstance] = serviceInstance.Str() } + + envelope.Tags[contracts.InternalSdkVersion] = getCollectorVersion() +} + +// Applies internal sdk version tag on the envelope +func applyInternalSdkVersionTagToEnvelope(envelope *contracts.Envelope) { + envelope.Tags[contracts.InternalSdkVersion] = getCollectorVersion() } // Applies instrumentation values to data properties diff --git a/exporter/azuremonitorexporter/log_to_envelope.go b/exporter/azuremonitorexporter/log_to_envelope.go index 693fb8037cc7..0c520e217c01 100644 --- a/exporter/azuremonitorexporter/log_to_envelope.go +++ b/exporter/azuremonitorexporter/log_to_envelope.go @@ -45,6 +45,7 @@ func (packer *logPacker) LogRecordToEnvelope(logRecord plog.LogRecord, resource applyResourcesToDataProperties(messageData.Properties, resourceAttributes) applyInstrumentationScopeValueToDataProperties(messageData.Properties, instrumentationScope) applyCloudTagsToEnvelope(envelope, resourceAttributes) + applyInternalSdkVersionTagToEnvelope(envelope) setAttributesAsProperties(logRecord.Attributes(), messageData.Properties) diff --git a/exporter/azuremonitorexporter/logexporter_test.go b/exporter/azuremonitorexporter/logexporter_test.go index fbf111631e1d..e13cc9c7260c 100644 --- a/exporter/azuremonitorexporter/logexporter_test.go +++ b/exporter/azuremonitorexporter/logexporter_test.go @@ -94,6 +94,7 @@ func TestLogRecordToEnvelope(t *testing.T) { assert.Equal(t, contracts.Information, messageData.SeverityLevel) assert.Equal(t, defaultTraceIDAsHex, envelope.Tags[contracts.OperationId]) assert.Equal(t, defaultSpanIDAsHex, envelope.Tags[contracts.OperationParentId]) + assert.Contains(t, envelope.Tags[contracts.InternalSdkVersion], "otelc-") }) } } diff --git a/exporter/azuremonitorexporter/metric_to_envelopes.go b/exporter/azuremonitorexporter/metric_to_envelopes.go index fd454113d936..1ac92edd91d2 100644 --- a/exporter/azuremonitorexporter/metric_to_envelopes.go +++ b/exporter/azuremonitorexporter/metric_to_envelopes.go @@ -56,6 +56,7 @@ func (packer *metricPacker) MetricToEnvelopes(metric pmetric.Metric, resource pc applyResourcesToDataProperties(metricData.Properties, resourceAttributes) applyInstrumentationScopeValueToDataProperties(metricData.Properties, instrumentationScope) applyCloudTagsToEnvelope(envelope, resourceAttributes) + applyInternalSdkVersionTagToEnvelope(envelope) setAttributesAsProperties(timedDataPoint.attributes, metricData.Properties) diff --git a/exporter/azuremonitorexporter/metricexporter_test.go b/exporter/azuremonitorexporter/metricexporter_test.go index 909ecbfcca8a..1fc84bd49f33 100644 --- a/exporter/azuremonitorexporter/metricexporter_test.go +++ b/exporter/azuremonitorexporter/metricexporter_test.go @@ -112,6 +112,7 @@ func getDataPoint(t testing.TB, metric pmetric.Metric) *contracts.DataPoint { require.NotNil(t, envelope) assert.NotNil(t, envelope.Tags) + assert.Contains(t, envelope.Tags[contracts.InternalSdkVersion], "otelc-") assert.NotNil(t, envelope.Time) require.NotNil(t, envelope.Data) diff --git a/exporter/azuremonitorexporter/trace_to_envelope.go b/exporter/azuremonitorexporter/trace_to_envelope.go index c1f4abdd1885..0ee4df804355 100644 --- a/exporter/azuremonitorexporter/trace_to_envelope.go +++ b/exporter/azuremonitorexporter/trace_to_envelope.go @@ -114,6 +114,7 @@ func spanToEnvelopes( applyResourcesToDataProperties(dataProperties, resourceAttributes) applyInstrumentationScopeValueToDataProperties(dataProperties, instrumentationScope) applyCloudTagsToEnvelope(envelope, resourceAttributes) + applyInternalSdkVersionTagToEnvelope(envelope) // Sanitize the base data, the envelope and envelope tags sanitize(dataSanitizeFunc, logger) @@ -158,6 +159,7 @@ func spanToEnvelopes( applyResourcesToDataProperties(dataProperties, resourceAttributes) applyInstrumentationScopeValueToDataProperties(dataProperties, instrumentationScope) applyCloudTagsToEnvelope(spanEventEnvelope, resourceAttributes) + applyInternalSdkVersionTagToEnvelope(envelope) // Sanitize the base data, the envelope and envelope tags sanitize(dataSanitizeFunc, logger) diff --git a/exporter/azuremonitorexporter/trace_to_envelope_test.go b/exporter/azuremonitorexporter/trace_to_envelope_test.go index 441449963605..6540b44d0767 100644 --- a/exporter/azuremonitorexporter/trace_to_envelope_test.go +++ b/exporter/azuremonitorexporter/trace_to_envelope_test.go @@ -574,6 +574,7 @@ func commonEnvelopeValidations( assert.Equal(t, defaultParentSpanIDAsHex, envelope.Tags[contracts.OperationParentId]) assert.Equal(t, defaultServiceNamespace+"."+defaultServiceName, envelope.Tags[contracts.CloudRole]) assert.Equal(t, defaultServiceInstance, envelope.Tags[contracts.CloudRoleInstance]) + assert.Contains(t, envelope.Tags[contracts.InternalSdkVersion], "otelc-") assert.NotNil(t, envelope.Data) if expectedEnvelopeName == defaultRequestDataEnvelopeName { diff --git a/exporter/azuremonitorexporter/version_info.go b/exporter/azuremonitorexporter/version_info.go new file mode 100644 index 000000000000..d431ff76927c --- /dev/null +++ b/exporter/azuremonitorexporter/version_info.go @@ -0,0 +1,42 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package azuremonitorexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter" + +import ( + "runtime" + "runtime/debug" + "strings" + "sync" +) + +var ( + once sync.Once + cachedVersion string +) + +func getCollectorVersion() string { + once.Do(func() { + osInformation := runtime.GOOS[:3] + "-" + runtime.GOARCH + unknownVersion := "otelc-unknown-" + osInformation + + info, ok := debug.ReadBuildInfo() + if !ok { + cachedVersion = unknownVersion + return + } + + for _, mod := range info.Deps { + if mod.Path == "go.opentelemetry.io/collector" { + // Extract the semantic version without metadata. + semVer := strings.SplitN(mod.Version, "-", 2)[0] + cachedVersion = "otelc-" + semVer + "-" + osInformation + return + } + } + + cachedVersion = unknownVersion + }) + + return cachedVersion +}