|
4 | 4 | using System; |
5 | 5 | using System.Collections.Generic; |
6 | 6 | using System.Linq; |
7 | | -using System.Threading.Tasks; |
8 | 7 | using Microsoft.Extensions.Compliance.Testing; |
9 | 8 | using Microsoft.Extensions.DependencyInjection; |
10 | 9 | using Microsoft.Extensions.Diagnostics.Enrichment; |
|
14 | 13 | using Moq; |
15 | 14 | using Xunit; |
16 | 15 | #if NET9_0_OR_GREATER |
| 16 | +using System.Threading.Tasks; |
17 | 17 | using Microsoft.Extensions.Diagnostics.Buffering; |
18 | 18 | #endif |
19 | 19 |
|
20 | 20 | namespace Microsoft.Extensions.Logging.Test; |
21 | 21 |
|
22 | | -public class ExtendedLoggerTests |
| 22 | +public static class ExtendedLoggerTests |
23 | 23 | { |
24 | 24 | [Theory] |
25 | 25 | [CombinatorialData] |
@@ -156,113 +156,6 @@ public static void Sampling() |
156 | 156 | Assert.Equal(0, provider.Logger!.Collector.Count); |
157 | 157 | } |
158 | 158 |
|
159 | | -#if NET9_0_OR_GREATER |
160 | | - [Fact] |
161 | | - public static void GlobalBuffering_CanonicalUsecase() |
162 | | - { |
163 | | - using var provider = new Provider(); |
164 | | - using ILoggerFactory factory = Utils.CreateLoggerFactory( |
165 | | - builder => |
166 | | - { |
167 | | - builder.AddProvider(provider); |
168 | | - builder.AddGlobalBuffer(LogLevel.Warning); |
169 | | - }); |
170 | | - |
171 | | - ILogger logger = factory.CreateLogger("my category"); |
172 | | - logger.LogWarning("MSG0"); |
173 | | - logger.Log(LogLevel.Warning, new EventId(2, "ID2"), "some state", null, (_, _) => "MSG2"); |
174 | | - |
175 | | - // nothing is logged because the buffer not flushed yet |
176 | | - Assert.Equal(0, provider.Logger!.Collector.Count); |
177 | | - |
178 | | - // instead of this, users would get LogBuffer from DI and call Flush on it |
179 | | - Utils.DisposingLoggerFactory dlf = (Utils.DisposingLoggerFactory)factory; |
180 | | - GlobalLogBuffer buffer = dlf.ServiceProvider.GetRequiredService<GlobalLogBuffer>(); |
181 | | - |
182 | | - buffer.Flush(); |
183 | | - |
184 | | - // 2 log records emitted because the buffer has been flushed |
185 | | - Assert.Equal(2, provider.Logger!.Collector.Count); |
186 | | - } |
187 | | - |
188 | | - [Fact] |
189 | | - public static void GlobalBuffering_ParallelLogging() |
190 | | - { |
191 | | - using var provider = new Provider(); |
192 | | - using ILoggerFactory factory = Utils.CreateLoggerFactory( |
193 | | - builder => |
194 | | - { |
195 | | - builder.AddProvider(provider); |
196 | | - builder.AddGlobalBuffer(LogLevel.Warning); |
197 | | - }); |
198 | | - |
199 | | - ILogger logger = factory.CreateLogger("my category"); |
200 | | - |
201 | | - // 1000 threads logging at the same time |
202 | | - Parallel.For(0, 1000, _ => |
203 | | - { |
204 | | - logger.LogWarning("MSG0"); |
205 | | - logger.Log(LogLevel.Warning, new EventId(2, "ID2"), "some state", null, (_, _) => "MSG2"); |
206 | | - }); |
207 | | - |
208 | | - // nothing is logged because the buffer not flushed yet |
209 | | - Assert.Equal(0, provider.Logger!.Collector.Count); |
210 | | - |
211 | | - |
212 | | - Utils.DisposingLoggerFactory dlf = (Utils.DisposingLoggerFactory)factory; |
213 | | - GlobalLogBuffer buffer = dlf.ServiceProvider.GetRequiredService<GlobalLogBuffer>(); |
214 | | - |
215 | | - buffer.Flush(); |
216 | | - |
217 | | - // 2000 log records emitted because the buffer has been flushed |
218 | | - Assert.Equal(2000, provider.Logger!.Collector.Count); |
219 | | - } |
220 | | - |
221 | | - [Fact] |
222 | | - public async Task GlobalBuffering_ParallelLoggingAndFlushing() |
223 | | - { |
224 | | - // Arrange |
225 | | - using var provider = new Provider(); |
226 | | - using ILoggerFactory factory = Utils.CreateLoggerFactory( |
227 | | - builder => |
228 | | - { |
229 | | - builder.AddProvider(provider); |
230 | | - builder.AddGlobalBuffer(options => |
231 | | - { |
232 | | - options.AutoFlushDuration = TimeSpan.Zero; |
233 | | - options.Rules.Add(new LogBufferingFilterRule(logLevel: LogLevel.Warning)); |
234 | | - }); |
235 | | - }); |
236 | | - |
237 | | - ILogger logger = factory.CreateLogger("my category"); |
238 | | - Utils.DisposingLoggerFactory dlf = (Utils.DisposingLoggerFactory)factory; |
239 | | - GlobalLogBuffer buffer = dlf.ServiceProvider.GetRequiredService<GlobalLogBuffer>(); |
240 | | - |
241 | | - // Act - Run logging and flushing operations in parallel |
242 | | - await Task.Run(() => |
243 | | - { |
244 | | - Parallel.For(0, 100, i => |
245 | | - { |
246 | | - logger.LogWarning("MSG0"); |
247 | | - logger.LogWarning("MSG1"); |
248 | | - logger.LogWarning("MSG2"); |
249 | | - logger.LogWarning("MSG3"); |
250 | | - logger.LogWarning("MSG4"); |
251 | | - logger.LogWarning("MSG5"); |
252 | | - logger.LogWarning("MSG6"); |
253 | | - logger.LogWarning("MSG7"); |
254 | | - logger.LogWarning("MSG8"); |
255 | | - logger.LogWarning("MSG9"); |
256 | | - buffer.Flush(); |
257 | | - }); |
258 | | - }); |
259 | | - |
260 | | - buffer.Flush(); |
261 | | - Assert.Equal(1000, provider.Logger!.Collector.Count); |
262 | | - } |
263 | | - |
264 | | -#endif |
265 | | - |
266 | 159 | [Theory] |
267 | 160 | [CombinatorialData] |
268 | 161 | public static void BagAndJoiner(bool objectVersion) |
@@ -1026,6 +919,112 @@ public static void LegacyLogging_OriginalFormatMustBeLastInTheListOfStatePropert |
1026 | 919 | Assert.Equal("V4", property.Value); |
1027 | 920 | } |
1028 | 921 |
|
| 922 | +#if NET9_0_OR_GREATER |
| 923 | + [Fact] |
| 924 | + public static void GlobalBuffering_CanonicalUsecase() |
| 925 | + { |
| 926 | + using var provider = new Provider(); |
| 927 | + using ILoggerFactory factory = Utils.CreateLoggerFactory( |
| 928 | + builder => |
| 929 | + { |
| 930 | + builder.AddProvider(provider); |
| 931 | + builder.AddGlobalBuffer(LogLevel.Warning); |
| 932 | + }); |
| 933 | + |
| 934 | + ILogger logger = factory.CreateLogger("my category"); |
| 935 | + logger.LogWarning("MSG0"); |
| 936 | + logger.Log(LogLevel.Warning, new EventId(2, "ID2"), "some state", null, (_, _) => "MSG2"); |
| 937 | + |
| 938 | + // nothing is logged because the buffer not flushed yet |
| 939 | + Assert.Equal(0, provider.Logger!.Collector.Count); |
| 940 | + |
| 941 | + // instead of this, users would get LogBuffer from DI and call Flush on it |
| 942 | + Utils.DisposingLoggerFactory dlf = (Utils.DisposingLoggerFactory)factory; |
| 943 | + GlobalLogBuffer buffer = dlf.ServiceProvider.GetRequiredService<GlobalLogBuffer>(); |
| 944 | + |
| 945 | + buffer.Flush(); |
| 946 | + |
| 947 | + // 2 log records emitted because the buffer has been flushed |
| 948 | + Assert.Equal(2, provider.Logger!.Collector.Count); |
| 949 | + } |
| 950 | + |
| 951 | + [Fact] |
| 952 | + public static void GlobalBuffering_ParallelLogging() |
| 953 | + { |
| 954 | + using var provider = new Provider(); |
| 955 | + using ILoggerFactory factory = Utils.CreateLoggerFactory( |
| 956 | + builder => |
| 957 | + { |
| 958 | + builder.AddProvider(provider); |
| 959 | + builder.AddGlobalBuffer(LogLevel.Warning); |
| 960 | + }); |
| 961 | + |
| 962 | + ILogger logger = factory.CreateLogger("my category"); |
| 963 | + |
| 964 | + // 1000 threads logging at the same time |
| 965 | + Parallel.For(0, 1000, _ => |
| 966 | + { |
| 967 | + logger.LogWarning("MSG0"); |
| 968 | + logger.Log(LogLevel.Warning, new EventId(2, "ID2"), "some state", null, (_, _) => "MSG2"); |
| 969 | + }); |
| 970 | + |
| 971 | + // nothing is logged because the buffer not flushed yet |
| 972 | + Assert.Equal(0, provider.Logger!.Collector.Count); |
| 973 | + |
| 974 | + Utils.DisposingLoggerFactory dlf = (Utils.DisposingLoggerFactory)factory; |
| 975 | + GlobalLogBuffer buffer = dlf.ServiceProvider.GetRequiredService<GlobalLogBuffer>(); |
| 976 | + |
| 977 | + buffer.Flush(); |
| 978 | + |
| 979 | + // 2000 log records emitted because the buffer has been flushed |
| 980 | + Assert.Equal(2000, provider.Logger!.Collector.Count); |
| 981 | + } |
| 982 | + |
| 983 | + [Fact] |
| 984 | + public static async Task GlobalBuffering_ParallelLoggingAndFlushing() |
| 985 | + { |
| 986 | + // Arrange |
| 987 | + using var provider = new Provider(); |
| 988 | + using ILoggerFactory factory = Utils.CreateLoggerFactory( |
| 989 | + builder => |
| 990 | + { |
| 991 | + builder.AddProvider(provider); |
| 992 | + builder.AddGlobalBuffer(options => |
| 993 | + { |
| 994 | + options.AutoFlushDuration = TimeSpan.Zero; |
| 995 | + options.Rules.Add(new LogBufferingFilterRule(logLevel: LogLevel.Warning)); |
| 996 | + }); |
| 997 | + }); |
| 998 | + |
| 999 | + ILogger logger = factory.CreateLogger("my category"); |
| 1000 | + Utils.DisposingLoggerFactory dlf = (Utils.DisposingLoggerFactory)factory; |
| 1001 | + GlobalLogBuffer buffer = dlf.ServiceProvider.GetRequiredService<GlobalLogBuffer>(); |
| 1002 | + |
| 1003 | + // Act - Run logging and flushing operations in parallel |
| 1004 | + await Task.Run(() => |
| 1005 | + { |
| 1006 | + Parallel.For(0, 100, i => |
| 1007 | + { |
| 1008 | + logger.LogWarning("MSG0"); |
| 1009 | + logger.LogWarning("MSG1"); |
| 1010 | + logger.LogWarning("MSG2"); |
| 1011 | + logger.LogWarning("MSG3"); |
| 1012 | + logger.LogWarning("MSG4"); |
| 1013 | + logger.LogWarning("MSG5"); |
| 1014 | + logger.LogWarning("MSG6"); |
| 1015 | + logger.LogWarning("MSG7"); |
| 1016 | + logger.LogWarning("MSG8"); |
| 1017 | + logger.LogWarning("MSG9"); |
| 1018 | + buffer.Flush(); |
| 1019 | + }); |
| 1020 | + }); |
| 1021 | + |
| 1022 | + buffer.Flush(); |
| 1023 | + Assert.Equal(1000, provider.Logger!.Collector.Count); |
| 1024 | + } |
| 1025 | + |
| 1026 | +#endif |
| 1027 | + |
1029 | 1028 | private sealed class CustomLoggerProvider : ILoggerProvider |
1030 | 1029 | { |
1031 | 1030 | private readonly string _providerName; |
|
0 commit comments