Skip to content

Commit f79ea0b

Browse files
Delay Adaptive Sampling (#3097)
Introducing delay in configuring Adaptive Sampling
1 parent 3309c1c commit f79ea0b

File tree

6 files changed

+130
-8
lines changed

6 files changed

+130
-8
lines changed

src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/ApplicationInsightsLoggerOptions.cs

+14
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ public TimeSpan QuickPulseInitializationDelay
155155
/// </summary>
156156
public bool EnableMetricsCustomDimensionOptimization { get; set; } = false;
157157

158+
/// <summary>
159+
/// Gets or sets the flag that enables Adaptive Sampling delay.
160+
/// Enabled by default.
161+
/// </summary>
162+
public bool EnableAdaptiveSamplingDelay { get; set; } = true;
163+
164+
/// <summary>
165+
/// Specifies the delay time for initializing Adaptive Sampling, allowing more initialization logs to be sent to Application Insights.
166+
/// The default value is 15 seconds.
167+
/// </summary>
168+
public TimeSpan AdaptiveSamplingInitializationDelay { get; set; } = TimeSpan.FromSeconds(15);
169+
158170
public string Format()
159171
{
160172
JObject sampling = null;
@@ -246,6 +258,8 @@ public string Format()
246258
{ nameof(DiagnosticsEventListenerLogLevel), DiagnosticsEventListenerLogLevel?.ToString() },
247259
{ nameof(EnableAutocollectedMetricsExtractor), EnableAutocollectedMetricsExtractor },
248260
{ nameof(EnableMetricsCustomDimensionOptimization), EnableMetricsCustomDimensionOptimization },
261+
{ nameof(EnableAdaptiveSamplingDelay), EnableAdaptiveSamplingDelay },
262+
{ nameof(AdaptiveSamplingInitializationDelay), AdaptiveSamplingInitializationDelay },
249263
};
250264

251265
return options.ToString(Formatting.Indented);

src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs

+4-6
Original file line numberDiff line numberDiff line change
@@ -388,16 +388,14 @@ private static void SetupTelemetryConfiguration(
388388
{
389389
configuration.TelemetryProcessorChainBuilder.Use((next) =>
390390
{
391-
var processor = new AdaptiveSamplingTelemetryProcessor(options.SamplingSettings, null, next);
392-
if (options.SamplingExcludedTypes != null)
391+
if (options.EnableAdaptiveSamplingDelay)
393392
{
394-
processor.ExcludedTypes = options.SamplingExcludedTypes;
393+
return new DelayedSamplingProcessor(next, options);
395394
}
396-
if (options.SamplingIncludedTypes != null)
395+
else
397396
{
398-
processor.IncludedTypes = options.SamplingIncludedTypes;
397+
return TelemetryProcessorFactory.CreateAdaptiveSamplingProcessor(options, next);
399398
}
400-
return processor;
401399
});
402400
}
403401

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using Microsoft.ApplicationInsights.Channel;
5+
using Microsoft.ApplicationInsights.Extensibility;
6+
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
7+
using System.Threading.Tasks;
8+
9+
namespace Microsoft.Azure.WebJobs.Logging.ApplicationInsights
10+
{
11+
internal class DelayedSamplingProcessor : ITelemetryProcessor
12+
{
13+
private readonly AdaptiveSamplingTelemetryProcessor _samplingProcessor;
14+
private ITelemetryProcessor _next;
15+
private bool _isSamplingEnabled = false;
16+
17+
public DelayedSamplingProcessor(ITelemetryProcessor next, ApplicationInsightsLoggerOptions options)
18+
{
19+
_next = next;
20+
_samplingProcessor = TelemetryProcessorFactory.CreateAdaptiveSamplingProcessor(options, next);
21+
22+
// Start a timer to enable sampling after a delay
23+
Task.Delay(options.AdaptiveSamplingInitializationDelay).ContinueWith(t => EnableSampling());
24+
}
25+
26+
public void Process(ITelemetry item)
27+
{
28+
if (_isSamplingEnabled)
29+
{
30+
// Forward to Adaptive Sampling processor
31+
_samplingProcessor.Process(item);
32+
}
33+
else
34+
{
35+
// Bypass sampling
36+
_next.Process(item);
37+
}
38+
}
39+
40+
private void EnableSampling()
41+
{
42+
_isSamplingEnabled = true;
43+
}
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using Microsoft.ApplicationInsights.Extensibility;
5+
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
6+
7+
namespace Microsoft.Azure.WebJobs.Logging.ApplicationInsights
8+
{
9+
internal static class TelemetryProcessorFactory
10+
{
11+
internal static AdaptiveSamplingTelemetryProcessor CreateAdaptiveSamplingProcessor(ApplicationInsightsLoggerOptions options, ITelemetryProcessor next = null)
12+
{
13+
// Create the sampling processor
14+
var samplingProcessor = new AdaptiveSamplingTelemetryProcessor(options.SamplingSettings, null, next);
15+
16+
if (options.SamplingExcludedTypes != null)
17+
{
18+
samplingProcessor.ExcludedTypes = options.SamplingExcludedTypes;
19+
}
20+
if (options.SamplingIncludedTypes != null)
21+
{
22+
samplingProcessor.IncludedTypes = options.SamplingIncludedTypes;
23+
}
24+
return samplingProcessor;
25+
}
26+
}
27+
}

src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/WebJobs.Logging.ApplicationInsights.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<Import Project="..\..\build\common.props" />
44

55
<PropertyGroup>
6-
<Version>3.0.41$(VersionSuffix)</Version>
6+
<Version>3.0.42$(VersionSuffix)</Version>
77
<InformationalVersion>$(Version) Commit hash: $(CommitHash)</InformationalVersion>
88
<TargetFramework>netstandard2.0</TargetFramework>
99
<PackageId>Microsoft.Azure.WebJobs.Logging.ApplicationInsights</PackageId>

test/Microsoft.Azure.WebJobs.Host.UnitTests/Loggers/ApplicationInsightsConfigurationTests.cs

+39-1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ public void DependencyInjectionConfiguration_ConfiguresSampling()
225225
o.SamplingSettings = samplingSettings;
226226
o.SamplingExcludedTypes = samplingExcludedTypes;
227227
o.SamplingIncludedTypes = samplingIncludedTypes;
228+
o.EnableAdaptiveSamplingDelay = false;
228229
});
229230
})
230231
.Build())
@@ -242,7 +243,43 @@ public void DependencyInjectionConfiguration_ConfiguresSampling()
242243
}
243244
}
244245

