Skip to content

Commit

Permalink
Add log filtering processor distro (#41665)
Browse files Browse the repository at this point in the history
* draft

* fix pooling issue

* file header

* clean up

* Add test

* rmv using

* refactor

* log

* rmv unused

* fix test

* changelog

* feedback

* refactor

* fix test

* Update Packages.Data.props

---------

Co-authored-by: Timothy Mothra <[email protected]>
  • Loading branch information
vishweshbankwar and TimothyMothra authored Feb 9, 2024
1 parent e72e285 commit 5e2352c
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
property can be set to `false` to disable live metrics.
([#41872](https://github.com/Azure/azure-sdk-for-net/pull/41872))

- Added an experimental feature for logs emitted within an active tracing
context to follow the Activity's sampling decision. The feature can be enabled
by setting `OTEL_DOTNET_AZURE_MONITOR_EXPERIMENTAL_ENABLE_LOG_SAMPLING`
environment variable to `true`.
([#41665](https://github.com/Azure/azure-sdk-for-net/pull/41665))

### Breaking Changes

### Bugs Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public void ConfigureFailed(Exception ex)
}
}

[NonEvent]
public void GetEnvironmentVariableFailed(string envVarName, Exception ex)
{
if (IsEnabled(EventLevel.Error))
{
GetEnvironmentVariableFailed(envVarName, ex.FlattenException().ToInvariantString());
}
}

[Event(1, Message = "Failed to configure AzureMonitorOptions using the connection string from environment variables due to an exception: {0}", Level = EventLevel.Error)]
public void ConfigureFailed(string exceptionMessage) => WriteEvent(1, exceptionMessage);

Expand All @@ -62,5 +71,8 @@ public void ConfigureFailed(Exception ex)

[Event(4, Message = "Vendor instrumentation added for: {0}.", Level = EventLevel.Verbose)]
public void VendorInstrumentationAdded(string packageName) => WriteEvent(4, packageName);

[Event(5, Message = "Failed to Read environment variable {0}, exception: {1}", Level = EventLevel.Error)]
public void GetEnvironmentVariableFailed(string envVarName, string exceptionMessage) => WriteEvent(5, envVarName, exceptionMessage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using OpenTelemetry.Logs;
using OpenTelemetry;

namespace Azure.Monitor.OpenTelemetry.AspNetCore
{
internal class LogFilteringProcessor : BatchLogRecordExportProcessor
{
public LogFilteringProcessor(BaseExporter<LogRecord> exporter)
: base(exporter)
{
}

public override void OnEnd(LogRecord logRecord)
{
if (logRecord.SpanId == default || logRecord.TraceFlags == ActivityTraceFlags.Recorded)
{
base.OnEnd(logRecord);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public static class OpenTelemetryBuilderExtensions
{
private const string SqlClientInstrumentationPackageName = "OpenTelemetry.Instrumentation.SqlClient";

private const string EnableLogSamplingEnvVar = "OTEL_DOTNET_AZURE_MONITOR_EXPERIMENTAL_ENABLE_LOG_SAMPLING";

/// <summary>
/// Configures Azure Monitor for logging, distributed tracing, and metrics.
/// </summary>
Expand Down Expand Up @@ -137,7 +139,29 @@ public static OpenTelemetryBuilder UseAzureMonitor(this OpenTelemetryBuilder bui
builder.Services.AddOptions<OpenTelemetryLoggerOptions>()
.Configure<IOptionsMonitor<AzureMonitorOptions>>((loggingOptions, azureOptions) =>
{
loggingOptions.AddAzureMonitorLogExporter(o => azureOptions.Get(Options.DefaultName).SetValueToExporterOptions(o));
var azureMonitorOptions = azureOptions.Get(Options.DefaultName);

bool enableLogSampling = false;
try
{
var enableLogSamplingEnvVar = Environment.GetEnvironmentVariable(EnableLogSamplingEnvVar);
bool.TryParse(enableLogSamplingEnvVar, out enableLogSampling);
}
catch (Exception ex)
{
AzureMonitorAspNetCoreEventSource.Log.GetEnvironmentVariableFailed(EnableLogSamplingEnvVar, ex);
}

if (enableLogSampling)
{
var azureMonitorExporterOptions = new AzureMonitorExporterOptions();
azureMonitorOptions.SetValueToExporterOptions(azureMonitorExporterOptions);
loggingOptions.AddProcessor(new LogFilteringProcessor(new AzureMonitorLogExporter(azureMonitorExporterOptions)));
}
else
{
loggingOptions.AddAzureMonitorLogExporter(o => azureMonitorOptions.SetValueToExporterOptions(o));
}
});

// Register a configuration action so that when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
using System.Collections.Generic;
using System.Linq;
using Xunit.Abstractions;
using OpenTelemetry.Logs;
using OpenTelemetry;
using System.Reflection;

namespace Azure.Monitor.OpenTelemetry.AspNetCore.Tests
{
Expand Down Expand Up @@ -77,6 +80,45 @@ public async Task ValidateTelemetryExport()
// TODO: This test needs to assert telemetry content. (ie: sample rate)
}

[Theory]
[InlineData(null)]
[InlineData("true")]
[InlineData("True")]
[InlineData("False")]
[InlineData("false")]
public void ValidateLogFilteringProcessorIsAddedToLoggerProvider(string enableLogSampling)
{
try
{
Environment.SetEnvironmentVariable("OTEL_DOTNET_AZURE_MONITOR_EXPERIMENTAL_ENABLE_LOG_SAMPLING", enableLogSampling);

var sv = new ServiceCollection();
sv.AddOpenTelemetry().UseAzureMonitor(o => o.ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000");

var sp = sv.BuildServiceProvider();
var loggerProvider = sp.GetRequiredService<ILoggerProvider>();
var sdkProvider = typeof(OpenTelemetryLoggerProvider).GetField("Provider", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(loggerProvider);
var processor = sdkProvider?.GetType().GetProperty("Processor", BindingFlags.Instance | BindingFlags.Public)?.GetMethod?.Invoke(sdkProvider, null);

Assert.NotNull(processor);

if (enableLogSampling != null && enableLogSampling.Equals("true" , StringComparison.OrdinalIgnoreCase))
{
Assert.True(processor is LogFilteringProcessor);
Assert.True(processor is BatchLogRecordExportProcessor);
}
else
{
Assert.True(processor is not LogFilteringProcessor);
Assert.True(processor is BatchLogRecordExportProcessor);
}
}
finally
{
Environment.SetEnvironmentVariable("OTEL_DOTNET_AZURE_MONITOR_EXPERIMENTAL_ENABLE_LOG_SAMPLING", null);
}
}

private void WaitForRequest(MockTransport transport)
{
SpinWait.SpinUntil(
Expand Down

0 comments on commit 5e2352c

Please sign in to comment.