diff --git a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/ApplicationInsightsLoggerOptions.cs b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/ApplicationInsightsLoggerOptions.cs
index 08c370923..ec8ebfb48 100644
--- a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/ApplicationInsightsLoggerOptions.cs
+++ b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/ApplicationInsightsLoggerOptions.cs
@@ -155,6 +155,18 @@ public TimeSpan QuickPulseInitializationDelay
///
public bool EnableMetricsCustomDimensionOptimization { get; set; } = false;
+ ///
+ /// Gets or sets the flag that enables Adaptive Sampling delay.
+ /// Enabled by default.
+ ///
+ public bool EnableAdaptiveSamplingDelay { get; set; } = true;
+
+ ///
+ /// Specifies the delay time for initializing Adaptive Sampling, allowing more initialization logs to be sent to Application Insights.
+ /// The default value is 15 seconds.
+ ///
+ public TimeSpan AdaptiveSamplingInitializationDelay { get; set; } = TimeSpan.FromSeconds(15);
+
public string Format()
{
JObject sampling = null;
@@ -246,6 +258,8 @@ public string Format()
{ nameof(DiagnosticsEventListenerLogLevel), DiagnosticsEventListenerLogLevel?.ToString() },
{ nameof(EnableAutocollectedMetricsExtractor), EnableAutocollectedMetricsExtractor },
{ nameof(EnableMetricsCustomDimensionOptimization), EnableMetricsCustomDimensionOptimization },
+ { nameof(EnableAdaptiveSamplingDelay), EnableAdaptiveSamplingDelay },
+ { nameof(AdaptiveSamplingInitializationDelay), AdaptiveSamplingInitializationDelay },
};
return options.ToString(Formatting.Indented);
diff --git a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs
index 832d04503..bdff570c0 100644
--- a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs
+++ b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs
@@ -388,16 +388,14 @@ private static void SetupTelemetryConfiguration(
{
configuration.TelemetryProcessorChainBuilder.Use((next) =>
{
- var processor = new AdaptiveSamplingTelemetryProcessor(options.SamplingSettings, null, next);
- if (options.SamplingExcludedTypes != null)
+ if (options.EnableAdaptiveSamplingDelay)
{
- processor.ExcludedTypes = options.SamplingExcludedTypes;
+ return new DelayedSamplingProcessor(next, options);
}
- if (options.SamplingIncludedTypes != null)
+ else
{
- processor.IncludedTypes = options.SamplingIncludedTypes;
+ return TelemetryProcessorFactory.CreateAdaptiveSamplingProcessor(options, next);
}
- return processor;
});
}
diff --git a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Processors/DelayedSamplingProcessor.cs b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Processors/DelayedSamplingProcessor.cs
new file mode 100644
index 000000000..33187aba9
--- /dev/null
+++ b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Processors/DelayedSamplingProcessor.cs
@@ -0,0 +1,45 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+using Microsoft.ApplicationInsights.Channel;
+using Microsoft.ApplicationInsights.Extensibility;
+using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
+using System.Threading.Tasks;
+
+namespace Microsoft.Azure.WebJobs.Logging.ApplicationInsights
+{
+ internal class DelayedSamplingProcessor : ITelemetryProcessor
+ {
+ private readonly AdaptiveSamplingTelemetryProcessor _samplingProcessor;
+ private ITelemetryProcessor _next;
+ private bool _isSamplingEnabled = false;
+
+ public DelayedSamplingProcessor(ITelemetryProcessor next, ApplicationInsightsLoggerOptions options)
+ {
+ _next = next;
+ _samplingProcessor = TelemetryProcessorFactory.CreateAdaptiveSamplingProcessor(options, next);
+
+ // Start a timer to enable sampling after a delay
+ Task.Delay(options.AdaptiveSamplingInitializationDelay).ContinueWith(t => EnableSampling());
+ }
+
+ public void Process(ITelemetry item)
+ {
+ if (_isSamplingEnabled)
+ {
+ // Forward to Adaptive Sampling processor
+ _samplingProcessor.Process(item);
+ }
+ else
+ {
+ // Bypass sampling
+ _next.Process(item);
+ }
+ }
+
+ private void EnableSampling()
+ {
+ _isSamplingEnabled = true;
+ }
+ }
+}
diff --git a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Processors/TelemetryProcessorExtensions.cs b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Processors/TelemetryProcessorExtensions.cs
new file mode 100644
index 000000000..ea041904d
--- /dev/null
+++ b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Processors/TelemetryProcessorExtensions.cs
@@ -0,0 +1,27 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+using Microsoft.ApplicationInsights.Extensibility;
+using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
+
+namespace Microsoft.Azure.WebJobs.Logging.ApplicationInsights
+{
+ internal static class TelemetryProcessorFactory
+ {
+ internal static AdaptiveSamplingTelemetryProcessor CreateAdaptiveSamplingProcessor(ApplicationInsightsLoggerOptions options, ITelemetryProcessor next = null)
+ {
+ // Create the sampling processor
+ var samplingProcessor = new AdaptiveSamplingTelemetryProcessor(options.SamplingSettings, null, next);
+
+ if (options.SamplingExcludedTypes != null)
+ {
+ samplingProcessor.ExcludedTypes = options.SamplingExcludedTypes;
+ }
+ if (options.SamplingIncludedTypes != null)
+ {
+ samplingProcessor.IncludedTypes = options.SamplingIncludedTypes;
+ }
+ return samplingProcessor;
+ }
+ }
+}
diff --git a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/WebJobs.Logging.ApplicationInsights.csproj b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/WebJobs.Logging.ApplicationInsights.csproj
index 4b0f5b568..971b1377d 100644
--- a/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/WebJobs.Logging.ApplicationInsights.csproj
+++ b/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/WebJobs.Logging.ApplicationInsights.csproj
@@ -3,7 +3,7 @@
- 3.0.41$(VersionSuffix)
+ 3.0.42$(VersionSuffix)
$(Version) Commit hash: $(CommitHash)
netstandard2.0
Microsoft.Azure.WebJobs.Logging.ApplicationInsights
diff --git a/test/Microsoft.Azure.WebJobs.Host.UnitTests/Loggers/ApplicationInsightsConfigurationTests.cs b/test/Microsoft.Azure.WebJobs.Host.UnitTests/Loggers/ApplicationInsightsConfigurationTests.cs
index db9993a2f..c051980af 100644
--- a/test/Microsoft.Azure.WebJobs.Host.UnitTests/Loggers/ApplicationInsightsConfigurationTests.cs
+++ b/test/Microsoft.Azure.WebJobs.Host.UnitTests/Loggers/ApplicationInsightsConfigurationTests.cs
@@ -225,6 +225,7 @@ public void DependencyInjectionConfiguration_ConfiguresSampling()
o.SamplingSettings = samplingSettings;
o.SamplingExcludedTypes = samplingExcludedTypes;
o.SamplingIncludedTypes = samplingIncludedTypes;
+ o.EnableAdaptiveSamplingDelay = false;
});
})
.Build())
@@ -242,7 +243,43 @@ public void DependencyInjectionConfiguration_ConfiguresSampling()
}
}
-
+ [Fact]
+ public void DependencyInjectionConfiguration_ConfiguresDelayedSampling()
+ {
+ var samplingSettings = new SamplingPercentageEstimatorSettings { MaxTelemetryItemsPerSecond = 1 };
+ var samplingExcludedTypes = "PageView;Request";
+ var samplingIncludedTypes = "Trace";
+ using (var host = new HostBuilder()
+ .ConfigureLogging(b =>
+ {
+ b.AddApplicationInsightsWebJobs(o =>
+ {
+ o.InstrumentationKey = "some key";
+ o.SamplingSettings = samplingSettings;
+ o.SamplingExcludedTypes = samplingExcludedTypes;
+ o.SamplingIncludedTypes = samplingIncludedTypes;
+ });
+ })
+ .Build())
+ {
+ var config = host.Services.GetService();
+ Assert.Equal(5, config.TelemetryProcessors.Count);
+ Assert.IsType(config.TelemetryProcessors[0]);
+ Assert.IsType(config.TelemetryProcessors[1]);
+ Assert.IsType(config.TelemetryProcessors[2]);
+ Assert.IsType(config.TelemetryProcessors[3]);
+
+ // Use reflection to access the private field "_samplingProcessor"
+ var samplingProcessorField = typeof(DelayedSamplingProcessor)
+ .GetField("_samplingProcessor", BindingFlags.NonPublic | BindingFlags.Instance);
+ var samplingProcessorInstance = (AdaptiveSamplingTelemetryProcessor)samplingProcessorField.GetValue(config.TelemetryProcessors[3]);
+
+ Assert.Equal(samplingSettings.MaxTelemetryItemsPerSecond, samplingProcessorInstance.MaxTelemetryItemsPerSecond);
+ Assert.Equal(samplingExcludedTypes, samplingProcessorInstance.ExcludedTypes);
+ Assert.Equal(samplingIncludedTypes, samplingProcessorInstance.IncludedTypes);
+ }
+ }
+
[Fact]
public void DependencyInjectionConfiguration_EnableLiveMetricsFilters()
{
@@ -589,6 +626,7 @@ public void DependencyInjectionConfiguration_NoFilterConfiguresSampling()
{
o.InstrumentationKey = "some key";
o.SamplingSettings = samplingSettings;
+ o.EnableAdaptiveSamplingDelay = false;
});
}).Build())
{