245-
246+
[Fact]
247+
public void DependencyInjectionConfiguration_ConfiguresDelayedSampling()
248+
{
249+
var samplingSettings = new SamplingPercentageEstimatorSettings { MaxTelemetryItemsPerSecond = 1 };
250+
var samplingExcludedTypes = "PageView;Request";
251+
var samplingIncludedTypes = "Trace";
252+
using (var host = new HostBuilder()
253+
.ConfigureLogging(b =>
254+
{
255+
b.AddApplicationInsightsWebJobs(o =>
256+
{
257+
o.InstrumentationKey = "some key";
258+
o.SamplingSettings = samplingSettings;
259+
o.SamplingExcludedTypes = samplingExcludedTypes;
260+
o.SamplingIncludedTypes = samplingIncludedTypes;
261+
});
262+
})
263+
.Build())
264+
{
265+
var config = host.Services.GetService<TelemetryConfiguration>();
266+
Assert.Equal(5, config.TelemetryProcessors.Count);
267+
Assert.IsType<OperationFilteringTelemetryProcessor>(config.TelemetryProcessors[0]);
268+
Assert.IsType<QuickPulseTelemetryProcessor>(config.TelemetryProcessors[1]);
269+
Assert.IsType<FilteringTelemetryProcessor>(config.TelemetryProcessors[2]);
270+
Assert.IsType<DelayedSamplingProcessor>(config.TelemetryProcessors[3]);
271+
272+
// Use reflection to access the private field "_samplingProcessor"
273+
var samplingProcessorField = typeof(DelayedSamplingProcessor)
274+
.GetField("_samplingProcessor", BindingFlags.NonPublic | BindingFlags.Instance);
275+
var samplingProcessorInstance = (AdaptiveSamplingTelemetryProcessor)samplingProcessorField.GetValue(config.TelemetryProcessors[3]);
276+
277+
Assert.Equal(samplingSettings.MaxTelemetryItemsPerSecond, samplingProcessorInstance.MaxTelemetryItemsPerSecond);
278+
Assert.Equal(samplingExcludedTypes, samplingProcessorInstance.ExcludedTypes);
279+
Assert.Equal(samplingIncludedTypes, samplingProcessorInstance.IncludedTypes);
280+
}
281+
}
282+
246283
[Fact]
247284
public void DependencyInjectionConfiguration_EnableLiveMetricsFilters()
248285
{
@@ -589,6 +626,7 @@ public void DependencyInjectionConfiguration_NoFilterConfiguresSampling()
589626
{
590627
o.InstrumentationKey = "some key";
591628
o.SamplingSettings = samplingSettings;
629+
o.EnableAdaptiveSamplingDelay = false;
592630
});
593631
}).Build())
594632
{

0 commit comments

Comments
 (0)