Skip to content

Commit

Permalink
Support OTEL_METRIC_EXPORT_INTERVAL and OTEL_METRIC_EXPORT_TIMEOUT (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
pellared committed Jul 15, 2022
1 parent bc4f788 commit a19d106
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 22 deletions.
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Exporter.Console/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

* The `MetricReaderOptions` defaults can be overridden using
`OTEL_METRIC_EXPORT_INTERVAL` and `OTEL_METRIC_EXPORT_TIMEOUT`
environmental variables as defined in the
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.12.0/specification/sdk-environment-variables.md#periodic-exporting-metricreader).
([#3424](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3424))

## 1.3.0

Released 2022-Jun-03
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\EnvironmentVariableHelper.cs" Link="Includes\EnvironmentVariableHelper.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\OpenTelemetrySdkEventSource.cs" Link="Includes\OpenTelemetrySdkEventSource.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PeriodicExportingMetricReaderHelper.cs" Link="Includes\PeriodicExportingMetricReaderHelper.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\ServiceProviderExtensions.cs" Link="Includes\ServiceProviderExtensions.cs" />
Expand Down
24 changes: 24 additions & 0 deletions src/OpenTelemetry.Exporter.Console/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,30 @@ used:
* [Metrics](../../docs/metrics/getting-started/Program.cs)
* [Traces](../../docs/trace/getting-started/Program.cs)

## Configuration

See the
[`TestConsoleExporter.cs`](../../examples/Console/TestConsoleExporter.cs) for
an example of how to use the exporter for exporting traces to a collection.

You can configure the `ConsoleExporter` through `Options` types properties
and environment variables.
The `Options` type setters take precedence over the environment variables.

## Environment Variables

The following environment variables can be used to override the default
values of the `PeriodicExportingMetricReaderOptions`
(following the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.12.0/specification/sdk-environment-variables.md#periodic-exporting-metricreader).

| Environment variable | `PeriodicExportingMetricReaderOptions` property |
| ------------------------------| ------------------------------------------------|
| `OTEL_METRIC_EXPORT_INTERVAL` | `ExportIntervalMilliseconds` |
| `OTEL_METRIC_EXPORT_TIMEOUT` | `ExportTimeoutMilliseconds` |

`FormatException` is thrown in case of an invalid value for any of the
supported environment variables.

## References

* [OpenTelemetry Project](https://opentelemetry.io/)
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
* `InMemoryExporter` will now buffer scopes when exporting `LogRecord`
([#3360](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3360))

* The `MetricReaderOptions` defaults can be overridden using
`OTEL_METRIC_EXPORT_INTERVAL` and `OTEL_METRIC_EXPORT_TIMEOUT`
environmental variables as defined in the
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.12.0/specification/sdk-environment-variables.md#periodic-exporting-metricreader).
([#3424](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3424))

## 1.3.0

Released 2022-Jun-03
Expand Down
18 changes: 18 additions & 0 deletions src/OpenTelemetry.Exporter.InMemory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ See the
[`TestInMemoryExporter.cs`](../../examples/Console/TestInMemoryExporter.cs) for
an example of how to use the exporter for exporting traces to a collection.

You can configure the `InMemoryExporter` through `Options` types properties
and environment variables.
The `Options` type setters take precedence over the environment variables.

## Environment Variables

The following environment variables can be used to override the default
values of the `PeriodicExportingMetricReaderOptions`
(following the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.12.0/specification/sdk-environment-variables.md#periodic-exporting-metricreader).

| Environment variable | `PeriodicExportingMetricReaderOptions` property |
| ------------------------------| ------------------------------------------------|
| `OTEL_METRIC_EXPORT_INTERVAL` | `ExportIntervalMilliseconds` |
| `OTEL_METRIC_EXPORT_TIMEOUT` | `ExportTimeoutMilliseconds` |

`FormatException` is thrown in case of an invalid value for any of the
supported environment variables.

## References

* [OpenTelemetry Project](https://opentelemetry.io/)
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 `MetricReaderOptions` defaults can be overridden using
`OTEL_METRIC_EXPORT_INTERVAL` and `OTEL_METRIC_EXPORT_TIMEOUT`
environmental variables as defined in the
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.12.0/specification/sdk-environment-variables.md#periodic-exporting-metricreader).
([#3424](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3424))

## 1.3.0

Released 2022-Jun-03
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ namespace OpenTelemetry.Metrics
/// </summary>
public static class OtlpMetricExporterExtensions
{
private const int DefaultExportIntervalMilliseconds = 60000;
private const int DefaultExportTimeoutMilliseconds = 30000;

/// <summary>
/// Adds <see cref="OtlpMetricExporter"/> to the <see cref="MeterProviderBuilder"/> using default options.
/// </summary>
Expand Down Expand Up @@ -111,9 +108,7 @@ internal static MeterProviderBuilder AddOtlpExporter(

var metricReader = PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader(
metricExporter,
metricReaderOptions,
DefaultExportIntervalMilliseconds,
DefaultExportTimeoutMilliseconds);
metricReaderOptions);

return builder.AddReader(metricReader);
}
Expand Down
15 changes: 12 additions & 3 deletions src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol

## Configuration

You can configure the `OtlpExporter` through `OtlpExporterOptions`
properties and environment variables. The `OtlpExporterOptions`
setters take precedence over the environment variables.
You can configure the `OtlpExporter` through `Options` types properties
and environment variables.
The `Options` type setters take precedence over the environment variables.

## Options Properties

Expand Down Expand Up @@ -63,6 +63,15 @@ values of the `OtlpExporterOptions`
| `OTEL_EXPORTER_OTLP_TIMEOUT` | `TimeoutMilliseconds` |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `Protocol` (`grpc` or `http/protobuf`)|

The following environment variables can be used to override the default
values of the `PeriodicExportingMetricReaderOptions`
(following the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.12.0/specification/sdk-environment-variables.md#periodic-exporting-metricreader).

| Environment variable | `PeriodicExportingMetricReaderOptions` property |
| ------------------------------| ------------------------------------------------|
| `OTEL_METRIC_EXPORT_INTERVAL` | `ExportIntervalMilliseconds` |
| `OTEL_METRIC_EXPORT_TIMEOUT` | `ExportTimeoutMilliseconds` |

`FormatException` is thrown in case of an invalid value for any of the
supported environment variables.

Expand Down
40 changes: 32 additions & 8 deletions src/OpenTelemetry/Internal/PeriodicExportingMetricReaderHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,32 @@
// limitations under the License.
// </copyright>

using OpenTelemetry.Internal;

namespace OpenTelemetry.Metrics;

internal static class PeriodicExportingMetricReaderHelper
{
internal const string OTelMetricExportIntervalEnvVarKey = "OTEL_METRIC_EXPORT_INTERVAL";
internal const int DefaultExportIntervalMilliseconds = 60000;
internal const string OTelMetricExportTimeoutEnvVarKey = "OTEL_METRIC_EXPORT_TIMEOUT";
internal const int DefaultExportTimeoutMilliseconds = 30000;

internal static PeriodicExportingMetricReader CreatePeriodicExportingMetricReader(
BaseExporter<Metric> exporter,
MetricReaderOptions options,
int defaultExportIntervalMilliseconds,
int defaultExportTimeoutMilliseconds)
int defaultExportIntervalMilliseconds = DefaultExportIntervalMilliseconds,
int defaultExportTimeoutMilliseconds = DefaultExportTimeoutMilliseconds)
{
var exportInterval =
options.PeriodicExportingMetricReaderOptions?.ExportIntervalMilliseconds
?? defaultExportIntervalMilliseconds;
var exportInterval = GetValue(
options.PeriodicExportingMetricReaderOptions?.ExportIntervalMilliseconds,
OTelMetricExportIntervalEnvVarKey,
defaultExportIntervalMilliseconds);

var exportTimeout =
options.PeriodicExportingMetricReaderOptions?.ExportTimeoutMilliseconds
?? defaultExportTimeoutMilliseconds;
var exportTimeout = GetValue(
options.PeriodicExportingMetricReaderOptions?.ExportTimeoutMilliseconds,
OTelMetricExportTimeoutEnvVarKey,
defaultExportTimeoutMilliseconds);

var metricReader = new PeriodicExportingMetricReader(exporter, exportInterval, exportTimeout)
{
Expand All @@ -39,4 +48,19 @@ internal static PeriodicExportingMetricReader CreatePeriodicExportingMetricReade

return metricReader;
}

private static int GetValue(int? optionsValue, string envVarKey, int defaultValue)
{
if (optionsValue.HasValue)
{
return optionsValue.Value;
}

if (EnvironmentVariableHelper.LoadNumeric(envVarKey, out var envVarValue))
{
return envVarValue;
}

return defaultValue;
}
}
10 changes: 5 additions & 5 deletions src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class PeriodicExportingMetricReader : BaseExportingMetricReader
internal const int DefaultExportTimeoutMilliseconds = 30000;

internal readonly int ExportIntervalMilliseconds;
private readonly int exportTimeoutMilliseconds;
internal readonly int ExportTimeoutMilliseconds;
private readonly Thread exporterThread;
private readonly AutoResetEvent exportTrigger = new(false);
private readonly ManualResetEvent shutdownTrigger = new(false);
Expand Down Expand Up @@ -60,7 +60,7 @@ public PeriodicExportingMetricReader(
}

this.ExportIntervalMilliseconds = exportIntervalMilliseconds;
this.exportTimeoutMilliseconds = exportTimeoutMilliseconds;
this.ExportTimeoutMilliseconds = exportTimeoutMilliseconds;

this.exporterThread = new Thread(new ThreadStart(this.ExporterProc))
{
Expand Down Expand Up @@ -141,15 +141,15 @@ private void ExporterProc()
{
case 0: // export
OpenTelemetrySdkEventSource.Log.MetricReaderEvent("PeriodicExportingMetricReader calling MetricReader.Collect because Export was triggered.");
this.Collect(this.exportTimeoutMilliseconds);
this.Collect(this.ExportTimeoutMilliseconds);
break;
case 1: // shutdown
OpenTelemetrySdkEventSource.Log.MetricReaderEvent("PeriodicExportingMetricReader calling MetricReader.Collect because Shutdown was triggered.");
this.Collect(this.exportTimeoutMilliseconds); // TODO: do we want to use the shutdown timeout here?
this.Collect(this.ExportTimeoutMilliseconds); // TODO: do we want to use the shutdown timeout here?
return;
case WaitHandle.WaitTimeout: // timer
OpenTelemetrySdkEventSource.Log.MetricReaderEvent("PeriodicExportingMetricReader calling MetricReader.Collect because the export interval has elapsed.");
this.Collect(this.exportTimeoutMilliseconds);
this.Collect(this.ExportTimeoutMilliseconds);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// <copyright file="PeriodicExportingMetricReaderHelperTests.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 OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using Xunit;

namespace OpenTelemetry.Internal.Tests
{
public class PeriodicExportingMetricReaderHelperTests : IDisposable
{
public PeriodicExportingMetricReaderHelperTests()
{
ClearEnvVars();
}

public void Dispose()
{
ClearEnvVars();
}

[Fact]
public void CreatePeriodicExportingMetricReader_Defaults()
{
var reader = CreatePeriodicExportingMetricReader();

Assert.Equal(60000, reader.ExportIntervalMilliseconds);
Assert.Equal(30000, reader.ExportTimeoutMilliseconds);
Assert.Equal(MetricReaderTemporalityPreference.Cumulative, reader.TemporalityPreference);
}

[Fact]
public void CreatePeriodicExportingMetricReader_TemporalityPreference_FromOptions()
{
var value = MetricReaderTemporalityPreference.Delta;
var reader = CreatePeriodicExportingMetricReader(new()
{
TemporalityPreference = value,
});

Assert.Equal(value, reader.TemporalityPreference);
}

[Fact]
public void CreatePeriodicExportingMetricReader_ExportIntervalMilliseconds_FromOptions()
{
Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey, "88888"); // should be ignored, as value set via options has higher priority
var value = 123;
var reader = CreatePeriodicExportingMetricReader(new()
{
PeriodicExportingMetricReaderOptions = new()
{
ExportIntervalMilliseconds = value,
},
});

Assert.Equal(value, reader.ExportIntervalMilliseconds);
}

[Fact]
public void CreatePeriodicExportingMetricReader_ExportTimeoutMilliseconds_FromOptions()
{
Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey, "99999"); // should be ignored, as value set via options has higher priority
var value = 456;
var reader = CreatePeriodicExportingMetricReader(new()
{
PeriodicExportingMetricReaderOptions = new()
{
ExportTimeoutMilliseconds = value,
},
});

Assert.Equal(value, reader.ExportTimeoutMilliseconds);
}

[Fact]
public void CreatePeriodicExportingMetricReader_ExportIntervalMilliseconds_FromEnvVar()
{
var value = 789;
Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey, value.ToString());
var reader = CreatePeriodicExportingMetricReader();

Assert.Equal(value, reader.ExportIntervalMilliseconds);
}

[Fact]
public void CreatePeriodicExportingMetricReader_ExportTimeoutMilliseconds_FromEnvVar()
{
var value = 246;
Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey, value.ToString());
var reader = CreatePeriodicExportingMetricReader();

Assert.Equal(value, reader.ExportTimeoutMilliseconds);
}

[Fact]
public void EnvironmentVariableNames()
{
Assert.Equal("OTEL_METRIC_EXPORT_INTERVAL", PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey);
Assert.Equal("OTEL_METRIC_EXPORT_TIMEOUT", PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey);
}

private static void ClearEnvVars()
{
Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey, null);
Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey, null);
}

private static PeriodicExportingMetricReader CreatePeriodicExportingMetricReader(
MetricReaderOptions options = null)
{
if (options == null)
{
options = new();
}

var dummyMetricExporter = new InMemoryExporter<Metric>(new Metric[0]);
return PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader(dummyMetricExporter, options);
}
}
}

0 comments on commit a19d106

Please sign in to comment.