Skip to content

Commit

Permalink
Add support for OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADE…
Browse files Browse the repository at this point in the history
…RS and OTEL_EXPORTER_OTLP_TIMEOUT env vars (#2188)
  • Loading branch information
dszmigielski authored Jul 27, 2021
1 parent 89a0bce commit 334689e
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

* The `OtlpExporterOptions` defaults can be overridden using
`OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_TIMEOUT`
envionmental variables as defined in the
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md).
([#2188](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2188))

## 1.2.0-alpha1

Released 2021-Jul-23
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System;
using System.Diagnostics.Tracing;
using System.Security;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation
Expand All @@ -25,6 +26,15 @@ internal class OpenTelemetryProtocolExporterEventSource : EventSource
{
public static readonly OpenTelemetryProtocolExporterEventSource Log = new OpenTelemetryProtocolExporterEventSource();

[NonEvent]
public void MissingPermissionsToReadEnvironmentVariable(SecurityException ex)
{
if (this.IsEnabled(EventLevel.Warning, EventKeywords.All))
{
this.MissingPermissionsToReadEnvironmentVariable(ex.ToInvariantString());
}
}

[NonEvent]
public void FailedToConvertToProtoDefinitionError(Exception ex)
{
Expand Down Expand Up @@ -81,5 +91,17 @@ public void CouldNotTranslateMetric(string className, string methodName)
{
this.WriteEvent(5, className, methodName);
}

[Event(6, Message = "Failed to parse environment variable: '{0}', value: '{1}'.", Level = EventLevel.Warning)]
public void FailedToParseEnvironmentVariable(string name, string value)
{
this.WriteEvent(6, name, value);
}

[Event(7, Message = "Missing permissions to read environment variable: '{0}'", Level = EventLevel.Warning)]
public void MissingPermissionsToReadEnvironmentVariable(string exception)
{
this.WriteEvent(7, exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

using System;
using System.Diagnostics;
using System.Security;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;

namespace OpenTelemetry.Exporter
{
Expand All @@ -24,6 +26,57 @@ namespace OpenTelemetry.Exporter
/// </summary>
public class OtlpExporterOptions
{
internal const string EndpointEnvVarName = "OTEL_EXPORTER_OTLP_ENDPOINT";
internal const string HeadersEnvVarName = "OTEL_EXPORTER_OTLP_HEADERS";
internal const string TimeoutEnvVarName = "OTEL_EXPORTER_OTLP_TIMEOUT";

/// <summary>
/// Initializes a new instance of the <see cref="OtlpExporterOptions"/> class.
/// </summary>
public OtlpExporterOptions()
{
try
{
string endpointEnvVar = Environment.GetEnvironmentVariable(EndpointEnvVarName);
if (!string.IsNullOrEmpty(endpointEnvVar))
{
if (Uri.TryCreate(endpointEnvVar, UriKind.Absolute, out var endpoint))
{
this.Endpoint = endpoint;
}
else
{
OpenTelemetryProtocolExporterEventSource.Log.FailedToParseEnvironmentVariable(EndpointEnvVarName, endpointEnvVar);
}
}

string headersEnvVar = Environment.GetEnvironmentVariable(HeadersEnvVarName);
if (!string.IsNullOrEmpty(headersEnvVar))
{
this.Headers = headersEnvVar;
}

string timeoutEnvVar = Environment.GetEnvironmentVariable(TimeoutEnvVarName);
if (!string.IsNullOrEmpty(timeoutEnvVar))
{
if (int.TryParse(timeoutEnvVar, out var timeout))
{
this.TimeoutMilliseconds = timeout;
}
else
{
OpenTelemetryProtocolExporterEventSource.Log.FailedToParseEnvironmentVariable(TimeoutEnvVarName, timeoutEnvVar);
}
}
}
catch (SecurityException ex)
{
// The caller does not have the required permission to
// retrieve the value of an environment variable from the current process.
OpenTelemetryProtocolExporterEventSource.Log.MissingPermissionsToReadEnvironmentVariable(ex);
}
}

/// <summary>
/// Gets or sets the target to which the exporter is going to send traces.
/// Must be a valid Uri with scheme (http) and host, and
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// <copyright file="OtlpExporterOptionsTests.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed 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.
// </copyright>

using System;
using Xunit;

namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
{
public class OtlpExporterOptionsTests : IDisposable
{
public OtlpExporterOptionsTests()
{
ClearEnvVars();
}

public void Dispose()
{
ClearEnvVars();
}

[Fact]
public void OtlpExporterOptions_Defaults()
{
var options = new OtlpExporterOptions();

Assert.Equal(new Uri("http://localhost:4317"), options.Endpoint);
Assert.Null(options.Headers);
Assert.Equal(10000, options.TimeoutMilliseconds);
}

[Fact]
public void OtlpExporterOptions_EnvironmentVariableOverride()
{
Environment.SetEnvironmentVariable(OtlpExporterOptions.EndpointEnvVarName, "http://test:8888");
Environment.SetEnvironmentVariable(OtlpExporterOptions.HeadersEnvVarName, "A=2,B=3");
Environment.SetEnvironmentVariable(OtlpExporterOptions.TimeoutEnvVarName, "2000");

var options = new OtlpExporterOptions();

Assert.Equal(new Uri("http://test:8888"), options.Endpoint);
Assert.Equal("A=2,B=3", options.Headers);
Assert.Equal(2000, options.TimeoutMilliseconds);
}

[Fact]
public void OtlpExporterOptions_InvalidEndpointVariableOverride()
{
Environment.SetEnvironmentVariable(OtlpExporterOptions.EndpointEnvVarName, "invalid");

var options = new OtlpExporterOptions();

Assert.Equal(new Uri("http://localhost:4317"), options.Endpoint); // use default
}

[Fact]
public void OtlpExporterOptions_InvalidTimeoutVariableOverride()
{
Environment.SetEnvironmentVariable(OtlpExporterOptions.TimeoutEnvVarName, "invalid");

var options = new OtlpExporterOptions();

Assert.Equal(10000, options.TimeoutMilliseconds); // use default
}

[Fact]
public void OtlpExporterOptions_SetterOverridesEnvironmentVariable()
{
Environment.SetEnvironmentVariable(OtlpExporterOptions.EndpointEnvVarName, "http://test:8888");
Environment.SetEnvironmentVariable(OtlpExporterOptions.HeadersEnvVarName, "A=2,B=3");
Environment.SetEnvironmentVariable(OtlpExporterOptions.TimeoutEnvVarName, "2000");

var options = new OtlpExporterOptions
{
Endpoint = new Uri("http://localhost:200"),
Headers = "C=3",
TimeoutMilliseconds = 40000,
};

Assert.Equal(new Uri("http://localhost:200"), options.Endpoint);
Assert.Equal("C=3", options.Headers);
Assert.Equal(40000, options.TimeoutMilliseconds);
}

[Fact]
public void OtlpExporterOptions_EnvironmentVariableNames()
{
Assert.Equal("OTEL_EXPORTER_OTLP_ENDPOINT", OtlpExporterOptions.EndpointEnvVarName);
Assert.Equal("OTEL_EXPORTER_OTLP_HEADERS", OtlpExporterOptions.HeadersEnvVarName);
Assert.Equal("OTEL_EXPORTER_OTLP_TIMEOUT", OtlpExporterOptions.TimeoutEnvVarName);
}

private static void ClearEnvVars()
{
Environment.SetEnvironmentVariable(OtlpExporterOptions.EndpointEnvVarName, null);
Environment.SetEnvironmentVariable(OtlpExporterOptions.HeadersEnvVarName, null);
Environment.SetEnvironmentVariable(OtlpExporterOptions.TimeoutEnvVarName, null);
}
}
}

0 comments on commit 334689e

Please sign in to comment.