Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support OTEL_METRIC_EXPORT_INTERVAL and OTEL_METRIC_EXPORT_TIMEOUT #3424

Merged
merged 7 commits into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
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
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
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
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)
pellared marked this conversation as resolved.
Show resolved Hide resolved
{
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);
}
}
}