From 3848f9ea27f5413fa80dae94fc1e9374f225faad Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 12:39:56 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=AD=A3=E5=90=91?= =?UTF-8?q?=E8=B4=9F=E5=90=91=E8=BF=87=E6=BB=A4=E6=97=A5=E5=BF=97=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8C=B9=E9=85=8D=E5=A4=9A=E4=B8=AA=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Writers/ConsoleLogger.cs | 89 +++++++++++++++---- 1 file changed, 73 insertions(+), 16 deletions(-) diff --git a/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs b/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs index 499daaa..42a6eaf 100644 --- a/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs +++ b/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using dotnetCampus.Logging.Writers.Helpers; using C = dotnetCampus.Logging.Writers.ConsoleLoggerHelpers.ConsoleColors; @@ -97,7 +98,12 @@ private static void ConsoleMultilineMessage(string message, Func /// 当前已设置的过滤标签。 /// - private static ImmutableHashSetString ConsoleFilterTags { get; set; } = []; + private static ImmutableHashSetString IncludingFilterTags { get; set; } = []; + + /// + /// 当前已设置的过滤标签。 + /// + private static ImmutableHashSetString ExcludingFilterTags { get; set; } = []; /// /// 高于或等于此级别的日志才会被记录。 @@ -114,13 +120,36 @@ public ConsoleLogger UseLevel(LogLevel level) /// 命令行参数。 public ConsoleLogger FilterConsoleTagsFromCommandLineArgs(string[] args) { + HashSet includingFilterTags = []; + HashSet excludingFilterTags = []; for (var i = 0; i < args.Length; i++) { - if (args[i] == "--log-console-tags" && i + 1 < args.Length) + if (args[i] != "--log-console-tags" || i + 1 >= args.Length) { - ConsoleFilterTags = args[i + 1].Split([',', ';', ' ']).ToImmutableHashSet(); - break; + continue; } + + var filterTags = args[i + 1].Split([',', ';', ' ']); + foreach (var tag in filterTags) + { + if (tag.StartsWith("-", StringComparison.Ordinal)) + { +#if NET8_0_OR_GREATER + excludingFilterTags.Add(tag[1..]); +#else + excludingFilterTags.Add(tag.Substring(1)); +#endif + } + else + { + includingFilterTags.Add(tag); + } + } + + IncludingFilterTags = includingFilterTags.ToImmutableHashSet(); + ExcludingFilterTags = excludingFilterTags.ToImmutableHashSet(); + + break; } return this; } @@ -132,24 +161,52 @@ public ConsoleLogger FilterConsoleTagsFromCommandLineArgs(string[] args) /// 是否满足过滤条件。 private static bool IsTagEnabled(string text) { - if (ConsoleFilterTags.Count is 0) + if (IncludingFilterTags.Count is 0 && ExcludingFilterTags.Count is 0) { return true; } - var start = text.IndexOf('['); - if (start == -1) - { - return true; - } - var end = text.IndexOf(']', start); - if (end == -1) + var defaultEnabled = IncludingFilterTags.Count is 0; + var currentTagStartIndex = -1; + var isInTag = false; + for (var i = 0; i < text.Length; i++) { - return true; + if (text[i] == '[') + { + // 进入标签。 + currentTagStartIndex = i; + isInTag = true; + } + else if (text[i] == ']') + { + // 离开标签。 + var currentTagEndIndex = i; + isInTag = false; + if (currentTagStartIndex < 0) + { + return defaultEnabled; + } + var tag = text.AsSpan().Slice(currentTagStartIndex + 1, currentTagEndIndex - currentTagStartIndex - 1); + if (IncludingFilterTags.Contains(tag.ToString())) + { + return true; + } + if (ExcludingFilterTags.Contains(tag.ToString())) + { + return false; + } + } + else if (char.IsWhiteSpace(text[i])) + { + // 空白字符,不处理。 + } + else if (!isInTag) + { + // 当前不在标签内,且非空白字符,直接跳出。 + return defaultEnabled; + } } - - var tag = text.AsSpan().Slice(start + 1, end - start - 1); - return ConsoleFilterTags.Contains(tag.ToString()); + return defaultEnabled; } private void ClearAndMoveToLastLine(int repeatCount) From d0a00443160d19238b5a0d3e92e988f6e1d41830 Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 13:22:28 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E6=8F=90=E5=8F=96=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E5=99=A8=EF=BC=8C=E6=96=B9=E4=BE=BF=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Writers/ConsoleLogger.cs | 101 +------------- .../Writers/Helpers/TagFilterManager.cs | 132 ++++++++++++++++++ 2 files changed, 135 insertions(+), 98 deletions(-) create mode 100644 src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs diff --git a/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs b/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs index 42a6eaf..f0f7ec9 100644 --- a/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs +++ b/src/dotnetCampus.Logger/Writers/ConsoleLogger.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using dotnetCampus.Logging.Writers.Helpers; using C = dotnetCampus.Logging.Writers.ConsoleLoggerHelpers.ConsoleColors; @@ -17,6 +16,7 @@ public class ConsoleLogger : ILogger private int _isCursorMovementEnabled = 3; private readonly RepeatLoggerDetector _repeat; + private TagFilterManager? _tagFilterManager; /// /// 高于或等于此级别的日志才会被记录。 @@ -36,7 +36,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } var message = formatter(state, exception); - if (!IsTagEnabled(message)) + if (_tagFilterManager?.IsTagEnabled(message) is false) { return; } @@ -95,16 +95,6 @@ private static void ConsoleMultilineMessage(string message, Func - /// 当前已设置的过滤标签。 - /// - private static ImmutableHashSetString IncludingFilterTags { get; set; } = []; - - /// - /// 当前已设置的过滤标签。 - /// - private static ImmutableHashSetString ExcludingFilterTags { get; set; } = []; - /// /// 高于或等于此级别的日志才会被记录。 /// @@ -120,95 +110,10 @@ public ConsoleLogger UseLevel(LogLevel level) /// 命令行参数。 public ConsoleLogger FilterConsoleTagsFromCommandLineArgs(string[] args) { - HashSet includingFilterTags = []; - HashSet excludingFilterTags = []; - for (var i = 0; i < args.Length; i++) - { - if (args[i] != "--log-console-tags" || i + 1 >= args.Length) - { - continue; - } - - var filterTags = args[i + 1].Split([',', ';', ' ']); - foreach (var tag in filterTags) - { - if (tag.StartsWith("-", StringComparison.Ordinal)) - { -#if NET8_0_OR_GREATER - excludingFilterTags.Add(tag[1..]); -#else - excludingFilterTags.Add(tag.Substring(1)); -#endif - } - else - { - includingFilterTags.Add(tag); - } - } - - IncludingFilterTags = includingFilterTags.ToImmutableHashSet(); - ExcludingFilterTags = excludingFilterTags.ToImmutableHashSet(); - - break; - } + _tagFilterManager = TagFilterManager.FromCommandLineArgs(args); return this; } - /// - /// 判断某个日志是否满足当前标签过滤条件。 - /// - /// 要判断的日志原文。 - /// 是否满足过滤条件。 - private static bool IsTagEnabled(string text) - { - if (IncludingFilterTags.Count is 0 && ExcludingFilterTags.Count is 0) - { - return true; - } - - var defaultEnabled = IncludingFilterTags.Count is 0; - var currentTagStartIndex = -1; - var isInTag = false; - for (var i = 0; i < text.Length; i++) - { - if (text[i] == '[') - { - // 进入标签。 - currentTagStartIndex = i; - isInTag = true; - } - else if (text[i] == ']') - { - // 离开标签。 - var currentTagEndIndex = i; - isInTag = false; - if (currentTagStartIndex < 0) - { - return defaultEnabled; - } - var tag = text.AsSpan().Slice(currentTagStartIndex + 1, currentTagEndIndex - currentTagStartIndex - 1); - if (IncludingFilterTags.Contains(tag.ToString())) - { - return true; - } - if (ExcludingFilterTags.Contains(tag.ToString())) - { - return false; - } - } - else if (char.IsWhiteSpace(text[i])) - { - // 空白字符,不处理。 - } - else if (!isInTag) - { - // 当前不在标签内,且非空白字符,直接跳出。 - return defaultEnabled; - } - } - return defaultEnabled; - } - private void ClearAndMoveToLastLine(int repeatCount) { if (_isCursorMovementEnabled > 0 && repeatCount > 2) diff --git a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs new file mode 100644 index 0000000..4f66f7f --- /dev/null +++ b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; + +namespace dotnetCampus.Logging.Writers.Helpers; + +internal class TagFilterManager +{ + /// + /// 当前已设置的过滤标签。(无前缀,代表任一匹配。) + /// + public required ImmutableHashSetString AnyFilterTags { get; init; } + + /// + /// 当前已设置的过滤标签。(前缀为 +,代表必须匹配。) + /// + public required ImmutableHashSetString IncludingFilterTags { get; init; } + + /// + /// 当前已设置的过滤标签。(前缀为 -,代表必须不匹配。) + /// + public required ImmutableHashSetString ExcludingFilterTags { get; init; } + + /// + /// 判断某个日志是否满足当前标签过滤条件。 + /// + /// 要判断的日志原文。 + /// 是否满足过滤条件。 + internal bool IsTagEnabled(string text) + { + if (AnyFilterTags.Count is 0 && ExcludingFilterTags.Count is 0 && IncludingFilterTags.Count is 0) + { + return true; + } + + var defaultEnabled = AnyFilterTags.Count is 0 && IncludingFilterTags.Count is 0; + var currentTagStartIndex = -1; + var isInTag = false; + for (var i = 0; i < text.Length; i++) + { + if (text[i] == '[') + { + // 进入标签。 + currentTagStartIndex = i; + isInTag = true; + } + else if (text[i] == ']') + { + // 离开标签。 + var currentTagEndIndex = i; + isInTag = false; + if (currentTagStartIndex < 0) + { + return defaultEnabled; + } + var tag = text.AsSpan().Slice(currentTagStartIndex + 1, currentTagEndIndex - currentTagStartIndex - 1).ToString(); + // 只要有一个排除标签匹配,就不输出。 + if (ExcludingFilterTags.Contains(tag)) + { + return false; + } + + } + else if (char.IsWhiteSpace(text[i])) + { + // 空白字符,不处理。 + } + else if (!isInTag) + { + // 当前不在标签内,且非空白字符,直接跳出。 + return defaultEnabled; + } + } + return defaultEnabled; + } + + /// + /// 从命令行参数中提取过滤标签。 + /// + /// 命令行参数。 + public static TagFilterManager? FromCommandLineArgs(string[] args) + { + HashSet anyFilterTags = []; + HashSet includingFilterTags = []; + HashSet excludingFilterTags = []; + for (var i = 0; i < args.Length; i++) + { + if (args[i] != "--log-console-tags" || i + 1 >= args.Length) + { + continue; + } + + var filterTags = args[i + 1].Split([',', ';', ' ']); + foreach (var tag in filterTags) + { + if (tag.StartsWith("-", StringComparison.Ordinal)) + { +#if NET8_0_OR_GREATER + excludingFilterTags.Add(tag[1..]); +#else + excludingFilterTags.Add(tag.Substring(1)); +#endif + } + else if (tag.StartsWith("+", StringComparison.Ordinal)) + { +#if NET8_0_OR_GREATER + includingFilterTags.Add(tag[1..]); +#else + includingFilterTags.Add(tag.Substring(1)); +#endif + } + else + { + anyFilterTags.Add(tag); + } + } + + return new TagFilterManager + { + AnyFilterTags = anyFilterTags.ToImmutableHashSet(), + IncludingFilterTags = includingFilterTags.ToImmutableHashSet(), + ExcludingFilterTags = excludingFilterTags.ToImmutableHashSet(), + }; + } + + return new TagFilterManager + { + AnyFilterTags = [], + IncludingFilterTags = [], + ExcludingFilterTags = [], + }; + } +} From ce55fc563ae5016aaba5b3938042a1272e857e09 Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 13:37:15 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Writers/Helpers/TagFilterManager.cs | 10 ++- .../dotnetCampus.Logger.csproj | 4 + .../TagFilterManagerTests.cs | 78 +++++++++++++++++++ tests/dotnetCampus.Logger.Tests/UnitTest1.cs | 10 --- .../dotnetCampus.Logger.Tests.csproj | 4 + 5 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs delete mode 100644 tests/dotnetCampus.Logger.Tests/UnitTest1.cs diff --git a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs index 4f66f7f..4da6489 100644 --- a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs +++ b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs @@ -5,18 +5,20 @@ namespace dotnetCampus.Logging.Writers.Helpers; internal class TagFilterManager { + public const string LogTagParameterName = "--log-console-tags"; + /// - /// 当前已设置的过滤标签。(无前缀,代表任一匹配。) + /// 当前已设置的任一标签。(无前缀) /// public required ImmutableHashSetString AnyFilterTags { get; init; } /// - /// 当前已设置的过滤标签。(前缀为 +,代表必须匹配。) + /// 当前已设置的包含标签。(前缀为 +) /// public required ImmutableHashSetString IncludingFilterTags { get; init; } /// - /// 当前已设置的过滤标签。(前缀为 -,代表必须不匹配。) + /// 当前已设置的排除标签。(前缀为 -) /// public required ImmutableHashSetString ExcludingFilterTags { get; init; } @@ -84,7 +86,7 @@ internal bool IsTagEnabled(string text) HashSet excludingFilterTags = []; for (var i = 0; i < args.Length; i++) { - if (args[i] != "--log-console-tags" || i + 1 >= args.Length) + if (args[i] != LogTagParameterName || i + 1 >= args.Length) { continue; } diff --git a/src/dotnetCampus.Logger/dotnetCampus.Logger.csproj b/src/dotnetCampus.Logger/dotnetCampus.Logger.csproj index ded2b44..c11f7eb 100644 --- a/src/dotnetCampus.Logger/dotnetCampus.Logger.csproj +++ b/src/dotnetCampus.Logger/dotnetCampus.Logger.csproj @@ -44,6 +44,10 @@ + + + + diff --git a/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs b/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs new file mode 100644 index 0000000..9e05c9c --- /dev/null +++ b/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs @@ -0,0 +1,78 @@ +using dotnetCampus.Logging.Writers.Helpers; + +namespace dotnetCampus.Logger.Tests; + +[TestClass] +public class TagFilterManagerTests +{ + [TestMethod("单个任一标签,只要有一个标签匹配即允许。")] + public void 单个任一标签() + { + var filter = CreateFilter("Foo"); + Assert.IsTrue(filter.IsTagEnabled("[Foo] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("多个任一标签,只要有一个标签匹配即允许。")] + public void 多个任一标签() + { + var filter = CreateFilter("Foo,Bar"); + Assert.IsTrue(filter.IsTagEnabled("[Foo] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("单个包含标签,只要有一个标签匹配即允许。")] + public void 单个包含标签() + { + var filter = CreateFilter("+Foo"); + Assert.IsTrue(filter.IsTagEnabled("[Foo] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("多个包含标签,必须所有标签都匹配才允许。")] + public void 多个包含标签() + { + var filter = CreateFilter("+Foo,+Bar"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("单个排除标签,任一标签匹配即不允许。")] + public void 单个排除标签() + { + var filter = CreateFilter("-Foo"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("多个排除标签,任一标签匹配即不允许。")] + public void 多个排除标签() + { + var filter = CreateFilter("-Foo,-Bar"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx] Message")); + } + + private static TagFilterManager CreateFilter(string commandLineFilterValue) + { + return TagFilterManager.FromCommandLineArgs([TagFilterManager.LogTagParameterName, commandLineFilterValue])!; + } +} diff --git a/tests/dotnetCampus.Logger.Tests/UnitTest1.cs b/tests/dotnetCampus.Logger.Tests/UnitTest1.cs deleted file mode 100644 index 2b72684..0000000 --- a/tests/dotnetCampus.Logger.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace dotnetCampus.Logger.Tests; - -[TestClass] -public class UnitTest1 -{ - [TestMethod("Add test description here")] - public void TestMethod1() - { - } -} diff --git a/tests/dotnetCampus.Logger.Tests/dotnetCampus.Logger.Tests.csproj b/tests/dotnetCampus.Logger.Tests/dotnetCampus.Logger.Tests.csproj index 902f82c..897ea37 100644 --- a/tests/dotnetCampus.Logger.Tests/dotnetCampus.Logger.Tests.csproj +++ b/tests/dotnetCampus.Logger.Tests/dotnetCampus.Logger.Tests.csproj @@ -18,4 +18,8 @@ + + + + From d7f030d4f7c83e902a52fe128a8adcb16d4a1211 Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 13:46:57 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E7=9A=84=E5=8D=95?= =?UTF-8?q?=E4=B8=80=E7=A7=8D=E7=B1=BB=E6=A0=87=E7=AD=BE=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Writers/Helpers/TagFilterManager.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs index 4da6489..67282e7 100644 --- a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs +++ b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace dotnetCampus.Logging.Writers.Helpers; @@ -37,6 +38,7 @@ internal bool IsTagEnabled(string text) var defaultEnabled = AnyFilterTags.Count is 0 && IncludingFilterTags.Count is 0; var currentTagStartIndex = -1; var isInTag = false; + List includingTags = IncludingFilterTags.ToList(); for (var i = 0; i < text.Length; i++) { if (text[i] == '[') @@ -60,7 +62,24 @@ internal bool IsTagEnabled(string text) { return false; } - + // 如果有包含标签,则匹配一个,直到全部匹配。 + if (IncludingFilterTags.Count > 0) + { + if (includingTags.Contains(tag)) + { + includingTags.Remove(tag); + } + if (includingTags.Count is 0) + { + return true; + } + continue; + } + // 如果有任一标签,则匹配一个即可。 + if (AnyFilterTags.Contains(tag)) + { + return true; + } } else if (char.IsWhiteSpace(text[i])) { From 46f198793fedf0629db9ed804979e35538be8130 Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 14:25:03 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8D=95=E4=B8=80?= =?UTF-8?q?=E7=BB=84=E5=90=88=E6=A0=87=E7=AD=BE=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Writers/Helpers/TagFilterManager.cs | 40 +++++++++++++------ .../TagFilterManagerTests.cs | 39 ++++++++++++++++++ 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs index 67282e7..19aca8d 100644 --- a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs +++ b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs @@ -28,6 +28,14 @@ internal class TagFilterManager /// /// 要判断的日志原文。 /// 是否满足过滤条件。 + /// + /// 匹配原则: + /// + /// 先看任一标签进行初筛:只要有一个标签匹配,即选出;但如果没有指定任一标签,则全部选出。 + /// 在前一个初筛的基础上,再看排除标签:只要有一个标签匹配,即排除。 + /// 在前两个筛选的基础上,再看包含标签:必须全部标签匹配,才选出,其他全部排除。 + /// + /// internal bool IsTagEnabled(string text) { if (AnyFilterTags.Count is 0 && ExcludingFilterTags.Count is 0 && IncludingFilterTags.Count is 0) @@ -38,6 +46,7 @@ internal bool IsTagEnabled(string text) var defaultEnabled = AnyFilterTags.Count is 0 && IncludingFilterTags.Count is 0; var currentTagStartIndex = -1; var isInTag = false; + var matchAny = false; List includingTags = IncludingFilterTags.ToList(); for (var i = 0; i < text.Length; i++) { @@ -62,23 +71,28 @@ internal bool IsTagEnabled(string text) { return false; } - // 如果有包含标签,则匹配一个,直到全部匹配。 - if (IncludingFilterTags.Count > 0) + // 如果有任一标签,则匹配一个即可。 + matchAny = matchAny || defaultEnabled || AnyFilterTags.Contains(tag); + if (matchAny) { - if (includingTags.Contains(tag)) + // 如果有包含标签,则匹配一个,直到全部匹配。 + if (IncludingFilterTags.Count > 0) { - includingTags.Remove(tag); + if (includingTags.Contains(tag)) + { + includingTags.Remove(tag); + } + if (includingTags.Count is 0) + { + return true; + } + continue; } - if (includingTags.Count is 0) + + if (ExcludingFilterTags.Count is 0) { return true; } - continue; - } - // 如果有任一标签,则匹配一个即可。 - if (AnyFilterTags.Contains(tag)) - { - return true; } } else if (char.IsWhiteSpace(text[i])) @@ -88,10 +102,10 @@ internal bool IsTagEnabled(string text) else if (!isInTag) { // 当前不在标签内,且非空白字符,直接跳出。 - return defaultEnabled; + return defaultEnabled || matchAny; } } - return defaultEnabled; + return defaultEnabled || matchAny; } /// diff --git a/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs b/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs index 9e05c9c..4e853d6 100644 --- a/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs +++ b/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs @@ -71,6 +71,45 @@ public void 多个排除标签() Assert.IsTrue(filter.IsTagEnabled("[xxxx] Message")); } + [TestMethod("单个任一和包含标签,只要有一个标签匹配即允许。")] + public void 单个任一和包含标签() + { + var filter = CreateFilter("Foo,+Bar"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("单个任一和排除标签,只要有一个标签匹配即不允许。")] + public void 单个任一和排除标签() + { + var filter = CreateFilter("Foo,-Bar"); + Assert.IsTrue(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("单个包含和排除标签,只要有一个标签匹配即不允许。")] + public void 单个包含和排除标签() + { + var filter = CreateFilter("+Foo,-Bar"); + Assert.IsTrue(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + private static TagFilterManager CreateFilter(string commandLineFilterValue) { return TagFilterManager.FromCommandLineArgs([TagFilterManager.LogTagParameterName, commandLineFilterValue])!; From 5c89a9a4a2a088e53584f0faa26835b666c88fdf Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 14:33:02 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E7=90=86=E6=B8=85=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Writers/Helpers/TagFilterManager.cs | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs index 19aca8d..4eec834 100644 --- a/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs +++ b/src/dotnetCampus.Logger/Writers/Helpers/TagFilterManager.cs @@ -43,10 +43,11 @@ internal bool IsTagEnabled(string text) return true; } - var defaultEnabled = AnyFilterTags.Count is 0 && IncludingFilterTags.Count is 0; + var 任一满足 = AnyFilterTags.Count is 0; + var 包含满足 = IncludingFilterTags.Count is 0; + var currentTagStartIndex = -1; var isInTag = false; - var matchAny = false; List includingTags = IncludingFilterTags.ToList(); for (var i = 0; i < text.Length; i++) { @@ -63,7 +64,7 @@ internal bool IsTagEnabled(string text) isInTag = false; if (currentTagStartIndex < 0) { - return defaultEnabled; + return 任一满足; } var tag = text.AsSpan().Slice(currentTagStartIndex + 1, currentTagEndIndex - currentTagStartIndex - 1).ToString(); // 只要有一个排除标签匹配,就不输出。 @@ -72,11 +73,11 @@ internal bool IsTagEnabled(string text) return false; } // 如果有任一标签,则匹配一个即可。 - matchAny = matchAny || defaultEnabled || AnyFilterTags.Contains(tag); - if (matchAny) + 任一满足 = 任一满足 || AnyFilterTags.Contains(tag); + if (任一满足) { // 如果有包含标签,则匹配一个,直到全部匹配。 - if (IncludingFilterTags.Count > 0) + if (!包含满足 && IncludingFilterTags.Count > 0) { if (includingTags.Contains(tag)) { @@ -84,14 +85,8 @@ internal bool IsTagEnabled(string text) } if (includingTags.Count is 0) { - return true; + 包含满足 = true; } - continue; - } - - if (ExcludingFilterTags.Count is 0) - { - return true; } } } @@ -102,10 +97,10 @@ internal bool IsTagEnabled(string text) else if (!isInTag) { // 当前不在标签内,且非空白字符,直接跳出。 - return defaultEnabled || matchAny; + return 任一满足 && 包含满足; } } - return defaultEnabled || matchAny; + return 任一满足 && 包含满足; } /// From 2ec39917b2e9e8d8de7a7fdbcc864866b78fd343 Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 15 Aug 2024 14:43:48 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TagFilterManagerTests.cs | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs b/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs index 4e853d6..954c51d 100644 --- a/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs +++ b/tests/dotnetCampus.Logger.Tests/TagFilterManagerTests.cs @@ -110,6 +110,112 @@ public void 单个包含和排除标签() Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); } + [TestMethod("单个任一和包含和排除标签,只要有一个排除标签匹配即不允许,否则只要有一个标签匹配即允许。")] + public void 单个任一和包含和排除标签() + { + var filter = CreateFilter("Foo,+Bar,-Baz"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Baz] Message")); + Assert.IsTrue(filter.IsTagEnabled("[xxxx][Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo][Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Bar][Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx][Foo][Bar][Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[xxxx] Message")); + } + + [TestMethod("多个任一和包含标签,在任一标签匹配的基础上,必须所有包含标签匹配才允许。")] + public void 多个任一和包含标签() + { + var filter = CreateFilter("Foo,Bar,+Baz,+Qux"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Qux] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Baz] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Baz][Qux] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar][Baz][Qux] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz][Qux] Message")); + } + + [TestMethod("多个任一和排除标签,在任一标签匹配的基础上,只要有一个排除标签匹配即不允许。")] + public void 多个任一和排除标签() + { + var filter = CreateFilter("Foo,Bar,-Baz,-Qux"); + Assert.IsTrue(filter.IsTagEnabled("[Foo] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Qux] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Baz][Qux] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Bar][Baz][Qux] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz][Qux] Message")); + } + + [TestMethod("多个包含和排除标签,必须所有包含标签匹配,且没有排除标签匹配才允许。")] + public void 多个包含和排除标签() + { + var filter = CreateFilter("+Foo,+Bar,-Baz,-Qux"); + Assert.IsFalse(filter.IsTagEnabled("[Foo] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Qux] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo][Bar] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Baz][Qux] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo][Bar][Baz][Qux] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz][Qux] Message")); + } + + public void 多个任一和包含和排除标签() + { + var filter = CreateFilter("Foo1,Foo2,+Bar1,+Bar2,-Baz1,-Baz2"); + Assert.IsFalse(filter.IsTagEnabled("[Foo1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Bar2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Foo2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Baz2] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo1][Bar1][Bar2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar2][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar2][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1][Bar2][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1][Bar2][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1][Baz1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar2][Baz1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo1][Bar1][Bar2][Baz1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Baz2] Message")); + Assert.IsTrue(filter.IsTagEnabled("[Foo2][Bar1][Bar2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar2][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar2][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1][Bar2][Baz1] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1][Bar2][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1][Baz1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar2][Baz1][Baz2] Message")); + Assert.IsFalse(filter.IsTagEnabled("[Foo2][Bar1][Bar2][Baz1][Baz2] Message")); + } + private static TagFilterManager CreateFilter(string commandLineFilterValue) { return TagFilterManager.FromCommandLineArgs([TagFilterManager.LogTagParameterName, commandLineFilterValue])!;