From 100b8f1e8c9da0319baefea097b805bd50592d5e Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Thu, 15 Feb 2024 23:36:40 +0200 Subject: [PATCH 1/8] Add extension method TelegramCore for running Telegram sink with default configurations --- examples/WebApp/Program.cs | 1 + .../Configuration/TelegramSinkDefaults.cs | 26 ++++++++++ .../DependencyInjectionExtensions.cs | 50 +++++++++++++++++++ .../LoggerConfigurationTelegramExtensions.cs | 3 +- 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs rename src/X.Serilog.Sinks.Telegram/{Configuration => Extensions}/LoggerConfigurationTelegramExtensions.cs (93%) diff --git a/examples/WebApp/Program.cs b/examples/WebApp/Program.cs index 084e75d..e22ff1a 100644 --- a/examples/WebApp/Program.cs +++ b/examples/WebApp/Program.cs @@ -7,6 +7,7 @@ using X.Serilog.Sinks.Telegram; using X.Serilog.Sinks.Telegram.Batch.Rules; using X.Serilog.Sinks.Telegram.Configuration; +using X.Serilog.Sinks.Telegram.Extensions; using X.Serilog.Sinks.Telegram.Filters; var builder = WebApplication.CreateBuilder(args); diff --git a/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs b/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs index c6d987d..42dc73b 100644 --- a/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs +++ b/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs @@ -7,6 +7,32 @@ namespace X.Serilog.Sinks.Telegram.Configuration; /// public static class TelegramSinkDefaults { + /// + /// Gets the logging mode for the application. + /// + /// + /// The logging mode determines how log messages are processed and formatted before being sent. + /// In this case, it is set to return , which indicates that log messages + /// will be published individually to the specified Telegram channel. + /// + /// + /// This property is read-only and returns the default logging mode of the system. + /// It is crucial for configuring the overall logging strategy of the application. + /// For example, when set to , each log message is sent as it occurs. + /// Other modes, like , could aggregate messages over a period + /// or until a certain condition is met before sending. + /// + public static LoggingMode DefaultFormatterMode => LoggingMode.Logs; + + public static FormatterConfiguration DefaultFormatterConfiguration => new() + { + UseEmoji = true, + ReadableApplicationName = "X.Serilog.Telegram.Sink", + IncludeException = false, + IncludeProperties = false, + TimeZone = TimeZoneInfo.Utc + }; + /// /// The limit on the number of log events to be included in a single batch. /// diff --git a/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs b/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs new file mode 100644 index 0000000..f04afa8 --- /dev/null +++ b/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs @@ -0,0 +1,50 @@ +using System.Collections.Immutable; +using X.Serilog.Sinks.Telegram.Batch.Rules; +using X.Serilog.Sinks.Telegram.Configuration; + +namespace X.Serilog.Sinks.Telegram.Extensions; + +public static class DependencyInjectionExtensions +{ + public static LoggerSinkConfiguration TelegramCore( + this LoggerSinkConfiguration sinkConfig, + string token, + string chatId, + LogEventLevel logLevel + ) + { + ArgumentNullException.ThrowIfNull(sinkConfig); + ArgumentNullException.ThrowIfNull(token); + ArgumentNullException.ThrowIfNull(chatId); + + TelegramCoreInternal(sinkConfig, token, chatId, logLevel); + + return sinkConfig; + } + + private static void TelegramCoreInternal(LoggerSinkConfiguration sinkConfig, string token, string chatId, + LogEventLevel logLevel) + { + sinkConfig.Telegram(config => + { + config.Token = token; + config.ChatId = chatId; + + config.Mode = TelegramSinkDefaults.DefaultFormatterMode; + + config.BatchPostingLimit = TelegramSinkDefaults.BatchPostingLimit; + config.BatchEmittingRulesConfiguration = new BatchEmittingRulesConfiguration + { + RuleCheckPeriod = TelegramSinkDefaults.RulesCheckPeriod, + BatchProcessingRules = new ImmutableArray + { + // send logs to the Telegram once per 250 seconds + new OncePerTimeRule(TelegramSinkDefaults.RulesCheckPeriod * 50) + } + }; + config.FormatterConfiguration = TelegramSinkDefaults.DefaultFormatterConfiguration; + }, + messageFormatter: null!, + restrictedToMinimumLevel: logLevel); + } +} \ No newline at end of file diff --git a/src/X.Serilog.Sinks.Telegram/Configuration/LoggerConfigurationTelegramExtensions.cs b/src/X.Serilog.Sinks.Telegram/Extensions/LoggerConfigurationTelegramExtensions.cs similarity index 93% rename from src/X.Serilog.Sinks.Telegram/Configuration/LoggerConfigurationTelegramExtensions.cs rename to src/X.Serilog.Sinks.Telegram/Extensions/LoggerConfigurationTelegramExtensions.cs index 06e88b2..db0fdbb 100644 --- a/src/X.Serilog.Sinks.Telegram/Configuration/LoggerConfigurationTelegramExtensions.cs +++ b/src/X.Serilog.Sinks.Telegram/Extensions/LoggerConfigurationTelegramExtensions.cs @@ -1,8 +1,9 @@ using System.Threading.Channels; using X.Serilog.Sinks.Telegram.Batch; +using X.Serilog.Sinks.Telegram.Configuration; using X.Serilog.Sinks.Telegram.Formatters; -namespace X.Serilog.Sinks.Telegram.Configuration; +namespace X.Serilog.Sinks.Telegram.Extensions; public static class LoggerConfigurationTelegramExtensions { From 9512803afcfbdf41fd6d283b85f1e90a8c1ff735 Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Thu, 15 Feb 2024 23:43:15 +0200 Subject: [PATCH 2/8] Extend configuration --- .../Extensions/DependencyInjectionExtensions.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs b/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs index f04afa8..0191e85 100644 --- a/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs +++ b/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs @@ -1,6 +1,7 @@ using System.Collections.Immutable; using X.Serilog.Sinks.Telegram.Batch.Rules; using X.Serilog.Sinks.Telegram.Configuration; +using X.Serilog.Sinks.Telegram.Filters; namespace X.Serilog.Sinks.Telegram.Extensions; @@ -22,7 +23,10 @@ LogEventLevel logLevel return sinkConfig; } - private static void TelegramCoreInternal(LoggerSinkConfiguration sinkConfig, string token, string chatId, + private static void TelegramCoreInternal( + LoggerSinkConfiguration sinkConfig, + string token, + string chatId, LogEventLevel logLevel) { sinkConfig.Telegram(config => @@ -43,6 +47,11 @@ private static void TelegramCoreInternal(LoggerSinkConfiguration sinkConfig, str } }; config.FormatterConfiguration = TelegramSinkDefaults.DefaultFormatterConfiguration; + config.LogFiltersConfiguration = new LogsFiltersConfiguration() + { + ApplyLogFilters = false, + Filters = new ImmutableArray() + }; }, messageFormatter: null!, restrictedToMinimumLevel: logLevel); From 14484e9190d3c61740ffa2b6dce7f06e31650aee Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Fri, 16 Feb 2024 14:38:12 +0200 Subject: [PATCH 3/8] Fix formatters nullable usage --- .../Formatters/DefaultAggregatedNotificationsFormatter.cs | 2 +- src/X.Serilog.Sinks.Telegram/Formatters/DefaultLogFormatter.cs | 2 +- src/X.Serilog.Sinks.Telegram/Formatters/IMessageFormatter.cs | 2 +- src/X.Serilog.Sinks.Telegram/Formatters/MessageFormatterBase.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/X.Serilog.Sinks.Telegram/Formatters/DefaultAggregatedNotificationsFormatter.cs b/src/X.Serilog.Sinks.Telegram/Formatters/DefaultAggregatedNotificationsFormatter.cs index 308ce6e..24c01b7 100644 --- a/src/X.Serilog.Sinks.Telegram/Formatters/DefaultAggregatedNotificationsFormatter.cs +++ b/src/X.Serilog.Sinks.Telegram/Formatters/DefaultAggregatedNotificationsFormatter.cs @@ -7,7 +7,7 @@ public class DefaultAggregatedNotificationsFormatter : MessageFormatterBase public override List Format( ICollection logEntries, FormatterConfiguration config, - Func, FormatterConfiguration, List> formatter = null) + Func, FormatterConfiguration, List>? formatter = null) { formatter ??= DefaultFormatter; return base.Format(logEntries, config, formatter); diff --git a/src/X.Serilog.Sinks.Telegram/Formatters/DefaultLogFormatter.cs b/src/X.Serilog.Sinks.Telegram/Formatters/DefaultLogFormatter.cs index 0b155bd..d513967 100644 --- a/src/X.Serilog.Sinks.Telegram/Formatters/DefaultLogFormatter.cs +++ b/src/X.Serilog.Sinks.Telegram/Formatters/DefaultLogFormatter.cs @@ -9,7 +9,7 @@ internal class DefaultLogFormatter : MessageFormatterBase /// Throws when, after using the formatter, the message is null, empty, or whitespace. public override List Format(ICollection logEntries, FormatterConfiguration config, - Func, FormatterConfiguration, List> formatter = null) + Func, FormatterConfiguration, List>? formatter = null) { if (!NotEmpty(logEntries)) { diff --git a/src/X.Serilog.Sinks.Telegram/Formatters/IMessageFormatter.cs b/src/X.Serilog.Sinks.Telegram/Formatters/IMessageFormatter.cs index de80b8c..f15311e 100644 --- a/src/X.Serilog.Sinks.Telegram/Formatters/IMessageFormatter.cs +++ b/src/X.Serilog.Sinks.Telegram/Formatters/IMessageFormatter.cs @@ -13,5 +13,5 @@ public interface IMessageFormatter /// Human-readable message. List Format(ICollection logEntries, FormatterConfiguration config, - Func, FormatterConfiguration, List> formatter = null); + Func, FormatterConfiguration, List>? formatter = null); } \ No newline at end of file diff --git a/src/X.Serilog.Sinks.Telegram/Formatters/MessageFormatterBase.cs b/src/X.Serilog.Sinks.Telegram/Formatters/MessageFormatterBase.cs index e863569..a69df61 100644 --- a/src/X.Serilog.Sinks.Telegram/Formatters/MessageFormatterBase.cs +++ b/src/X.Serilog.Sinks.Telegram/Formatters/MessageFormatterBase.cs @@ -10,7 +10,7 @@ public abstract class MessageFormatterBase : IMessageFormatter /// public virtual List Format(ICollection logEntries, FormatterConfiguration config, - Func, FormatterConfiguration, List> formatter = null) + Func, FormatterConfiguration, List>? formatter = null) { if (!NotEmpty(logEntries)) { From 4586a10fcdb54909ee1476911e307824a9db0c23 Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Fri, 16 Feb 2024 14:38:38 +0200 Subject: [PATCH 4/8] Improve execution hooks registration --- .../BatchEmittingRulesConfiguration.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/X.Serilog.Sinks.Telegram/Configuration/BatchEmittingRulesConfiguration.cs b/src/X.Serilog.Sinks.Telegram/Configuration/BatchEmittingRulesConfiguration.cs index db5515d..d33f4bf 100644 --- a/src/X.Serilog.Sinks.Telegram/Configuration/BatchEmittingRulesConfiguration.cs +++ b/src/X.Serilog.Sinks.Telegram/Configuration/BatchEmittingRulesConfiguration.cs @@ -40,15 +40,7 @@ public TimeSpan RuleCheckPeriod /// public IImmutableList BatchProcessingExecutionHooks => BatchProcessingRules - .Select(rule => - { - if (rule is IExecutionHook hook) - { - return hook; - } - - return null; - }) - .Where(hook => hook != null) - .ToImmutableList()!; + .Where(rule => rule is IExecutionHook) + .Cast() + .ToImmutableList(); } \ No newline at end of file From 72c711cf8f98a58903b9e5f2c4a6feb8a5dc9582 Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Fri, 16 Feb 2024 14:41:45 +0200 Subject: [PATCH 5/8] Bump serilog version and minor code formatting fix --- src/X.Serilog.Sinks.Telegram/TelegramSink.cs | 3 ++- src/X.Serilog.Sinks.Telegram/X.Serilog.Sinks.Telegram.csproj | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/X.Serilog.Sinks.Telegram/TelegramSink.cs b/src/X.Serilog.Sinks.Telegram/TelegramSink.cs index eeb2175..371d4a6 100644 --- a/src/X.Serilog.Sinks.Telegram/TelegramSink.cs +++ b/src/X.Serilog.Sinks.Telegram/TelegramSink.cs @@ -112,7 +112,8 @@ private async Task EmitBatchInternalAsync(int batchSize, CancellationToken cance private async Task> GetMessagesFromQueueAsync(int amount) { var logsBatch = await _logsQueueAccessor.DequeueSeveralAsync(amount); - var events = logsBatch.Where(log => log is not null) + var events = logsBatch + .Where(log => log is not null) .Select(LogEntry.MapFrom) .ToList(); diff --git a/src/X.Serilog.Sinks.Telegram/X.Serilog.Sinks.Telegram.csproj b/src/X.Serilog.Sinks.Telegram/X.Serilog.Sinks.Telegram.csproj index d1fb817..159a61b 100644 --- a/src/X.Serilog.Sinks.Telegram/X.Serilog.Sinks.Telegram.csproj +++ b/src/X.Serilog.Sinks.Telegram/X.Serilog.Sinks.Telegram.csproj @@ -15,7 +15,7 @@ - + From 42b28de039c8487b4ea3871fd5f8979457af59a8 Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Fri, 16 Feb 2024 14:42:12 +0200 Subject: [PATCH 6/8] Finalize TelegramCore method --- .../Configuration/TelegramSinkDefaults.cs | 2 +- .../Extensions/DependencyInjectionExtensions.cs | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs b/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs index 42dc73b..9bef296 100644 --- a/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs +++ b/src/X.Serilog.Sinks.Telegram/Configuration/TelegramSinkDefaults.cs @@ -22,7 +22,7 @@ public static class TelegramSinkDefaults /// Other modes, like , could aggregate messages over a period /// or until a certain condition is met before sending. /// - public static LoggingMode DefaultFormatterMode => LoggingMode.Logs; + public static LoggingMode DefaultFormatterMode => LoggingMode.AggregatedNotifications; public static FormatterConfiguration DefaultFormatterConfiguration => new() { diff --git a/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs b/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs index 0191e85..f0f6c35 100644 --- a/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs +++ b/src/X.Serilog.Sinks.Telegram/Extensions/DependencyInjectionExtensions.cs @@ -7,7 +7,7 @@ namespace X.Serilog.Sinks.Telegram.Extensions; public static class DependencyInjectionExtensions { - public static LoggerSinkConfiguration TelegramCore( + public static LoggerConfiguration TelegramCore( this LoggerSinkConfiguration sinkConfig, string token, string chatId, @@ -18,18 +18,16 @@ LogEventLevel logLevel ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(chatId); - TelegramCoreInternal(sinkConfig, token, chatId, logLevel); - - return sinkConfig; + return TelegramCoreInternal(sinkConfig, token, chatId, logLevel); } - private static void TelegramCoreInternal( + private static LoggerConfiguration TelegramCoreInternal( LoggerSinkConfiguration sinkConfig, string token, string chatId, LogEventLevel logLevel) { - sinkConfig.Telegram(config => + return sinkConfig.Telegram(config => { config.Token = token; config.ChatId = chatId; @@ -40,11 +38,12 @@ private static void TelegramCoreInternal( config.BatchEmittingRulesConfiguration = new BatchEmittingRulesConfiguration { RuleCheckPeriod = TelegramSinkDefaults.RulesCheckPeriod, - BatchProcessingRules = new ImmutableArray + BatchProcessingRules = new List { + new BatchSizeRule(config.LogsAccessor, batchSize: config.BatchPostingLimit), // send logs to the Telegram once per 250 seconds new OncePerTimeRule(TelegramSinkDefaults.RulesCheckPeriod * 50) - } + }.ToImmutableList() }; config.FormatterConfiguration = TelegramSinkDefaults.DefaultFormatterConfiguration; config.LogFiltersConfiguration = new LogsFiltersConfiguration() From 8a3b5673c78e97075685da74dd188e220b619e83 Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Fri, 16 Feb 2024 14:43:35 +0200 Subject: [PATCH 7/8] Add console app example and bump deps versions --- X.Serilog.Sinks.Telegram.sln | 7 +++++++ examples/ConsoleApp/ConsoleApp.csproj | 19 +++++++++++++++++++ examples/ConsoleApp/Program.cs | 23 +++++++++++++++++++++++ examples/WebApp/WebApp.csproj | 5 +++-- 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 examples/ConsoleApp/ConsoleApp.csproj create mode 100644 examples/ConsoleApp/Program.cs diff --git a/X.Serilog.Sinks.Telegram.sln b/X.Serilog.Sinks.Telegram.sln index 8396d0d..d4db7ff 100644 --- a/X.Serilog.Sinks.Telegram.sln +++ b/X.Serilog.Sinks.Telegram.sln @@ -8,6 +8,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{4A EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApp", "examples\WebApp\WebApp.csproj", "{15736D36-94A1-4E3F-8A5F-EFEFE27F1995}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "examples\ConsoleApp\ConsoleApp.csproj", "{D007F793-195D-448A-A34E-74EF0245F9D3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -22,9 +24,14 @@ Global {15736D36-94A1-4E3F-8A5F-EFEFE27F1995}.Debug|Any CPU.Build.0 = Debug|Any CPU {15736D36-94A1-4E3F-8A5F-EFEFE27F1995}.Release|Any CPU.ActiveCfg = Release|Any CPU {15736D36-94A1-4E3F-8A5F-EFEFE27F1995}.Release|Any CPU.Build.0 = Release|Any CPU + {D007F793-195D-448A-A34E-74EF0245F9D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D007F793-195D-448A-A34E-74EF0245F9D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D007F793-195D-448A-A34E-74EF0245F9D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D007F793-195D-448A-A34E-74EF0245F9D3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {807F309C-4CE3-4E68-8D46-9044A0A7BD6A} = {652C6F31-3E8C-400E-9716-ACF591E48E6F} {15736D36-94A1-4E3F-8A5F-EFEFE27F1995} = {4A2DA76C-10DE-476D-A26E-16FAB3CBFC8C} + {D007F793-195D-448A-A34E-74EF0245F9D3} = {4A2DA76C-10DE-476D-A26E-16FAB3CBFC8C} EndGlobalSection EndGlobal diff --git a/examples/ConsoleApp/ConsoleApp.csproj b/examples/ConsoleApp/ConsoleApp.csproj new file mode 100644 index 0000000..b6ebeec --- /dev/null +++ b/examples/ConsoleApp/ConsoleApp.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/examples/ConsoleApp/Program.cs b/examples/ConsoleApp/Program.cs new file mode 100644 index 0000000..111d5e4 --- /dev/null +++ b/examples/ConsoleApp/Program.cs @@ -0,0 +1,23 @@ +using Serilog; +using Serilog.Events; +using X.Serilog.Sinks.Telegram.Extensions; + +const string botToken = "TELEGRAM_BOT_TOKEN"; +const string loggingChatId = "CHANNEL_OR_CHAT_ID"; + +Log.Logger = new LoggerConfiguration() + // add console as logging target + .WriteTo.TelegramCore( + token: botToken, + chatId: loggingChatId, + logLevel: LogEventLevel.Verbose) + .WriteTo.Console() + .CreateLogger(); + + +while (true) +{ + var level = Random.Shared.NextInt64(0, 6); + Log.Logger.Write((LogEventLevel)level, "Message"); + await Task.Delay(500); +} \ No newline at end of file diff --git a/examples/WebApp/WebApp.csproj b/examples/WebApp/WebApp.csproj index 8d4a0ad..62db7f4 100644 --- a/examples/WebApp/WebApp.csproj +++ b/examples/WebApp/WebApp.csproj @@ -7,8 +7,9 @@ - - + + + From 10ab26bd24850b4e8dd24967c135d1e8659b8dbf Mon Sep 17 00:00:00 2001 From: Bardin08 Date: Fri, 16 Feb 2024 14:49:04 +0200 Subject: [PATCH 8/8] Remove invalid comment from console example --- examples/ConsoleApp/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ConsoleApp/Program.cs b/examples/ConsoleApp/Program.cs index 111d5e4..b72b8b7 100644 --- a/examples/ConsoleApp/Program.cs +++ b/examples/ConsoleApp/Program.cs @@ -6,7 +6,6 @@ const string loggingChatId = "CHANNEL_OR_CHAT_ID"; Log.Logger = new LoggerConfiguration() - // add console as logging target .WriteTo.TelegramCore( token: botToken, chatId: loggingChatId,