Skip to content

Commit 0be57d0

Browse files
[AzureMonitorExporter] Trace based logs sampler (#53441)
* Trace based logs sampler * Public api summary, test fix, api update and changelog * missed changelog
1 parent 7fe03c5 commit 0be57d0

16 files changed

+442
-31
lines changed

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
### Features Added
66

7+
* Added `EnableTraceBasedLogSampler` property to `AzureMonitorOptions` to enable
8+
filtering logs based on trace sampling decisions, reducing log volume while
9+
maintaining trace-log correlation.
10+
([#53441](https://github.com/Azure/azure-sdk-for-net/pull/53441))
11+
712
### Breaking Changes
813

914
### Bugs Fixed

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/api/Azure.Monitor.OpenTelemetry.AspNetCore.net8.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public AzureMonitorOptions() { }
77
public Azure.Core.TokenCredential Credential { get { throw null; } set { } }
88
public bool DisableOfflineStorage { get { throw null; } set { } }
99
public bool EnableLiveMetrics { get { throw null; } set { } }
10+
public bool EnableTraceBasedLogsSampler { get { throw null; } set { } }
1011
public float SamplingRatio { get { throw null; } set { } }
1112
public string StorageDirectory { get { throw null; } set { } }
1213
public double? TracesPerSecond { get { throw null; } set { } }

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/api/Azure.Monitor.OpenTelemetry.AspNetCore.netstandard2.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public AzureMonitorOptions() { }
77
public Azure.Core.TokenCredential Credential { get { throw null; } set { } }
88
public bool DisableOfflineStorage { get { throw null; } set { } }
99
public bool EnableLiveMetrics { get { throw null; } set { } }
10+
public bool EnableTraceBasedLogsSampler { get { throw null; } set { } }
1011
public float SamplingRatio { get { throw null; } set { } }
1112
public string StorageDirectory { get { throw null; } set { } }
1213
public double? TracesPerSecond { get { throw null; } set { } }

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/src/Azure.Monitor.OpenTelemetry.AspNetCore.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<Description>An OpenTelemetry .NET distro that exports to Azure Monitor</Description>
44
<AssemblyTitle>AzureMonitor OpenTelemetry ASP.NET Core Distro</AssemblyTitle>
@@ -24,10 +24,10 @@
2424
<!-- Depending on monthly deliverables, we may switch between PackageReference or ProjectReference. Keeping both here to make the switch easier. -->
2525

2626
<!-- FOR PUBLIC RELEASES, MUST USE PackageReference. THIS REQUIRES A STAGGERED RELEASE IF SHIPPING A NEW EXPORTER. -->
27-
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" VersionOverride="1.5.0-beta.1" />
27+
<!--<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" VersionOverride="1.5.0-beta.1" />-->
2828

2929
<!-- FOR LOCAL DEV, ProjectReference IS PREFERRED. -->
30-
<!--<ProjectReference Include="..\..\Azure.Monitor.OpenTelemetry.Exporter\src\Azure.Monitor.OpenTelemetry.Exporter.csproj" />-->
30+
<ProjectReference Include="..\..\Azure.Monitor.OpenTelemetry.Exporter\src\Azure.Monitor.OpenTelemetry.Exporter.csproj" />
3131
</ItemGroup>
3232

3333
<!-- Shared sources from Azure.Core -->

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/src/AzureMonitorOptions.cs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ public class AzureMonitorOptions : ClientOptions
4848
/// </summary>
4949
public bool EnableLiveMetrics { get; set; } = true;
5050

51+
/// <summary>
52+
/// Enables or disables filtering logs based on trace sampling decisions.
53+
/// </summary>
54+
/// <remarks>
55+
/// When enabled, only logs associated with sampled traces are exported.
56+
/// Logs without trace context are always exported.
57+
/// This reduces log volume while maintaining trace-log correlation.
58+
/// </remarks>
59+
public bool EnableTraceBasedLogsSampler { get; set; } = true;
60+
5161
/// <summary>
5262
/// Gets or sets the ratio of telemetry items to be sampled. The value must be between 0.0F and 1.0F, inclusive.
5363
/// For example, specifying 0.4 means that 40% of traces are sampled and 60% are dropped.
@@ -86,27 +96,13 @@ internal void SetValueToExporterOptions(AzureMonitorExporterOptions exporterOpti
8696
exporterOptions.TracesPerSecond = TracesPerSecond;
8797
exporterOptions.StorageDirectory = StorageDirectory;
8898
exporterOptions.EnableLiveMetrics = EnableLiveMetrics;
99+
exporterOptions.EnableTraceBasedLogsSampler = EnableTraceBasedLogsSampler;
89100
if (Transport != null)
90101
{
91102
exporterOptions.Transport = Transport;
92103
}
93104
exporterOptions.Diagnostics.IsDistributedTracingEnabled = Diagnostics.IsDistributedTracingEnabled;
94105
exporterOptions.Diagnostics.IsLoggingEnabled = Diagnostics.IsLoggingEnabled;
95106
}
96-
97-
//internal void SetValueToLiveMetricsOptions(AzureMonitorLiveMetricsOptions liveMetricsOptions)
98-
//{
99-
// liveMetricsOptions.ConnectionString = ConnectionString;
100-
// liveMetricsOptions.Credential = Credential;
101-
// liveMetricsOptions.EnableLiveMetrics = EnableLiveMetrics;
102-
103-
// if (Transport != null)
104-
// {
105-
// liveMetricsOptions.Transport = Transport;
106-
// }
107-
108-
// liveMetricsOptions.Diagnostics.IsDistributedTracingEnabled = Diagnostics.IsDistributedTracingEnabled;
109-
// liveMetricsOptions.Diagnostics.IsLoggingEnabled = Diagnostics.IsLoggingEnabled;
110-
//}
111107
}
112108
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Options;
7+
using Azure.Monitor.OpenTelemetry.Exporter;
8+
using Xunit;
9+
10+
namespace Azure.Monitor.OpenTelemetry.AspNetCore.Tests
11+
{
12+
public class AzureMonitorOptionsTests
13+
{
14+
private const string TestConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000";
15+
16+
[Fact]
17+
public void AzureMonitorOptions_EnableTraceBasedLogsSampler_DefaultValue_IsTrue()
18+
{
19+
// Arrange & Act
20+
var options = new AzureMonitorOptions();
21+
22+
// Assert
23+
Assert.True(options.EnableTraceBasedLogsSampler);
24+
}
25+
26+
[Fact]
27+
public void AzureMonitorOptions_EnableTraceBasedLogsSampler_CanBeDisabled()
28+
{
29+
// Arrange & Act
30+
var options = new AzureMonitorOptions
31+
{
32+
EnableTraceBasedLogsSampler = false
33+
};
34+
35+
// Assert
36+
Assert.False(options.EnableTraceBasedLogsSampler);
37+
}
38+
39+
[Fact]
40+
public void AzureMonitorOptions_SetValueToExporterOptions_CopiesEnableTraceBasedLogsSampler()
41+
{
42+
// Arrange
43+
var azureMonitorOptions = new AzureMonitorOptions
44+
{
45+
ConnectionString = TestConnectionString,
46+
EnableTraceBasedLogsSampler = false
47+
};
48+
49+
var exporterOptions = new AzureMonitorExporterOptions();
50+
51+
// Act
52+
azureMonitorOptions.SetValueToExporterOptions(exporterOptions);
53+
54+
// Assert
55+
Assert.False(exporterOptions.EnableTraceBasedLogsSampler);
56+
Assert.Equal(TestConnectionString, exporterOptions.ConnectionString);
57+
}
58+
59+
[Fact]
60+
public void UseAzureMonitor_DefaultEnableTraceBasedLogsSampler()
61+
{
62+
// Arrange
63+
var serviceCollection = new ServiceCollection();
64+
65+
// Act
66+
serviceCollection.AddOpenTelemetry()
67+
.UseAzureMonitor(options =>
68+
{
69+
options.ConnectionString = TestConnectionString;
70+
options.DisableOfflineStorage = true;
71+
});
72+
73+
var serviceProvider = serviceCollection.BuildServiceProvider();
74+
75+
// Assert
76+
var azureMonitorOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorOptions>>()
77+
.Get(Options.DefaultName);
78+
79+
Assert.True(azureMonitorOptions.EnableTraceBasedLogsSampler);
80+
81+
var exporterOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorExporterOptions>>()
82+
.Get(Options.DefaultName);
83+
84+
Assert.True(exporterOptions.EnableTraceBasedLogsSampler);
85+
}
86+
87+
[Fact]
88+
public void UseAzureMonitor_CanDisableTraceBasedLogsSampler()
89+
{
90+
// Arrange
91+
var serviceCollection = new ServiceCollection();
92+
93+
// Act
94+
serviceCollection.AddOpenTelemetry()
95+
.UseAzureMonitor(options =>
96+
{
97+
options.ConnectionString = TestConnectionString;
98+
options.EnableTraceBasedLogsSampler = false;
99+
options.DisableOfflineStorage = true;
100+
});
101+
102+
var serviceProvider = serviceCollection.BuildServiceProvider();
103+
104+
// Assert
105+
var azureMonitorOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorOptions>>()
106+
.Get(Options.DefaultName);
107+
108+
Assert.False(azureMonitorOptions.EnableTraceBasedLogsSampler);
109+
110+
var exporterOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorExporterOptions>>()
111+
.Get(Options.DefaultName);
112+
113+
Assert.False(exporterOptions.EnableTraceBasedLogsSampler);
114+
}
115+
116+
[Fact]
117+
public void UseAzureMonitor_EnableTraceBasedLogsSampler_PropagatesCorrectly()
118+
{
119+
// Arrange
120+
var serviceCollection = new ServiceCollection();
121+
122+
// Act - Test with true
123+
serviceCollection.AddOpenTelemetry()
124+
.UseAzureMonitor(options =>
125+
{
126+
options.ConnectionString = TestConnectionString;
127+
options.EnableTraceBasedLogsSampler = true;
128+
options.DisableOfflineStorage = true;
129+
});
130+
131+
var serviceProvider = serviceCollection.BuildServiceProvider();
132+
133+
// Assert
134+
var azureMonitorOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorOptions>>()
135+
.Get(Options.DefaultName);
136+
137+
var exporterOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorExporterOptions>>()
138+
.Get(Options.DefaultName);
139+
140+
Assert.Equal(azureMonitorOptions.EnableTraceBasedLogsSampler, exporterOptions.EnableTraceBasedLogsSampler);
141+
Assert.True(exporterOptions.EnableTraceBasedLogsSampler);
142+
}
143+
144+
[Fact]
145+
public void UseAzureMonitor_WithoutConfiguration_UsesDefaultValue()
146+
{
147+
// Arrange
148+
var serviceCollection = new ServiceCollection();
149+
150+
// Act
151+
serviceCollection.AddOpenTelemetry()
152+
.UseAzureMonitor(options =>
153+
{
154+
options.ConnectionString = TestConnectionString;
155+
options.DisableOfflineStorage = true;
156+
157+
// Not setting EnableTraceBasedLogsSampler, should use default
158+
});
159+
160+
var serviceProvider = serviceCollection.BuildServiceProvider();
161+
162+
// Assert
163+
var azureMonitorOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorOptions>>()
164+
.Get(Options.DefaultName);
165+
166+
var exporterOptions = serviceProvider.GetRequiredService<IOptionsMonitor<AzureMonitorExporterOptions>>()
167+
.Get(Options.DefaultName);
168+
169+
// Both should be true (default value)
170+
Assert.True(azureMonitorOptions.EnableTraceBasedLogsSampler);
171+
Assert.True(exporterOptions.EnableTraceBasedLogsSampler);
172+
}
173+
}
174+
}

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/tests/Azure.Monitor.OpenTelemetry.AspNetCore.Tests/DefaultAzureMonitorOptionsTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public void VerifyConfigure_Default()
2929
Assert.False(azureMonitorOptions.DisableOfflineStorage);
3030
Assert.Equal(1.0F, azureMonitorOptions.SamplingRatio);
3131
Assert.Null(azureMonitorOptions.StorageDirectory);
32+
Assert.True(azureMonitorOptions.EnableTraceBasedLogsSampler);
3233
}
3334

3435
#if NET
@@ -39,7 +40,8 @@ public void VerifyConfigure_ViaJson()
3940
""ConnectionString"" : ""testJsonValue"",
4041
""DisableOfflineStorage"" : ""true"",
4142
""SamplingRatio"" : 0.5,
42-
""StorageDirectory"" : ""testJsonValue""
43+
""StorageDirectory"" : ""testJsonValue"",
44+
""EnableTraceBasedLogsSampler"" : ""true""
4345
}}";
4446

