diff --git a/.publicApi/Microsoft.ApplicationInsights.dll/Stable/PublicAPI.Unshipped.txt b/.publicApi/Microsoft.ApplicationInsights.dll/Stable/PublicAPI.Unshipped.txt
index 291890d4a..02fa764ab 100644
--- a/.publicApi/Microsoft.ApplicationInsights.dll/Stable/PublicAPI.Unshipped.txt
+++ b/.publicApi/Microsoft.ApplicationInsights.dll/Stable/PublicAPI.Unshipped.txt
@@ -164,9 +164,21 @@ Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.ConnectionStr
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.ConnectionString.set -> void
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.DisableTelemetry.get -> bool
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.DisableTelemetry.set -> void
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.DisableOfflineStorage.get -> bool?
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.DisableOfflineStorage.set -> void
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Dispose() -> void
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.EnableLiveMetrics.get -> bool?
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.EnableLiveMetrics.set -> void
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.EnableTraceBasedLogsSampler.get -> bool?
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.EnableTraceBasedLogsSampler.set -> void
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.SamplingRatio.get -> float?
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.SamplingRatio.set -> void
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.SetAzureTokenCredential(Azure.Core.TokenCredential tokenCredential) -> void
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.StorageDirectory.get -> string
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.StorageDirectory.set -> void
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.TelemetryConfiguration() -> void
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.TracesPerSecond.get -> double?
+Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.TracesPerSecond.set -> void
Microsoft.ApplicationInsights.Metric
Microsoft.ApplicationInsights.Metric.TrackValue(double metricValue) -> void
Microsoft.ApplicationInsights.Metric.TrackValue(double metricValue, string dimension1Value) -> bool
diff --git a/BASE/Test/Microsoft.ApplicationInsights.Test/Microsoft.ApplicationInsights.Tests/TelemetryConfigurationSetExporterOptionsTests.cs b/BASE/Test/Microsoft.ApplicationInsights.Test/Microsoft.ApplicationInsights.Tests/TelemetryConfigurationSetExporterOptionsTests.cs
new file mode 100644
index 000000000..4fb1800c9
--- /dev/null
+++ b/BASE/Test/Microsoft.ApplicationInsights.Test/Microsoft.ApplicationInsights.Tests/TelemetryConfigurationSetExporterOptionsTests.cs
@@ -0,0 +1,319 @@
+namespace Microsoft.ApplicationInsights.Tests
+{
+ using System;
+ using System.Reflection;
+ using Azure.Core;
+ using Azure.Monitor.OpenTelemetry.Exporter;
+ using Microsoft.ApplicationInsights.Extensibility;
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Options;
+ using OpenTelemetry;
+ using Xunit;
+
+ ///
+ /// Tests for Azure Monitor Exporter configuration properties in TelemetryConfiguration.
+ ///
+ public class TelemetryConfigurationSetExporterOptionsTests : IDisposable
+ {
+ private TelemetryConfiguration telemetryConfiguration;
+
+ public TelemetryConfigurationSetExporterOptionsTests()
+ {
+ }
+
+ public void Dispose()
+ {
+ this.telemetryConfiguration?.Dispose();
+ }
+
+ ///
+ /// Helper method to get AzureMonitorExporterOptions from the built OpenTelemetrySdk.
+ ///
+ private AzureMonitorExporterOptions GetExporterOptions(OpenTelemetrySdk sdk)
+ {
+ // Use reflection to access the internal Services property
+ var servicesProperty = typeof(OpenTelemetrySdk).GetProperty(
+ "Services",
+ BindingFlags.NonPublic | BindingFlags.Instance);
+
+ var serviceProvider = servicesProperty?.GetValue(sdk) as IServiceProvider;
+ Assert.NotNull(serviceProvider);
+
+ var options = serviceProvider.GetService>();
+ Assert.NotNull(options);
+
+ return options.Value;
+ }
+
+ ///
+ /// Helper method to build the configuration by creating a TelemetryClient.
+ /// Creating a TelemetryClient triggers the Build() method internally.
+ ///
+ private OpenTelemetrySdk BuildConfiguration()
+ {
+ // Creating a TelemetryClient triggers configuration.Build() internally
+ var client = new TelemetryClient(this.telemetryConfiguration);
+
+ // Access the private 'sdk' field from TelemetryClient via reflection
+ var sdkField = typeof(TelemetryClient).GetField(
+ "sdk",
+ BindingFlags.NonPublic | BindingFlags.Instance);
+
+ return sdkField?.GetValue(client) as OpenTelemetrySdk;
+ }
+
+ #region SamplingRatio Tests
+
+ [Fact]
+ public void SamplingRatio_SetsSamplingRatioInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act
+ this.telemetryConfiguration.SamplingRatio = 0.5F;
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify the actual value
+ Assert.Equal(0.5F, exporterOptions.SamplingRatio);
+ }
+
+ [Fact]
+ public void SamplingRatio_AfterBuild_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Build the configuration by creating a TelemetryClient
+ _ = new TelemetryClient(this.telemetryConfiguration);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ this.telemetryConfiguration.SamplingRatio = 0.5F);
+ }
+
+ #endregion
+
+ #region TracesPerSecond Tests
+
+ [Fact]
+ public void TracesPerSecond_SetsTracesPerSecondInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act
+ this.telemetryConfiguration.TracesPerSecond = 1.5;
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify the actual value
+ Assert.Equal(1.5, exporterOptions.TracesPerSecond);
+ }
+
+ [Fact]
+ public void TracesPerSecond_AfterBuild_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Build the configuration by creating a TelemetryClient
+ _ = new TelemetryClient(this.telemetryConfiguration);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ this.telemetryConfiguration.TracesPerSecond = 1.5);
+ }
+
+ #endregion
+
+ #region StorageDirectory Tests
+
+ [Fact]
+ public void StorageDirectory_SetsStorageDirectoryInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act
+ this.telemetryConfiguration.StorageDirectory = "C:\\TelemetryStorage";
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify the actual value
+ Assert.Equal("C:\\TelemetryStorage", exporterOptions.StorageDirectory);
+ }
+
+ [Fact]
+ public void StorageDirectory_AfterBuild_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Build the configuration by creating a TelemetryClient
+ _ = new TelemetryClient(this.telemetryConfiguration);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ this.telemetryConfiguration.StorageDirectory = "C:\\TelemetryStorage");
+ }
+
+ #endregion
+
+ #region DisableOfflineStorage Tests
+
+ [Fact]
+ public void DisableOfflineStorage_SetsDisableOfflineStorageInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act
+ this.telemetryConfiguration.DisableOfflineStorage = true;
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify the actual value
+ Assert.True(exporterOptions.DisableOfflineStorage);
+ }
+
+ [Fact]
+ public void DisableOfflineStorage_AfterBuild_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Build the configuration by creating a TelemetryClient
+ _ = new TelemetryClient(this.telemetryConfiguration);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ this.telemetryConfiguration.DisableOfflineStorage = true);
+ }
+
+ #endregion
+
+ #region EnableLiveMetrics Tests
+
+ [Fact]
+ public void EnableLiveMetrics_SetsEnableLiveMetricsFalseInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act
+ this.telemetryConfiguration.EnableLiveMetrics = false;
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify the actual value
+ Assert.False(exporterOptions.EnableLiveMetrics);
+ }
+
+ [Fact]
+ public void EnableLiveMetrics_AfterBuild_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Build the configuration by creating a TelemetryClient
+ _ = new TelemetryClient(this.telemetryConfiguration);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ this.telemetryConfiguration.EnableLiveMetrics = false);
+ }
+
+ #endregion
+
+ #region EnableTraceBasedLogsSampler Tests
+
+ [Fact]
+ public void EnableTraceBasedLogsSampler_SetsEnableTraceBasedLogsSamplerFalseInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act
+ this.telemetryConfiguration.EnableTraceBasedLogsSampler = false;
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify the actual value
+ Assert.False(exporterOptions.EnableTraceBasedLogsSampler);
+ }
+
+ [Fact]
+ public void EnableTraceBasedLogsSampler_AfterBuild_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ this.telemetryConfiguration = new TelemetryConfiguration();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Build the configuration by creating a TelemetryClient
+ _ = new TelemetryClient(this.telemetryConfiguration);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ this.telemetryConfiguration.EnableTraceBasedLogsSampler = false);
+ }
+
+ #endregion
+
+ #region Combined Options Tests
+
+ [Fact]
+ public void AllOptions_BeforeBuild_SetsAllValuesInExporterOptions()
+ {
+ // Arrange
+ this.telemetryConfiguration = TelemetryConfiguration.CreateDefault();
+ this.telemetryConfiguration.ConnectionString = "InstrumentationKey=test-ikey";
+
+ // Act - set all properties
+ this.telemetryConfiguration.SamplingRatio = 0.75F;
+ this.telemetryConfiguration.TracesPerSecond = 1.5;
+ this.telemetryConfiguration.StorageDirectory = "C:\\TelemetryStorage";
+ this.telemetryConfiguration.DisableOfflineStorage = true;
+ this.telemetryConfiguration.EnableLiveMetrics = false;
+ this.telemetryConfiguration.EnableTraceBasedLogsSampler = false;
+
+ // Build the configuration by creating a TelemetryClient
+ var sdk = this.BuildConfiguration();
+ var exporterOptions = this.GetExporterOptions(sdk);
+
+ // Assert - verify all values
+ Assert.Equal(0.75F, exporterOptions.SamplingRatio);
+ Assert.Equal(1.5, exporterOptions.TracesPerSecond);
+ Assert.Equal("C:\\TelemetryStorage", exporterOptions.StorageDirectory);
+ Assert.True(exporterOptions.DisableOfflineStorage);
+ Assert.False(exporterOptions.EnableLiveMetrics);
+ Assert.False(exporterOptions.EnableTraceBasedLogsSampler);
+ }
+
+ #endregion
+ }
+}
diff --git a/BASE/src/Microsoft.ApplicationInsights/Extensibility/TelemetryConfiguration.cs b/BASE/src/Microsoft.ApplicationInsights/Extensibility/TelemetryConfiguration.cs
index ad17575ee..aabcc4791 100644
--- a/BASE/src/Microsoft.ApplicationInsights/Extensibility/TelemetryConfiguration.cs
+++ b/BASE/src/Microsoft.ApplicationInsights/Extensibility/TelemetryConfiguration.cs
@@ -40,6 +40,14 @@ public sealed class TelemetryConfiguration : IDisposable
private bool isBuilt = false;
private bool isDisposed = false;
+ // Exporter options
+ private float? samplingRatio;
+ private double? tracesPerSecond;
+ private string storageDirectory;
+ private bool? disableOfflineStorage;
+ private bool? enableLiveMetrics;
+ private bool? enableTraceBasedLogsSampler;
+
private Action builderConfiguration;
private OpenTelemetrySdk openTelemetrySdk;
private ActivitySource defaultActivitySource;
@@ -109,6 +117,91 @@ public string ConnectionString
}
}
+ ///
+ /// Gets or sets the sampling ratio for traces (0.0 to 1.0).
+ /// A value of 1.0 means all telemetry is sent, 0.5 means 50% is sent.
+ /// When null, the Azure Monitor Exporter default of 1.0 is used.
+ ///
+ public float? SamplingRatio
+ {
+ get => this.samplingRatio;
+ set
+ {
+ this.ThrowIfBuilt();
+ this.samplingRatio = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the number of traces per second for rate-limited sampling.
+ /// When null, the Azure Monitor Exporter default of 5.0 is used.
+ ///
+ public double? TracesPerSecond
+ {
+ get => this.tracesPerSecond;
+ set
+ {
+ this.ThrowIfBuilt();
+ this.tracesPerSecond = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the directory for offline telemetry storage.
+ /// When null, the Azure Monitor Exporter default (system default location) is used.
+ ///
+ public string StorageDirectory
+ {
+ get => this.storageDirectory;
+ set
+ {
+ this.ThrowIfBuilt();
+ this.storageDirectory = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether offline storage is disabled.
+ /// When null, the Azure Monitor Exporter default of false (offline storage enabled) is used.
+ ///
+ public bool? DisableOfflineStorage
+ {
+ get => this.disableOfflineStorage;
+ set
+ {
+ this.ThrowIfBuilt();
+ this.disableOfflineStorage = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether Live Metrics is enabled.
+ /// When null, the Azure Monitor Exporter default of true is used.
+ ///
+ public bool? EnableLiveMetrics
+ {
+ get => this.enableLiveMetrics;
+ set
+ {
+ this.ThrowIfBuilt();
+ this.enableLiveMetrics = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether trace-based log sampling is enabled.
+ /// When null, the Azure Monitor Exporter default of true is used.
+ ///
+ public bool? EnableTraceBasedLogsSampler
+ {
+ get => this.enableTraceBasedLogsSampler;
+ set
+ {
+ this.ThrowIfBuilt();
+ this.enableTraceBasedLogsSampler = value;
+ }
+ }
+
///
/// Gets the default ActivitySource used by TelemetryClient.
///
@@ -274,6 +367,36 @@ internal OpenTelemetrySdk Build()
builder.SetAzureMonitorExporter(options =>
{
options.ConnectionString = this.connectionString;
+
+ if (this.samplingRatio.HasValue)
+ {
+ options.SamplingRatio = this.samplingRatio.Value;
+ }
+
+ if (this.tracesPerSecond.HasValue)
+ {
+ options.TracesPerSecond = this.tracesPerSecond.Value;
+ }
+
+ if (this.storageDirectory != null)
+ {
+ options.StorageDirectory = this.storageDirectory;
+ }
+
+ if (this.disableOfflineStorage.HasValue)
+ {
+ options.DisableOfflineStorage = this.disableOfflineStorage.Value;
+ }
+
+ if (this.enableLiveMetrics.HasValue)
+ {
+ options.EnableLiveMetrics = this.enableLiveMetrics.Value;
+ }
+
+ if (this.enableTraceBasedLogsSampler.HasValue)
+ {
+ options.EnableTraceBasedLogsSampler = this.enableTraceBasedLogsSampler.Value;
+ }
});
});
diff --git a/examples/BasicConsoleApp/Program.cs b/examples/BasicConsoleApp/Program.cs
index 65174ca4f..782d0c438 100644
--- a/examples/BasicConsoleApp/Program.cs
+++ b/examples/BasicConsoleApp/Program.cs
@@ -17,10 +17,9 @@ internal class Program
static void Main(string[] args)
{
- var telemetryConfig = new TelemetryConfiguration
- {
- ConnectionString = "",
- };
+
+ var telemetryConfig = TelemetryConfiguration.CreateDefault();
+ telemetryConfig.ConnectionString = "";
telemetryConfig.ConfigureOpenTelemetryBuilder(builder => builder.WithTracing(tracing => tracing.AddSource("MyCompany.MyProduct.MyLibrary").AddConsoleExporter())
.WithLogging(logging => logging.AddConsoleExporter())