Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,81 @@ namespace Serilog.Sinks.OpenTelemetry.Configuration;

static class OpenTelemetryEnvironment
{
const string ProtocolVarName = "OTEL_EXPORTER_OTLP_PROTOCOL";
const string EndpointVarName = "OTEL_EXPORTER_OTLP_ENDPOINT";
const string HeaderVarName = "OTEL_EXPORTER_OTLP_HEADERS";
const string ResourceAttributesVarName = "OTEL_RESOURCE_ATTRIBUTES";
const string ServiceNameVarName = "OTEL_SERVICE_NAME";

public static void Configure(BatchedOpenTelemetrySinkOptions options, Func<string, string?> getConfigurationVariable)
{
options.Protocol = getConfigurationVariable(ProtocolVarName) switch
{
"http/protobuf" => OtlpProtocol.HttpProtobuf,
"grpc" => OtlpProtocol.Grpc,
_ => options.Protocol
};
if (ParseProtocol(getConfigurationVariable(OpenTelemetryEnvironmentVariables.DefaultProtocol)) is { } protocol)
options.Protocol = protocol;

if (getConfigurationVariable(EndpointVarName) is { Length: > 1 } endpoint)
if (getConfigurationVariable(OpenTelemetryEnvironmentVariables.DefaultEndpoint) is { Length: > 1 } endpoint)
options.Endpoint = endpoint;

FillHeadersIfPresent(getConfigurationVariable(HeaderVarName), options.Headers);
FillLogsConfigUsingSpecificationEnvVars(options, getConfigurationVariable);

FillHeadersResourceAttributesIfPresent(getConfigurationVariable(ResourceAttributesVarName), options.ResourceAttributes);
FillTracesConfigUsingSpecificationEnvVars(options, getConfigurationVariable);

if (getConfigurationVariable(ServiceNameVarName) is { Length: > 1 } serviceName)
FillDictionary(
options.Headers,
getConfigurationVariable,
OpenTelemetryEnvironmentVariables.DefaultHeaders);

FillDictionary(
options.ResourceAttributes,
getConfigurationVariable,
OpenTelemetryEnvironmentVariables.ResourceAttributes);

if (getConfigurationVariable(OpenTelemetryEnvironmentVariables.ServiceName) is { Length: > 1 } serviceName)
{
options.ResourceAttributes[SemanticConventions.AttributeServiceName] = serviceName;
}
}

static void FillHeadersIfPresent(string? config, IDictionary<string, string> headers)
static OtlpProtocol? ParseProtocol(string? protocol)
{
return protocol switch
{
"http/protobuf" => OtlpProtocol.HttpProtobuf,
"grpc" => OtlpProtocol.Grpc,
_ => null
};
}

static void FillLogsConfigUsingSpecificationEnvVars(
BatchedOpenTelemetrySinkOptions options,
Func<string, string?> getConfigurationVariable)
{
options.LogsEndpoint = getConfigurationVariable(OpenTelemetryEnvironmentVariables.LogsEndpoint);
}

static void FillTracesConfigUsingSpecificationEnvVars(
BatchedOpenTelemetrySinkOptions options,
Func<string, string?> getConfigurationVariable)
{
options.TracesEndpoint = getConfigurationVariable(OpenTelemetryEnvironmentVariables.TracesEndpoint);
}

static void FillDictionary(
IDictionary<string, string> dictionary,
Func<string, string?> getConfigurationVariable,
string environmentVariableName)
{
var config = getConfigurationVariable(environmentVariableName);
if (config == null) return;
foreach (var (key, value) in BaggageFormat.DecodeBaggageString(config, HeaderVarName))
foreach (var (key, value) in BaggageFormat.DecodeBaggageString(config, environmentVariableName))
{
headers[key] = value;
dictionary[key] = value;
}
}

static void FillHeadersResourceAttributesIfPresent(string? config, IDictionary<string, object> resourceAttributes)
static void FillDictionary(
IDictionary<string, object> dictionary,
Func<string, string?> getConfigurationVariable,
string environmentVariableName)
{
var config = getConfigurationVariable(environmentVariableName);
if (config == null) return;
foreach (var (key, value) in BaggageFormat.DecodeBaggageString(config, ResourceAttributesVarName))
foreach (var (key, value) in BaggageFormat.DecodeBaggageString(config, environmentVariableName))
{
resourceAttributes[key] = value;
dictionary[key] = value;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Serilog.Sinks.OpenTelemetry.Configuration;

static class OpenTelemetryEnvironmentVariables
{
public const string DefaultEndpoint = "OTEL_EXPORTER_OTLP_ENDPOINT";
public const string DefaultHeaders = "OTEL_EXPORTER_OTLP_HEADERS";
public const string DefaultProtocol = "OTEL_EXPORTER_OTLP_PROTOCOL";

public const string LogsEndpoint = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT";

public const string TracesEndpoint = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";

public const string ServiceName = "OTEL_SERVICE_NAME";
public const string ResourceAttributes = "OTEL_RESOURCE_ATTRIBUTES";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ namespace Serilog.Sinks.OpenTelemetry.Tests;

public class OpenTelemetryEnvironmentTests
{
[Fact]
public void ConfigureRespectsSpecificEndpointEnvironmentVariableValues()
{
BatchedOpenTelemetrySinkOptions options = new();

var generalEndpoint = "http://general";
var logSpecificEndpoint = "http://log-specific";
var tracesSpecificEndpoint = "http://traces-specific";

OpenTelemetryEnvironment.Configure(options, GetEnvVar);

Assert.Equal(generalEndpoint, options.Endpoint);
Assert.Equal(logSpecificEndpoint, options.LogsEndpoint);
Assert.Equal(tracesSpecificEndpoint, options.TracesEndpoint);
return;

string? GetEnvVar(string name) => name switch
{
OpenTelemetryEnvironmentVariables.DefaultEndpoint => generalEndpoint,
OpenTelemetryEnvironmentVariables.LogsEndpoint => logSpecificEndpoint,
OpenTelemetryEnvironmentVariables.TracesEndpoint => tracesSpecificEndpoint,
_ => null
};
}

[Fact]
public void ConfigureFillsOptionsWithEnvironmentVariableValues()
{
Expand All @@ -30,11 +55,11 @@ public void ConfigureFillsOptionsWithEnvironmentVariableValues()

string? GetEnvVar(string name) => name switch
{
"OTEL_EXPORTER_OTLP_ENDPOINT" => endpoint,
"OTEL_EXPORTER_OTLP_HEADERS" => headers,
"OTEL_RESOURCE_ATTRIBUTES" => resourceAttributes,
"OTEL_EXPORTER_OTLP_PROTOCOL" => "grpc",
"OTEL_SERVICE_NAME" => serviceName,
OpenTelemetryEnvironmentVariables.DefaultEndpoint => endpoint,
OpenTelemetryEnvironmentVariables.DefaultHeaders => headers,
OpenTelemetryEnvironmentVariables.ResourceAttributes => resourceAttributes,
OpenTelemetryEnvironmentVariables.DefaultProtocol => "grpc",
OpenTelemetryEnvironmentVariables.ServiceName => serviceName,
_ => null
};
}
Expand All @@ -54,8 +79,8 @@ public void ExplicitServiceNameOverridesResourceAttribute()

string? GetEnvVar(string name) => name switch
{
"OTEL_RESOURCE_ATTRIBUTES" => resourceAttributes,
"OTEL_SERVICE_NAME" => serviceName,
OpenTelemetryEnvironmentVariables.ResourceAttributes => resourceAttributes,
OpenTelemetryEnvironmentVariables.ServiceName => serviceName,
_ => null
};
}
Expand All @@ -76,8 +101,8 @@ public void ConfigureAppendPathToEndpointIfProtocolIsHttpProtobufAndEndpointDoes
string? GetEnvVar(string name)
=> name switch
{
"OTEL_EXPORTER_OTLP_ENDPOINT" => endpoint,
"OTEL_EXPORTER_OTLP_PROTOCOL" => "http/protobuf",
OpenTelemetryEnvironmentVariables.DefaultEndpoint => endpoint,
OpenTelemetryEnvironmentVariables.DefaultProtocol => "http/protobuf",
_ => null
};
}
Expand All @@ -95,7 +120,7 @@ public void ConfigureThrowsIfHeaderEnvIsInvalidFormat()
string? GetEnvVar(string name)
=> name switch
{
"OTEL_EXPORTER_OTLP_HEADERS" => headers,
OpenTelemetryEnvironmentVariables.DefaultHeaders => headers,
_ => null
};
}
Expand All @@ -113,7 +138,7 @@ public void ConfigureThrowsIfResourceAttributesEnvIsInvalidFormat()
string? GetEnvVar(string name)
=> name switch
{
"OTEL_RESOURCE_ATTRIBUTES" => resourceAttributes,
OpenTelemetryEnvironmentVariables.ResourceAttributes => resourceAttributes,
_ => null
};
}
Expand Down
Loading