4547
var configuration = new ConfigurationBuilder()

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/tests/Azure.Monitor.OpenTelemetry.AspNetCore.Tests/InitializationTests.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,6 @@ public static void EvaluateLoggerProvider(IServiceProvider serviceProvider, bool
401401

402402
var secondProcessor = valueField.GetValue(secondNode);
403403
Assert.NotNull(secondProcessor);
404-
Assert.Contains("BatchLogRecordExportProcessor", secondProcessor.GetType().Name);
405404

406405
var exporterProperty = secondProcessor.GetType().GetProperty("Exporter", BindingFlags.NonPublic | BindingFlags.Instance);
407406
Assert.NotNull(exporterProperty);
@@ -412,9 +411,6 @@ public static void EvaluateLoggerProvider(IServiceProvider serviceProvider, bool
412411
}
413412
else
414413
{
415-
// When LiveMetrics is disabled, processor should be a BatchLogRecordExportProcessor
416-
Assert.Contains("BatchLogRecordExportProcessor", processor.GetType().Name);
417-
418414
var exporterProperty = processor.GetType().GetProperty("Exporter", BindingFlags.NonPublic | BindingFlags.Instance);
419415
Assert.NotNull(exporterProperty);
420416

sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
* Enabled resource metrics export by default.
88
([#53432](https://github.com/Azure/azure-sdk-for-net/pull/53432))
99

10+
* Added `EnableTraceBasedLogSampler` property to `AzureMonitorExporterOptions`
11+
to enable filtering logs based on trace sampling decisions, reducing log
12+
volume while maintaining trace-log correlation.
13+
([#53441](https://github.com/Azure/azure-sdk-for-net/pull/53441))
14+
1015
### Breaking Changes
1116

1217
### Bugs Fixed

sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/api/Azure.Monitor.OpenTelemetry.Exporter.net8.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public AzureMonitorExporterOptions(Azure.Monitor.OpenTelemetry.Exporter.AzureMon
1515
public Azure.Core.TokenCredential Credential { get { throw null; } set { } }
1616
public bool DisableOfflineStorage { get { throw null; } set { } }
1717
public bool EnableLiveMetrics { get { throw null; } set { } }
18+
public bool EnableTraceBasedLogsSampler { get { throw null; } set { } }
1819
public float SamplingRatio { get { throw null; } set { } }
1920
public string StorageDirectory { get { throw null; } set { } }
2021
public double? TracesPerSecond { get { throw null; } set { } }

0 commit comments

Comments
 (0)