Skip to content

Commit 3b718cd

Browse files
author
evgenyfedorov2
committed
Fix dynamic config update
1 parent 4001a15 commit 3b718cd

File tree

3 files changed

+96
-9
lines changed

3 files changed

+96
-9
lines changed

src/Libraries/Microsoft.Extensions.Telemetry/Sampling/RandomProbabilisticSampler.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ namespace Microsoft.Extensions.Diagnostics.Sampling;
2020
/// </summary>
2121
internal sealed class RandomProbabilisticSampler : LoggingSampler, IDisposable
2222
{
23+
internal RandomProbabilisticSamplerFilterRule[] LastKnownGoodSamplerRules;
24+
2325
#if NETFRAMEWORK
2426
private static readonly System.Threading.ThreadLocal<Random> _randomInstance = new(() => new Random());
2527
#endif
2628

2729
private readonly IDisposable? _samplerOptionsChangeTokenRegistration;
2830
private readonly LogSamplingRuleSelector<RandomProbabilisticSamplerFilterRule> _ruleSelector;
29-
private RandomProbabilisticSamplerFilterRule[] _lastKnownGoodSamplerRules;
3031
private volatile bool _disposed;
3132

3233
/// <summary>
@@ -37,7 +38,7 @@ public RandomProbabilisticSampler(
3738
IOptionsMonitor<RandomProbabilisticSamplerOptions> options)
3839
{
3940
_ruleSelector = Throw.IfNull(ruleSelector);
40-
_lastKnownGoodSamplerRules = Throw.IfNullOrMemberNull(options, options!.CurrentValue).Rules.ToArray();
41+
LastKnownGoodSamplerRules = Throw.IfNullOrMemberNull(options, options!.CurrentValue).Rules.ToArray();
4142
_samplerOptionsChangeTokenRegistration = options.OnChange(OnSamplerOptionsChanged);
4243
}
4344

@@ -70,11 +71,11 @@ private void OnSamplerOptionsChanged(RandomProbabilisticSamplerOptions? updatedO
7071
{
7172
if (updatedOptions is null)
7273
{
73-
_lastKnownGoodSamplerRules = Array.Empty<RandomProbabilisticSamplerFilterRule>();
74+
LastKnownGoodSamplerRules = Array.Empty<RandomProbabilisticSamplerFilterRule>();
7475
}
7576
else
7677
{
77-
_lastKnownGoodSamplerRules = updatedOptions.Rules.ToArray();
78+
LastKnownGoodSamplerRules = updatedOptions.Rules.ToArray();
7879
}
7980

8081
_ruleSelector.InvalidateCache();
@@ -84,7 +85,7 @@ private bool TryApply<TState>(in LogEntry<TState> logEntry, out double probabili
8485
{
8586
probability = 0.0;
8687

87-
RandomProbabilisticSamplerFilterRule? rule = _ruleSelector.Select(_lastKnownGoodSamplerRules, logEntry.Category, logEntry.LogLevel, logEntry.EventId);
88+
RandomProbabilisticSamplerFilterRule? rule = _ruleSelector.Select(LastKnownGoodSamplerRules, logEntry.Category, logEntry.LogLevel, logEntry.EventId);
8889

8990
if (rule is null)
9091
{

src/Libraries/Microsoft.Extensions.Telemetry/Sampling/SamplingLoggerBuilderExtensions.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using Microsoft.Extensions.DependencyInjection;
88
using Microsoft.Extensions.DependencyInjection.Extensions;
99
using Microsoft.Extensions.Diagnostics.Sampling;
10-
using Microsoft.Extensions.Logging;
1110
using Microsoft.Extensions.Options;
1211
using Microsoft.Shared.DiagnosticIds;
1312
using Microsoft.Shared.Diagnostics;
@@ -51,11 +50,17 @@ public static ILoggingBuilder AddRandomProbabilisticSampler(this ILoggingBuilder
5150
_ = Throw.IfNull(builder);
5251
_ = Throw.IfNull(configuration);
5352

54-
_ = builder.Services.AddOptionsWithValidateOnStart<RandomProbabilisticSamplerOptions, RandomProbabilisticSamplerOptionsValidator>();
55-
_ = builder.Services.AddSingleton<IConfigureOptions<RandomProbabilisticSamplerOptions>>(
53+
_ = builder.Services
54+
.AddOptionsWithValidateOnStart<RandomProbabilisticSamplerOptions, RandomProbabilisticSamplerOptionsValidator>();
55+
_ = builder.Services
56+
.AddSingleton<IConfigureOptions<RandomProbabilisticSamplerOptions>>(
5657
new RandomProbabilisticSamplerConfigureOptions(configuration));
58+
_ = builder.Services
59+
.AddSingleton<IOptionsChangeTokenSource<RandomProbabilisticSamplerOptions>>(
60+
new ConfigurationChangeTokenSource<RandomProbabilisticSamplerOptions>(configuration));
5761

58-
_ = builder.Services.AddSingleton(typeof(LogSamplingRuleSelector<>));
62+
_ = builder.Services
63+
.AddSingleton(typeof(LogSamplingRuleSelector<>));
5964

6065
return builder.AddSampler<RandomProbabilisticSampler>();
6166
}

test/Libraries/Microsoft.Extensions.Telemetry.Tests/Sampling/SamplingLoggerBuilderExtensionsTests.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.Extensions.Diagnostics.Sampling;
1010
using Microsoft.Extensions.Logging;
1111
using Microsoft.Extensions.Logging.Abstractions;
12+
using Microsoft.Extensions.Logging.Test;
1213
using Microsoft.Extensions.Options;
1314
using Xunit;
1415

@@ -72,6 +73,86 @@ public void AddRandomProbabilisticSamplerFromConfiguration_RegistersInDI()
7273
Assert.Equivalent(expectedData, options.CurrentValue.Rules);
7374
}
7475

76+
[Fact]
77+
public void AddRandomProbabilisticSamplerFromConfig_PicksUpConfigChanges()
78+
{
79+
List<RandomProbabilisticSamplerFilterRule> initialData =
80+
[
81+
new(probability: 1.0, categoryName: "Program.MyLogger", logLevel: LogLevel.Information, eventId: 1, eventName: "number one"),
82+
new(probability : 0.01, logLevel : LogLevel.Information),
83+
new(probability : 0.1, logLevel : LogLevel.Warning)
84+
];
85+
List<RandomProbabilisticSamplerFilterRule> updatedData =
86+
[
87+
new(probability: 0, logLevel: LogLevel.Information),
88+
new(probability : 0, logLevel : LogLevel.Information),
89+
new(probability : 0, logLevel : LogLevel.Warning)
90+
];
91+
string jsonConfig =
92+
@"
93+
{
94+
""RandomProbabilisticSampler"": {
95+
""Rules"": [
96+
{
97+
""CategoryName"": ""Program.MyLogger"",
98+
""LogLevel"": ""Information"",
99+
""EventId"": 1,
100+
""EventName"": ""number one"",
101+
""Probability"": 1.0
102+
},
103+
{
104+
""LogLevel"": ""Information"",
105+
""Probability"": 0.01
106+
},
107+
{
108+
""LogLevel"": ""Warning"",
109+
""Probability"": 0.1
110+
}
111+
]
112+
}
113+
}
114+
";
115+
116+
using var config = TestConfiguration.Create(() => jsonConfig);
117+
var serviceCollection = new ServiceCollection();
118+
serviceCollection.AddLogging(builder =>
119+
{
120+
builder.AddRandomProbabilisticSampler(config);
121+
});
122+
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
123+
IOptionsMonitor<RandomProbabilisticSamplerOptions>? options = serviceProvider.GetService<IOptionsMonitor<RandomProbabilisticSamplerOptions>>();
124+
Assert.NotNull(options);
125+
Assert.NotNull(options.CurrentValue);
126+
Assert.Equivalent(initialData, options.CurrentValue.Rules);
127+
128+
jsonConfig =
129+
@"
130+
{
131+
""RandomProbabilisticSampler"": {
132+
""Rules"": [
133+
{
134+
""LogLevel"": ""Information"",
135+
""Probability"": 0
136+
},
137+
{
138+
""LogLevel"": ""Information"",
139+
""Probability"": 0
140+
},
141+
{
142+
""LogLevel"": ""Warning"",
143+
""Probability"": 0
144+
}
145+
]
146+
}
147+
}
148+
";
149+
config.Reload();
150+
151+
var sampler = serviceProvider.GetRequiredService<LoggingSampler>() as RandomProbabilisticSampler;
152+
Assert.NotNull(sampler);
153+
Assert.Equivalent(updatedData, sampler.LastKnownGoodSamplerRules);
154+
}
155+
75156
[Fact]
76157
public void AddRandomProbabilisticSampler_WhenRulesIsNull_ValidationFails()
77158
{

0 commit comments

Comments
 (0)