From 391d829f05bee09d25b98fd65bd12f18745b101f Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Wed, 1 Nov 2023 15:08:02 -0700 Subject: [PATCH 1/7] feat(azuremonitorexporter): add support for connection strings This commit introduces the ability to configure the Azure Monitor Exporter using a connection string. The connection string simplifies the configuration by encapsulating various settings into a single string, making it easier for users to configure the exporter. Changes: - Update the Config struct to include a ConnectionString field. - Modify the factory's getTransportChannel method to parse the connection string and apply the settings to the exporter configuration. - Update the tests to cover the new connection string functionality. - Update the documentation to provide examples of how to use the connection string for configuration. By supporting connection strings, users now have a more straightforward way to configure the Azure Monitor Exporter, aligning with Azure Monitor's standard practices. Refs: #28853 (Add ConnectionString Support for Azure Monitor Exporter) --- exporter/azuremonitorexporter/config.go | 1 + exporter/azuremonitorexporter/config_test.go | 3 +- .../connection_string_parser.go | 80 +++++++++++ .../connection_string_parser_test.go | 134 ++++++++++++++++++ exporter/azuremonitorexporter/factory.go | 30 +++- exporter/azuremonitorexporter/factory_test.go | 8 +- .../azuremonitorexporter/testdata/config.yaml | 4 +- 7 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 exporter/azuremonitorexporter/connection_string_parser.go create mode 100644 exporter/azuremonitorexporter/connection_string_parser_test.go diff --git a/exporter/azuremonitorexporter/config.go b/exporter/azuremonitorexporter/config.go index 6c5042954344..058a28851de5 100644 --- a/exporter/azuremonitorexporter/config.go +++ b/exporter/azuremonitorexporter/config.go @@ -12,6 +12,7 @@ import ( // Config defines configuration for Azure Monitor type Config struct { Endpoint string `mapstructure:"endpoint"` + ConnectionString configopaque.String `mapstructure:"connection_string"` InstrumentationKey configopaque.String `mapstructure:"instrumentation_key"` MaxBatchSize int `mapstructure:"maxbatchsize"` MaxBatchInterval time.Duration `mapstructure:"maxbatchinterval"` diff --git a/exporter/azuremonitorexporter/config_test.go b/exporter/azuremonitorexporter/config_test.go index 0e271073e400..ac961c05d03c 100644 --- a/exporter/azuremonitorexporter/config_test.go +++ b/exporter/azuremonitorexporter/config_test.go @@ -35,7 +35,8 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, "2"), expected: &Config{ Endpoint: defaultEndpoint, - InstrumentationKey: "abcdefg", + ConnectionString: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/", + InstrumentationKey: "00000000-0000-0000-0000-000000000000", MaxBatchSize: 100, MaxBatchInterval: 10 * time.Second, SpanEventsEnabled: false, diff --git a/exporter/azuremonitorexporter/connection_string_parser.go b/exporter/azuremonitorexporter/connection_string_parser.go new file mode 100644 index 000000000000..23e87fdba2f7 --- /dev/null +++ b/exporter/azuremonitorexporter/connection_string_parser.go @@ -0,0 +1,80 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package azuremonitorexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter" + +import ( + "fmt" + "net/url" + "path" + "strings" +) + +type ConnectionVars struct { + InstrumentationKey string + IngestionUrl string +} + +const ( + DefaultIngestionEndpoint = "https://dc.services.visualstudio.com/" + IngestionEndpointKey = "IngestionEndpoint" + InstrumentationKey = "InstrumentationKey" + ConnectionStringMaxLength = 4096 +) + +func parseConnectionString(exporterConfig *Config) (*ConnectionVars, error) { + connectionString := string(exporterConfig.ConnectionString) + instrumentationKey := string(exporterConfig.InstrumentationKey) + connectionVars := &ConnectionVars{} + + if connectionString == "" && instrumentationKey == "" { + return nil, fmt.Errorf("ConnectionString and InstrumentationKey cannot be empty") + } + if len(connectionString) > ConnectionStringMaxLength { + return nil, fmt.Errorf("ConnectionString exceeds maximum length of %d characters", ConnectionStringMaxLength) + } + if connectionString == "" { + connectionVars.InstrumentationKey = instrumentationKey + connectionVars.IngestionUrl, _ = getIngestionURL(DefaultIngestionEndpoint) + return connectionVars, nil + } + + pairs := strings.Split(connectionString, ";") + values := make(map[string]string) + for _, pair := range pairs { + kv := strings.SplitN(strings.TrimSpace(pair), "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("invalid format for connection string: %s", pair) + } + + key, value := strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]) + if key == "" { + return nil, fmt.Errorf("key cannot be empty") + } + values[key] = value + } + + var ok bool + if connectionVars.InstrumentationKey, ok = values[InstrumentationKey]; !ok || connectionVars.InstrumentationKey == "" { + return nil, fmt.Errorf("%s is required", InstrumentationKey) + } + + var ingestionEndpoint string + if ingestionEndpoint, ok = values[IngestionEndpointKey]; !ok || ingestionEndpoint == "" { + ingestionEndpoint = DefaultIngestionEndpoint + } + + connectionVars.IngestionUrl, _ = getIngestionURL(ingestionEndpoint) + + return connectionVars, nil +} + +func getIngestionURL(ingestionEndpoint string) (string, error) { + ingestionURL, err := url.Parse(ingestionEndpoint) + if err != nil { + ingestionURL, _ = url.Parse(DefaultIngestionEndpoint) + } + + ingestionURL.Path = path.Join(ingestionURL.Path, "/v2/track") + return ingestionURL.String(), nil +} diff --git a/exporter/azuremonitorexporter/connection_string_parser_test.go b/exporter/azuremonitorexporter/connection_string_parser_test.go new file mode 100644 index 000000000000..ad23870f648a --- /dev/null +++ b/exporter/azuremonitorexporter/connection_string_parser_test.go @@ -0,0 +1,134 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package azuremonitorexporter + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/config/configopaque" +) + +func TestParseConnectionString(t *testing.T) { + tests := []struct { + name string + config *Config + want *ConnectionVars + wantError bool + }{ + { + name: "Valid connection string and instrumentation key", + config: &Config{ + ConnectionString: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/", + InstrumentationKey: "00000000-0000-0000-0000-00000000IKEY", + }, + want: &ConnectionVars{ + InstrumentationKey: "00000000-0000-0000-0000-000000000000", + IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + }, + wantError: false, + }, + { + name: "Empty connection string with valid instrumentation key", + config: &Config{ + InstrumentationKey: "00000000-0000-0000-0000-000000000000", + }, + want: &ConnectionVars{ + InstrumentationKey: "00000000-0000-0000-0000-000000000000", + IngestionUrl: DefaultIngestionEndpoint + "v2/track", + }, + wantError: false, + }, + { + name: "Valid connection string with empty instrumentation key", + config: &Config{ + ConnectionString: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/", + }, + want: &ConnectionVars{ + InstrumentationKey: "00000000-0000-0000-0000-000000000000", + IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + }, + wantError: false, + }, + { + name: "Empty connection string and instrumentation key", + config: &Config{ + ConnectionString: "", + InstrumentationKey: "", + }, + want: nil, + wantError: true, + }, + { + name: "Invalid connection string format", + config: &Config{ + ConnectionString: "InvalidConnectionString", + }, + want: nil, + wantError: true, + }, + { + name: "Missing InstrumentationKey in connection string", + config: &Config{ + ConnectionString: "IngestionEndpoint=https://ingestion.azuremonitor.com/", + }, + want: nil, + wantError: true, + }, + { + name: "Empty InstrumentationKey in connection string", + config: &Config{ + ConnectionString: "InstrumentationKey=;IngestionEndpoint=https://ingestion.azuremonitor.com/", + }, + want: nil, + wantError: true, + }, + { + name: "Extra parameters in connection string", + config: &Config{ + ConnectionString: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/;ExtraParam=extra", + }, + want: &ConnectionVars{ + InstrumentationKey: "00000000-0000-0000-0000-000000000000", + IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + }, + wantError: false, + }, + { + name: "Spaces around equals in connection string", + config: &Config{ + ConnectionString: "InstrumentationKey = 00000000-0000-0000-0000-000000000000 ; IngestionEndpoint = https://ingestion.azuremonitor.com/", + }, + want: &ConnectionVars{ + InstrumentationKey: "00000000-0000-0000-0000-000000000000", + IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + }, + wantError: false, + }, + { + name: "Connection string too long", + config: &Config{ + ConnectionString: configopaque.String(strings.Repeat("a", ConnectionStringMaxLength+1)), + }, + want: nil, + wantError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseConnectionString(tt.config) + if tt.wantError { + require.Error(t, err, "Expected an error but got none") + } else { + require.NoError(t, err, "Unexpected error: %v", err) + require.NotNil(t, got, "Expected a non-nil result") + assert.Equal(t, tt.want.InstrumentationKey, got.InstrumentationKey, "InstrumentationKey does not match") + assert.Equal(t, tt.want.IngestionUrl, got.IngestionUrl, "IngestionEndpoint does not match") + } + }) + } +} diff --git a/exporter/azuremonitorexporter/factory.go b/exporter/azuremonitorexporter/factory.go index aee00000a27c..119a8c2f858f 100644 --- a/exporter/azuremonitorexporter/factory.go +++ b/exporter/azuremonitorexporter/factory.go @@ -12,6 +12,7 @@ import ( "github.com/microsoft/ApplicationInsights-Go/appinsights" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configopaque" "go.opentelemetry.io/collector/exporter" "go.uber.org/zap" @@ -62,7 +63,11 @@ func (f *factory) createTracesExporter( return nil, errUnexpectedConfigurationType } - tc := f.getTransportChannel(exporterConfig, set.Logger) + tc, errInstrumentationKeyOrConnectionString := f.getTransportChannel(exporterConfig, set.Logger) + if errInstrumentationKeyOrConnectionString != nil { + return nil, errInstrumentationKeyOrConnectionString + } + return newTracesExporter(exporterConfig, tc, set) } @@ -77,7 +82,11 @@ func (f *factory) createLogsExporter( return nil, errUnexpectedConfigurationType } - tc := f.getTransportChannel(exporterConfig, set.Logger) + tc, errInstrumentationKeyOrConnectionString := f.getTransportChannel(exporterConfig, set.Logger) + if errInstrumentationKeyOrConnectionString != nil { + return nil, errInstrumentationKeyOrConnectionString + } + return newLogsExporter(exporterConfig, tc, set) } @@ -92,17 +101,28 @@ func (f *factory) createMetricsExporter( return nil, errUnexpectedConfigurationType } - tc := f.getTransportChannel(exporterConfig, set.Logger) + tc, errInstrumentationKeyOrConnectionString := f.getTransportChannel(exporterConfig, set.Logger) + if errInstrumentationKeyOrConnectionString != nil { + return nil, errInstrumentationKeyOrConnectionString + } + return newMetricsExporter(exporterConfig, tc, set) } // Configures the transport channel. // This method is not thread-safe -func (f *factory) getTransportChannel(exporterConfig *Config, logger *zap.Logger) transportChannel { +func (f *factory) getTransportChannel(exporterConfig *Config, logger *zap.Logger) (transportChannel, error) { // The default transport channel uses the default send mechanism from the AppInsights telemetry client. // This default channel handles batching, appropriate retries, and is backed by memory. if f.tChannel == nil { + connectionVars, err := parseConnectionString(exporterConfig) + if err != nil { + return nil, err + } + + exporterConfig.InstrumentationKey = configopaque.String(connectionVars.InstrumentationKey) + exporterConfig.Endpoint = connectionVars.IngestionUrl telemetryConfiguration := appinsights.NewTelemetryConfiguration(string(exporterConfig.InstrumentationKey)) telemetryConfiguration.EndpointUrl = exporterConfig.Endpoint telemetryConfiguration.MaxBatchSize = exporterConfig.MaxBatchSize @@ -120,5 +140,5 @@ func (f *factory) getTransportChannel(exporterConfig *Config, logger *zap.Logger } } - return f.tChannel + return f.tChannel, nil } diff --git a/exporter/azuremonitorexporter/factory_test.go b/exporter/azuremonitorexporter/factory_test.go index 9825b61bd0e1..5fa5bd0f2f86 100644 --- a/exporter/azuremonitorexporter/factory_test.go +++ b/exporter/azuremonitorexporter/factory_test.go @@ -20,7 +20,9 @@ func TestCreateTracesExporterUsingSpecificTransportChannel(t *testing.T) { f := factory{tChannel: &mockTransportChannel{}} ctx := context.Background() params := exportertest.NewNopCreateSettings() - exporter, err := f.createTracesExporter(ctx, params, createDefaultConfig()) + config := createDefaultConfig().(*Config) + config.ConnectionString = "InstrumentationKey=test-key;IngestionEndpoint=https://test-endpoint/" + exporter, err := f.createTracesExporter(ctx, params, config) assert.NotNil(t, exporter) assert.Nil(t, err) } @@ -30,7 +32,9 @@ func TestCreateTracesExporterUsingDefaultTransportChannel(t *testing.T) { f := factory{} assert.Nil(t, f.tChannel) ctx := context.Background() - exporter, err := f.createTracesExporter(ctx, exportertest.NewNopCreateSettings(), createDefaultConfig()) + config := createDefaultConfig().(*Config) + config.ConnectionString = "InstrumentationKey=test-key;IngestionEndpoint=https://test-endpoint/" + exporter, err := f.createTracesExporter(ctx, exportertest.NewNopCreateSettings(), config) assert.NotNil(t, exporter) assert.Nil(t, err) assert.NotNil(t, f.tChannel) diff --git a/exporter/azuremonitorexporter/testdata/config.yaml b/exporter/azuremonitorexporter/testdata/config.yaml index c182f3bd8ae2..1a8a01a3ddb3 100644 --- a/exporter/azuremonitorexporter/testdata/config.yaml +++ b/exporter/azuremonitorexporter/testdata/config.yaml @@ -3,7 +3,9 @@ azuremonitor/2: # endpoint is the uri used to communicate with Azure Monitor endpoint: "https://dc.services.visualstudio.com/v2/track" # instrumentation_key is the unique identifer for your Application Insights resource - instrumentation_key: abcdefg + instrumentation_key: 00000000-0000-0000-0000-000000000000 + # connection string specifies Application Insights InstrumentationKey and IngestionEndpoint + connection_string: InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/ # maxbatchsize is the maximum number of items that can be queued before calling to the configured endpoint maxbatchsize: 100 # maxbatchinterval is the maximum time to wait before calling the configured endpoint. From 4ac031482f0791bb755a009487b6f8fba3a31a4d Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Wed, 1 Nov 2023 15:45:33 -0700 Subject: [PATCH 2/7] Lint fixes --- .../azuremonitorexporter/connection_string_parser.go | 10 +++++----- .../connection_string_parser_test.go | 12 ++++++------ exporter/azuremonitorexporter/factory.go | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/exporter/azuremonitorexporter/connection_string_parser.go b/exporter/azuremonitorexporter/connection_string_parser.go index 23e87fdba2f7..15b4f57827fc 100644 --- a/exporter/azuremonitorexporter/connection_string_parser.go +++ b/exporter/azuremonitorexporter/connection_string_parser.go @@ -12,7 +12,7 @@ import ( type ConnectionVars struct { InstrumentationKey string - IngestionUrl string + IngestionURL string } const ( @@ -35,7 +35,7 @@ func parseConnectionString(exporterConfig *Config) (*ConnectionVars, error) { } if connectionString == "" { connectionVars.InstrumentationKey = instrumentationKey - connectionVars.IngestionUrl, _ = getIngestionURL(DefaultIngestionEndpoint) + connectionVars.IngestionURL = getIngestionURL(DefaultIngestionEndpoint) return connectionVars, nil } @@ -64,17 +64,17 @@ func parseConnectionString(exporterConfig *Config) (*ConnectionVars, error) { ingestionEndpoint = DefaultIngestionEndpoint } - connectionVars.IngestionUrl, _ = getIngestionURL(ingestionEndpoint) + connectionVars.IngestionURL = getIngestionURL(ingestionEndpoint) return connectionVars, nil } -func getIngestionURL(ingestionEndpoint string) (string, error) { +func getIngestionURL(ingestionEndpoint string) string { ingestionURL, err := url.Parse(ingestionEndpoint) if err != nil { ingestionURL, _ = url.Parse(DefaultIngestionEndpoint) } ingestionURL.Path = path.Join(ingestionURL.Path, "/v2/track") - return ingestionURL.String(), nil + return ingestionURL.String() } diff --git a/exporter/azuremonitorexporter/connection_string_parser_test.go b/exporter/azuremonitorexporter/connection_string_parser_test.go index ad23870f648a..ad8315f49159 100644 --- a/exporter/azuremonitorexporter/connection_string_parser_test.go +++ b/exporter/azuremonitorexporter/connection_string_parser_test.go @@ -27,7 +27,7 @@ func TestParseConnectionString(t *testing.T) { }, want: &ConnectionVars{ InstrumentationKey: "00000000-0000-0000-0000-000000000000", - IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + IngestionURL: "https://ingestion.azuremonitor.com/v2/track", }, wantError: false, }, @@ -38,7 +38,7 @@ func TestParseConnectionString(t *testing.T) { }, want: &ConnectionVars{ InstrumentationKey: "00000000-0000-0000-0000-000000000000", - IngestionUrl: DefaultIngestionEndpoint + "v2/track", + IngestionURL: DefaultIngestionEndpoint + "v2/track", }, wantError: false, }, @@ -49,7 +49,7 @@ func TestParseConnectionString(t *testing.T) { }, want: &ConnectionVars{ InstrumentationKey: "00000000-0000-0000-0000-000000000000", - IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + IngestionURL: "https://ingestion.azuremonitor.com/v2/track", }, wantError: false, }, @@ -93,7 +93,7 @@ func TestParseConnectionString(t *testing.T) { }, want: &ConnectionVars{ InstrumentationKey: "00000000-0000-0000-0000-000000000000", - IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + IngestionURL: "https://ingestion.azuremonitor.com/v2/track", }, wantError: false, }, @@ -104,7 +104,7 @@ func TestParseConnectionString(t *testing.T) { }, want: &ConnectionVars{ InstrumentationKey: "00000000-0000-0000-0000-000000000000", - IngestionUrl: "https://ingestion.azuremonitor.com/v2/track", + IngestionURL: "https://ingestion.azuremonitor.com/v2/track", }, wantError: false, }, @@ -127,7 +127,7 @@ func TestParseConnectionString(t *testing.T) { require.NoError(t, err, "Unexpected error: %v", err) require.NotNil(t, got, "Expected a non-nil result") assert.Equal(t, tt.want.InstrumentationKey, got.InstrumentationKey, "InstrumentationKey does not match") - assert.Equal(t, tt.want.IngestionUrl, got.IngestionUrl, "IngestionEndpoint does not match") + assert.Equal(t, tt.want.IngestionURL, got.IngestionURL, "IngestionEndpoint does not match") } }) } diff --git a/exporter/azuremonitorexporter/factory.go b/exporter/azuremonitorexporter/factory.go index 119a8c2f858f..7f47c145adad 100644 --- a/exporter/azuremonitorexporter/factory.go +++ b/exporter/azuremonitorexporter/factory.go @@ -122,7 +122,7 @@ func (f *factory) getTransportChannel(exporterConfig *Config, logger *zap.Logger } exporterConfig.InstrumentationKey = configopaque.String(connectionVars.InstrumentationKey) - exporterConfig.Endpoint = connectionVars.IngestionUrl + exporterConfig.Endpoint = connectionVars.IngestionURL telemetryConfiguration := appinsights.NewTelemetryConfiguration(string(exporterConfig.InstrumentationKey)) telemetryConfiguration.EndpointUrl = exporterConfig.Endpoint telemetryConfiguration.MaxBatchSize = exporterConfig.MaxBatchSize From 58519b6e38501aca399f27178064a94433374fab Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Wed, 1 Nov 2023 16:20:43 -0700 Subject: [PATCH 3/7] Fix config in exporters_test --- cmd/otelcontribcol/exporters_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/otelcontribcol/exporters_test.go b/cmd/otelcontribcol/exporters_test.go index 893cbbe5c81b..0e3f99ea7fb8 100644 --- a/cmd/otelcontribcol/exporters_test.go +++ b/cmd/otelcontribcol/exporters_test.go @@ -298,6 +298,7 @@ func TestDefaultExporters(t *testing.T) { getConfigFn: func() component.Config { cfg := expFactories["azuremonitor"].CreateDefaultConfig().(*azuremonitorexporter.Config) cfg.Endpoint = "http://" + endpoint + cfg.ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=" + cfg.Endpoint return cfg }, From 68aa5b4e2c42db7d5beaa7042575033aceeefd90 Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Wed, 1 Nov 2023 16:40:26 -0700 Subject: [PATCH 4/7] Update changelog + lint --- ...nection-string-azure-monitor-exporter.yaml | 27 +++++++++++++++++++ cmd/otelcontribcol/exporters_test.go | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 .chloggen/add-connection-string-azure-monitor-exporter.yaml diff --git a/.chloggen/add-connection-string-azure-monitor-exporter.yaml b/.chloggen/add-connection-string-azure-monitor-exporter.yaml new file mode 100755 index 000000000000..a86836b233d7 --- /dev/null +++ b/.chloggen/add-connection-string-azure-monitor-exporter.yaml @@ -0,0 +1,27 @@ +# 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: azuremonitorexporter + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Added connection string support to the Azure Monitor Exporter + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [28853] + +# (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: This enhancement simplifies the configuration process and aligns the exporter with Azure Monitor's recommended practices. + +# 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] diff --git a/cmd/otelcontribcol/exporters_test.go b/cmd/otelcontribcol/exporters_test.go index 0e3f99ea7fb8..0781b5d1dd8e 100644 --- a/cmd/otelcontribcol/exporters_test.go +++ b/cmd/otelcontribcol/exporters_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configgrpc" + "go.opentelemetry.io/collector/config/configopaque" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/exporter/otlpexporter" @@ -298,7 +299,7 @@ func TestDefaultExporters(t *testing.T) { getConfigFn: func() component.Config { cfg := expFactories["azuremonitor"].CreateDefaultConfig().(*azuremonitorexporter.Config) cfg.Endpoint = "http://" + endpoint - cfg.ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=" + cfg.Endpoint + cfg.ConnectionString = configopaque.String("InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=" + cfg.Endpoint) return cfg }, From 5415495685d86313e530c629b13a65fa7087e338 Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Wed, 1 Nov 2023 17:20:53 -0700 Subject: [PATCH 5/7] gotidy --- cmd/otelcontribcol/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/otelcontribcol/go.mod b/cmd/otelcontribcol/go.mod index e88ad93641b8..d4abb3306638 100644 --- a/cmd/otelcontribcol/go.mod +++ b/cmd/otelcontribcol/go.mod @@ -186,6 +186,7 @@ require ( github.com/stretchr/testify v1.8.4 go.opentelemetry.io/collector/component v0.88.1-0.20231026220224-6405e152a2d9 go.opentelemetry.io/collector/config/configgrpc v0.88.1-0.20231026220224-6405e152a2d9 + go.opentelemetry.io/collector/config/configopaque v0.88.1-0.20231026220224-6405e152a2d9 go.opentelemetry.io/collector/confmap v0.88.1-0.20231026220224-6405e152a2d9 go.opentelemetry.io/collector/connector v0.88.1-0.20231026220224-6405e152a2d9 go.opentelemetry.io/collector/connector/forwardconnector v0.88.1-0.20231026220224-6405e152a2d9 @@ -636,7 +637,6 @@ require ( go.opentelemetry.io/collector/config/configcompression v0.88.1-0.20231026220224-6405e152a2d9 // indirect go.opentelemetry.io/collector/config/confighttp v0.88.1-0.20231026220224-6405e152a2d9 // indirect go.opentelemetry.io/collector/config/confignet v0.88.1-0.20231026220224-6405e152a2d9 // indirect - go.opentelemetry.io/collector/config/configopaque v0.88.1-0.20231026220224-6405e152a2d9 // indirect go.opentelemetry.io/collector/config/configtelemetry v0.88.1-0.20231026220224-6405e152a2d9 // indirect go.opentelemetry.io/collector/config/configtls v0.88.1-0.20231026220224-6405e152a2d9 // indirect go.opentelemetry.io/collector/config/internal v0.88.1-0.20231026220224-6405e152a2d9 // indirect From 18f30da0ba4b88f60b5b054f35d9ce42c4346a45 Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Thu, 2 Nov 2023 14:58:35 -0700 Subject: [PATCH 6/7] doc update --- exporter/azuremonitorexporter/README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/exporter/azuremonitorexporter/README.md b/exporter/azuremonitorexporter/README.md index bdfda098e57d..c04baaa4bbea 100644 --- a/exporter/azuremonitorexporter/README.md +++ b/exporter/azuremonitorexporter/README.md @@ -17,13 +17,16 @@ This exporter sends logs, traces and metrics to [Azure Monitor](https://docs.mic ## Configuration -The following settings are required: +To configure the Azure Monitor Exporter, you must specify one of the following settings: -- `instrumentation_key` (no default): Application Insights instrumentation key, which can be found in the Application Insights resource in the Azure Portal. +- `connection_string` (recommended): The Azure Application Insights Connection String is required to send telemetry data to the monitoring service. It is the recommended method for configuring the exporter, aligning with Azure Monitor's best practices. If you need guidance on creating Azure resources, please refer to the step-by-step guides to [Create an Application Insights resource](https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource) and [find your connection string](https://docs.microsoft.com/azure/azure-monitor/app/sdk-connection-string?tabs=net#find-your-connection-string). +- `instrumentation_key`: Application Insights instrumentation key, which can be found in the Application Insights resource in the Azure Portal. While it is currently supported, its use is discouraged and it is slated for deprecation. It is highly encouraged to use the `connection_string` setting for new configurations and migrate existing configurations to use the `connection_string` as soon as possible. + +**Important**: Only one of `connection_string` or `instrumentation_key` should be specified in your configuration. If both are provided, `connection_string` will be used as the priority setting. The following settings can be optionally configured: -- `endpoint` (default = `https://dc.services.visualstudio.com/v2/track`): The endpoint URL where data will be submitted. +- `endpoint` (default = `https://dc.services.visualstudio.com/v2/track`): The endpoint URL where data will be submitted. While this option remains available, it is important to note that the use of the `connection_string` is recommended, as it encompasses the endpoint information. The direct configuration of the `endpoint` is considered to be on a deprecation path. - `maxbatchsize` (default = 1024): The maximum number of telemetry items that can be submitted in each request. If this many items are buffered, the buffer will be flushed before `maxbatchinterval` expires. - `maxbatchinterval` (default = 10s): The maximum time to wait before sending a batch of telemetry. - `spaneventsenabled` (default = false): Enables export of span events. @@ -31,6 +34,20 @@ The following settings can be optionally configured: Example: ```yaml +# Recommended Configuration: +# It is highly recommended to use the connection string which includes the InstrumentationKey and IngestionEndpoint +# This is the preferred method over using 'instrumentation_key' alone. +exporters: + azuremonitor: + connection_string: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/" +``` + +(or) + +```yaml +# Legacy Configuration: +# The use of 'instrumentation_key' alone is not recommended and will be deprecated in the future. It is advised to use the connection_string instead. +# This example is provided primarily for existing configurations that have not yet transitioned to the connection string. exporters: azuremonitor: instrumentation_key: b1cd0778-85fc-4677-a3fa-79d3c23e0efd From 9a8fac8932c601fddeea2e97dc1fd381197d329f Mon Sep 17 00:00:00 2001 From: rajkumar-rangaraj Date: Thu, 2 Nov 2023 15:12:24 -0700 Subject: [PATCH 7/7] Update Changelog subtext --- .../add-connection-string-azure-monitor-exporter.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.chloggen/add-connection-string-azure-monitor-exporter.yaml b/.chloggen/add-connection-string-azure-monitor-exporter.yaml index a86836b233d7..db6a9fa1d899 100755 --- a/.chloggen/add-connection-string-azure-monitor-exporter.yaml +++ b/.chloggen/add-connection-string-azure-monitor-exporter.yaml @@ -15,7 +15,13 @@ issues: [28853] # (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: This enhancement simplifies the configuration process and aligns the exporter with Azure Monitor's recommended practices. +subtext: | + This enhancement simplifies the configuration process and aligns the exporter with Azure Monitor's recommended practices. + The Connection String method allows the inclusion of various fields such as the InstrumentationKey and IngestionEndpoint + within a single string, facilitating an easier and more integrated setup. + While the traditional InstrumentationKey method remains supported for backward compatibility, it will be phased out. + Users are encouraged to adopt the Connection String approach to ensure future compatibility and to leverage the broader + configuration options it enables. # 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.