forked from open-telemetry/opentelemetry-collector-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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: open-telemetry#28853 (Add ConnectionString Support for Azure Monitor Exporter)
- Loading branch information
1 parent
f530bc4
commit 391d829
Showing
7 changed files
with
251 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
134 changes: 134 additions & 0 deletions
134
exporter/azuremonitorexporter/connection_string_parser_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters