diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index f00aa48..f92299d 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -67,29 +67,30 @@ jobs: needs: build-and-test-release runs-on: windows-latest steps: - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - name: Set up JDK 17 + uses: actions/setup-java@v3 with: - java-version: 1.11 + java-version: 17 + distribution: 'zulu' # Alternative distribution options are available. - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Cache SonarCloud packages - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~\sonar\cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache SonarCloud scanner id: cache-sonar-scanner - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: .\.sonar\scanner key: ${{ runner.os }}-sonar-scanner restore-keys: ${{ runner.os }}-sonar-scanner - name: Cache dotnet-coverage id: cache-dotnet-coverage - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: .\.dotnet-coverage\dotnet-coverage key: ${{ runner.os }}-dotnet-coverage diff --git a/README.md b/README.md index c7702f1..1dfdd19 100644 --- a/README.md +++ b/README.md @@ -4,31 +4,36 @@ A basic Slack Sink for the Serilog framework. ## Status -| | | -|----------------------:|-----------------------| -| Build & Test Status (main) | [![Build&Test](https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook/actions/workflows/dotnet.yml/badge.svg)](https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook/actions/workflows/dotnet.yml) | -| Nuget Package Version | [![Nuget Version](https://img.shields.io/nuget/v/jjm.one.Serilog.Sinks.SlackWebHook?style=flat-square)](https://www.nuget.org/packages/jjm.one.Serilog.Sinks.SlackWebHook/) | +| | | +|------------------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Build & Test Status (main) | [![Build&Test](https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook/actions/workflows/dotnet.yml/badge.svg)](https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook/actions/workflows/dotnet.yml) | +| Nuget Package Version | [![Nuget Version](https://img.shields.io/nuget/v/jjm.one.Serilog.Sinks.SlackWebHook?style=flat-square)](https://www.nuget.org/packages/jjm.one.Serilog.Sinks.SlackWebHook/) | | SonarCloudQuality Gate Status | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=jjm-one_jjm.one.Serilog.Sinks.SlackWebHook&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=jjm-one_jjm.one.Serilog.Sinks.SlackWebHook) | ## Description -This tool provides a Serilog Sink which sends log messages to one or more channels in a Slack workspace. To send this messages this tool is using the [Slack.Webhooks](https://github.com/mrb0nj/Slack.Webhooks) project to handle the communication with Slack. Therefor you need a valid WebHook URL to use this Sink. To get such a WebHook URL please read this [article](https://slack.com/help/articles/115005265063-Incoming-Webhooks-for-Slack). The log messages will be send in batches to the slack servers. You can setup the batch size to fit your needs. +This tool provides a Serilog Sink which sends log messages to one or more channels in a Slack workspace. To send this +messages this tool is using the [Slack.Webhooks](https://github.com/mrb0nj/Slack.Webhooks) project to handle the +communication with Slack. Therefor you need a valid WebHook URL to use this Sink. To get such a WebHook URL please read +this [article](https://slack.com/help/articles/115005265063-Incoming-Webhooks-for-Slack). The log messages will be send +in batches to the slack servers. You can setup the batch size to fit your needs. ## Nuget Package -You can get the latest version of this software as a nuget package form [nuget.org](https://www.nuget.org/packages/jjm.one.Serilog.Sinks.SlackWebHook/) +You can get the latest version of this software as a nuget package +form [nuget.org](https://www.nuget.org/packages/jjm.one.Serilog.Sinks.SlackWebHook/) ### Installing the Nuget Package -| Tool | Command/Code | -|----------------------|--------------| -| Package Manager | ```PM> Install-Package jjm.one.Serilog.Sinks.SlackWebHook -Version X.Y.Z``` | -| .NET CLI | ```> dotnet add package jjm.one.Serilog.Sinks.SlackWebHook --version X.Y.Z``` | +| Tool | Command/Code | +|----------------------|-----------------------------------------------------------------------------------------| +| Package Manager | ```PM> Install-Package jjm.one.Serilog.Sinks.SlackWebHook -Version X.Y.Z``` | +| .NET CLI | ```> dotnet add package jjm.one.Serilog.Sinks.SlackWebHook --version X.Y.Z``` | | PackageReference | `````` | -| Package CLI | ```> paket add jjm.one.Serilog.Sinks.SlackWebHook --version X.Y.Z``` | -| Script & Interactive | ```> #r "nuget: jjm.one.Serilog.Sinks.SlackWebHook, X.Y.Z"``` | -| Cake as Addin | ```#addin nuget:?package=jjm.one.Serilog.Sinks.SlackWebHook&version=X.Y.Z``` | -| Cake as Tool | ```#tool nuget:?package=jjm.one.Serilog.Sinks.SlackWebHook&version=X.Y.Z``` | +| Package CLI | ```> paket add jjm.one.Serilog.Sinks.SlackWebHook --version X.Y.Z``` | +| Script & Interactive | ```> #r "nuget: jjm.one.Serilog.Sinks.SlackWebHook, X.Y.Z"``` | +| Cake as Addin | ```#addin nuget:?package=jjm.one.Serilog.Sinks.SlackWebHook&version=X.Y.Z``` | +| Cake as Tool | ```#tool nuget:?package=jjm.one.Serilog.Sinks.SlackWebHook&version=X.Y.Z``` | ## Dependencies @@ -120,7 +125,8 @@ Log.Logger = new LoggerConfiguration() ## Full Documentation -The full documentation for this package can be found [here](https://jjm-one.github.io/jjm.one.Serilog.Sinks.SlackWebHook/main/doc/html/index.html). +The full documentation for this package can be +found [here](https://jjm-one.github.io/jjm.one.Serilog.Sinks.SlackWebHook/main/doc/html/index.html). ## Repo diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/SlackSinkExample.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/SlackSinkExample.cs index 908e0ec..a07709a 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/SlackSinkExample.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/SlackSinkExample.cs @@ -1,88 +1,97 @@ -using Serilog; +using System; +using System.Threading; +using Serilog; using Serilog.Core; using Serilog.Events; -using System; -namespace jjm.one.Serilog.Sinks.SlackWebHook.Example +namespace jjm.one.Serilog.Sinks.SlackWebHook.Example; + +/// +/// This class contains examples on how to use the library. +/// +public static class SlackSinkExample { - public static class SlackSinkExample + /// + /// The main function of the class. + /// + /// + /// + public static void Main() { - public static void Main() + string? slackChannel = null; + + Console.WriteLine( + "####################################################################################################"); + Console.WriteLine("Serilog Slack Sink Example (ver. " + typeof(SlackSinkExample).Assembly.GetName().Version + + ")"); + Console.WriteLine( + "####################################################################################################"); + Console.WriteLine(); + + Console.Write("Slack WebHook Url: "); + var input = Console.ReadLine(); + if (string.IsNullOrEmpty(input)) throw new ArgumentException("No valid WebHook Url!"); + var slackWebHookUrl = input; + Console.WriteLine(); + + Console.Write("Slack Channel (optional): "); + input = Console.ReadLine(); + if (!string.IsNullOrEmpty(input)) slackChannel = input; + Console.WriteLine(); + + Console.Write("Slack Username (optional): "); + input = Console.ReadLine(); + var slackUsername = string.IsNullOrEmpty(input) ? input : "Serilog Slack Sink Example"; + Console.WriteLine(); + + Console.Write("Slack User Icon (optional): "); + input = Console.ReadLine(); + var slackUserIcon = string.IsNullOrEmpty(input) ? input : ":monkey_face:"; + Console.WriteLine(); + + var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose); + + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Verbose() + .WriteTo.Slack( + slackWebHookUrl, + slackChannel, + slackUsername, + slackUserIcon, + periodicBatchingSinkOptionsBatchSizeLimit: 1, + periodicBatchingSinkOptionsPeriod: TimeSpan.FromMilliseconds(10), + periodicBatchingSinkOptionsQueueLimit: 100, + sinkRestrictedToMinimumLevel: LogEventLevel.Verbose, + sinkOutputTemplate: "{Message}", + sinkLevelSwitch: levelSwitch + ) + .CreateLogger(); + + Log.Write(LogEventLevel.Verbose, "Verbose Logging Message"); + Log.Write(LogEventLevel.Debug, "Debug Logging Message"); + Log.Write(LogEventLevel.Information, "Information Logging Message"); + Log.Write(LogEventLevel.Warning, "Warning Logging Message"); + Log.Write(LogEventLevel.Error, "Error Logging Message"); + Log.Write(LogEventLevel.Fatal, "Fatal Logging Message"); + + try + { + throw new Exception("TEST EXCEPTION!"); + } + catch (Exception e) { - string slackChannel = null; - - Console.WriteLine("####################################################################################################"); - Console.WriteLine("Serilog Slack Sink Example (ver. " + typeof(SlackSinkExample).Assembly.GetName().Version + ")"); - Console.WriteLine("####################################################################################################"); - Console.WriteLine(); - - Console.Write("Slack WebHook Url: "); - var input = Console.ReadLine(); - if (string.IsNullOrEmpty(input)) throw new ArgumentException("No valid WebHook Url!"); - var slackWebHookUrl = input; - Console.WriteLine(); - - Console.Write("Slack Channel (optional): "); - input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input)) slackChannel = input; - Console.WriteLine(); - - Console.Write("Slack Username (optional): "); - input = Console.ReadLine(); - var slackUsername = string.IsNullOrEmpty(input) ? input : "Serilog Slack Sink Example"; - Console.WriteLine(); - - Console.Write("Slack User Icon (optional): "); - input = Console.ReadLine(); - var slackUserIcon = string.IsNullOrEmpty(input) ? input : ":monkey_face:"; - Console.WriteLine(); - - var levelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Verbose); - - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Verbose() - .WriteTo.Slack( - slackWebHookUrl: slackWebHookUrl, - slackChannel: slackChannel, - slackUsername: slackUsername, - slackEmojiIcon: slackUserIcon, - - periodicBatchingSinkOptionsBatchSizeLimit: 1, - periodicBatchingSinkOptionsPeriod: TimeSpan.FromMilliseconds(10), - periodicBatchingSinkOptionsQueueLimit: 100, - - sinkRestrictedToMinimumLevel: LogEventLevel.Verbose, - sinkOutputTemplate: "{Message}", - sinkLevelSwitch: levelSwitch - ) - .CreateLogger(); - - Log.Write(LogEventLevel.Verbose, "Verbose Logging Message"); - Log.Write(LogEventLevel.Debug, "Debug Logging Message"); - Log.Write(LogEventLevel.Information, "Information Logging Message"); - Log.Write(LogEventLevel.Warning, "Warning Logging Message"); - Log.Write(LogEventLevel.Error, "Error Logging Message"); - Log.Write(LogEventLevel.Fatal, "Fatal Logging Message"); - - try - { - throw new Exception("TEST EXCEPTION!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Fatal, e, "Fatal Logging Message with exception"); - } - - levelSwitch.MinimumLevel = LogEventLevel.Fatal; - - Log.Write(LogEventLevel.Error, "This Message shouldn't be send to Slack!"); - - System.Threading.Thread.Sleep(10000); - - Console.WriteLine("Press any key to finish..."); - Console.ReadKey(); - - Environment.Exit(0); + Log.Write(LogEventLevel.Fatal, e, "Fatal Logging Message with exception"); } + + levelSwitch.MinimumLevel = LogEventLevel.Fatal; + + Log.Write(LogEventLevel.Error, "This Message shouldn't be send to Slack!"); + + Thread.Sleep(10000); + + Console.WriteLine("Press any key to finish..."); + Console.ReadKey(); + + Environment.Exit(0); } -} +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.MiscUtilFunctions.Tests.xml b/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.MiscUtilFunctions.Tests.xml index 2e5c556..9f02b12 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.MiscUtilFunctions.Tests.xml +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.MiscUtilFunctions.Tests.xml @@ -4,5 +4,17 @@ jjm.one.Serilog.Sinks.SlackWebHook.Example + + + This class contains examples on how to use the library. + + + + + The main function of the class. + + + + diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.Serilog.Sinks.SlackWebHook.Example.csproj b/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.Serilog.Sinks.SlackWebHook.Example.csproj index 0fabd8c..37193a6 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.Serilog.Sinks.SlackWebHook.Example.csproj +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Example/jjm.one.Serilog.Sinks.SlackWebHook.Example.csproj @@ -1,38 +1,37 @@ - - net7.0 - disable - enable - 2.0.2 - Jonas Merkle [JJM] - © by Jonas Merkle [JJM], 2023. - jm.one.Serilog.Sinks.SlackWebHook.Example - jm.one.Serilog.Sinks.SlackWebHook.Example - A basic Slack Sink for the Serilog framwork. (Example) - serilog, serilog-sink, slack, logging, csharp, example - https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook - git - https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook - false - false - + + net7.0 + disable + enable + 2.1.0 + Jonas Merkle [JJM] + © by Jonas Merkle [JJM], 2023. + jjm.one.Serilog.Sinks.SlackWebHook.Example + A basic Slack Sink for the Serilog framwork. (Example) + serilog, serilog-sink, slack, logging, csharp, example + https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook + git + https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook + false + false + - - latestmajor - ./jjm.one.MiscUtilFunctions.Tests.xml - - - latestmajor - ./jjm.one.MiscUtilFunctions.Tests.xml - + + latestmajor + ./jjm.one.MiscUtilFunctions.Tests.xml + + + latestmajor + ./jjm.one.MiscUtilFunctions.Tests.xml + - - - + + + - - - + + + diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackLoggerConfigurationExtensionsConstructorParameterTests.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackLoggerConfigurationExtensionsConstructorParameterTests.cs index ac85bf3..b69cbf2 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackLoggerConfigurationExtensionsConstructorParameterTests.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackLoggerConfigurationExtensionsConstructorParameterTests.cs @@ -1,439 +1,399 @@ -using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Net.Http; +using NUnit.Framework; using Serilog; using Serilog.Events; using Slack.Webhooks; -using System; -using System.Collections.Generic; -using System.Net.Http; -namespace jjm.one.Serilog.Sinks.SlackWebHook.Tests +namespace jjm.one.Serilog.Sinks.SlackWebHook.Tests; + +[TestFixture] +public class SlackLoggerConfigurationExtensionsConstructorParameterTests { - [TestFixture] - public class SlackLoggerConfigurationExtensionsConstructorParameterTests + [SetUp] + public void SetUp() { - #region const - - public const string ValidWebHook = @"https://slack.com/api/api.test"; + } - #endregion + public const string ValidWebHook = @"https://slack.com/api/api.test"; - #region setup + [Test] + public void SingleChannel_ConstructorTest_WebHookUrlNull() + { + Assert.Throws(() => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + null, + slackChannel: null + ) + .CreateLogger(); + }); + } - [SetUp] - public void SetUp() + [Test] + public void SingleChannel_ConstructorTest_WebHookUrlEmpty() + { + Assert.Throws(() => { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + "", + slackChannel: null + ) + .CreateLogger(); + }); + } - } + [Test] + public void SingleChannel_ConstructorTest_WebHookUrlValid() + { + Assert.DoesNotThrow(() => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null + ) + .CreateLogger(); + }); + } - #endregion + [Test] + public void MultiChannel_ConstructorTest_WebHookUrlNull() + { + Assert.Throws(() => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + null, + slackChannel: null + ) + .CreateLogger(); + }); + } - #region WebHookUrl test + [Test] + public void MultiChannel_ConstructorTest_WebHookUrlEmpty() + { + Assert.Throws(() => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + "", + slackChannels: null + ) + .CreateLogger(); + }); + } - [Test] - public void SingleChannel_ConstructorTest_WebHookUrlNull() + [Test] + public void MultiChannel_ConstructorTest_WebHookUrlValid() + { + Assert.DoesNotThrow(() => { - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: null, - slackChannel: null - ) - .CreateLogger(); - }); - } - - [Test] - public void SingleChannel_ConstructorTest_WebHookUrlEmpty() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null + ) + .CreateLogger(); + }); + } + + [Test] + public void SingleChannel_ConstructorTest_SlackParseObjCast() + { + Assert.Throws(() => { - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: "", - slackChannel: null - ) - .CreateLogger(); - }); - } - - [Test] - public void SingleChannel_ConstructorTest_WebHookUrlValid() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackParseObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_WebHookUrlNull() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackParseObj: ParseMode.None + ) + .CreateLogger(); + }); + } + + [Test] + public void MultiChannel_ConstructorTest_SlackParseObjCast() + { + Assert.Throws(() => { - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: null, - slackChannel: null - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_WebHookUrlEmpty() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackParseObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: "", - slackChannels: null - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_WebHookUrlValid() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackParseObj: ParseMode.None + ) + .CreateLogger(); + }); + } + + [Test] + public void SingleChannel_ConstructorTest_SlackAttachmentColorsObjCast() + { + Assert.Throws(() => { - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null - ) - .CreateLogger(); - }); - } - - #endregion - - #region slackParseObj cast test - - [Test] - public void SingleChannel_ConstructorTest_SlackParseObjCast() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackAttachmentColorsObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackAttachmentColorsObj: new Dictionary + { + { LogEventLevel.Verbose, "" } + } + ) + .CreateLogger(); + }); + } - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackParseObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackParseObj: ParseMode.None - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_SlackParseObjCast() + [Test] + public void MultiChannel_ConstructorTest_SlackAttachmentColorsObjCast() + { + Assert.Throws(() => { - - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackParseObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackParseObj: ParseMode.None - ) - .CreateLogger(); - }); - } - - #endregion - - #region slackAttachmentColorsObj cast test - - [Test] - public void SingleChannel_ConstructorTest_SlackAttachmentColorsObjCast() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackAttachmentColorsObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackAttachmentColorsObj: new Dictionary + { + { LogEventLevel.Verbose, "" } + } + ) + .CreateLogger(); + }); + } - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackAttachmentColorsObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackAttachmentColorsObj: new Dictionary() - { - {LogEventLevel.Verbose, ""}, - } - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_SlackAttachmentColorsObjCast() + [Test] + public void SingleChannel_ConstructorTest_SlackAttachmentFooterIconObjCast() + { + Assert.Throws(() => { - - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackAttachmentColorsObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackAttachmentColorsObj: new Dictionary() - { - {LogEventLevel.Verbose, ""}, - } - ) - .CreateLogger(); - }); - } - - #endregion - - #region slackAttachmentFooterIconObj cast test - - [Test] - public void SingleChannel_ConstructorTest_SlackAttachmentFooterIconObjCast() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackAttachmentFooterIconObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackAttachmentFooterIconObj: new Dictionary + { + { LogEventLevel.Verbose, "" } + } + ) + .CreateLogger(); + }); + } - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackAttachmentFooterIconObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackAttachmentFooterIconObj: new Dictionary() - { - {LogEventLevel.Verbose, ""}, - } - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_SlackAttachmentFooterIconObjCast() + [Test] + public void MultiChannel_ConstructorTest_SlackAttachmentFooterIconObjCast() + { + Assert.Throws(() => { - - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackAttachmentFooterIconObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackAttachmentFooterIconObj: new Dictionary() - { - {LogEventLevel.Verbose, ""}, - } - ) - .CreateLogger(); - }); - } - - #endregion - - #region slackHttpClientObj cast test - - [Test] - public void SingleChannel_ConstructorTest_SlackHttpClientObjCast() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackAttachmentFooterIconObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackAttachmentFooterIconObj: new Dictionary + { + { LogEventLevel.Verbose, "" } + } + ) + .CreateLogger(); + }); + } - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackHttpClientObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - slackHttpClientObj: new HttpClient() - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_SlackHttpClientObjCast() + [Test] + public void SingleChannel_ConstructorTest_SlackHttpClientObjCast() + { + Assert.Throws(() => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackHttpClientObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + slackHttpClientObj: new HttpClient() + ) + .CreateLogger(); + }); + } - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackHttpClientObj: "TestObject" - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - slackHttpClientObj: new HttpClient() - ) - .CreateLogger(); - }); - } - - #endregion - - #region generateSlackFunctions cast test - - private static string TestF1(LogEvent a, IFormatProvider b, object c) + [Test] + public void MultiChannel_ConstructorTest_SlackHttpClientObjCast() + { + Assert.Throws(() => { - return null; - } - private static List TestF2(LogEvent a, IFormatProvider b, object c) + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackHttpClientObj: "TestObject" + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { - return null; - } - private static List TestF3(LogEvent a, IFormatProvider b, object c) + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + slackHttpClientObj: new HttpClient() + ) + .CreateLogger(); + }); + } + + private static string? TestF1(LogEvent a, IFormatProvider b, object c) + { + return null; + } + + private static List? TestF2(LogEvent a, IFormatProvider b, object c) + { + return null; + } + + private static List? TestF3(LogEvent a, IFormatProvider b, object c) + { + return null; + } + + [Test] + public void SingleChannel_ConstructorTest_GenerateSlackFunctionsCast() + { + var f1 = TestF1; + var f2 = TestF2; + var f3 = TestF3; + + Assert.Throws(() => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + generateSlackFunctions: new Tuple("", "", "") + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { - return null; - } + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + generateSlackFunctions: new Tuple(f1, f2, f3) + ) + .CreateLogger(); + }); + } + + [Test] + public void MultiChannel_ConstructorTest_GenerateSlackFunctionsCast() + { + var f1 = TestF1; + var f2 = TestF2; + var f3 = TestF3; - [Test] - public void SingleChannel_ConstructorTest_GenerateSlackFunctionsCast() + Assert.Throws(() => { - Func f1 = TestF1; - Func> f2 = TestF2; - Func> f3 = TestF3; - - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - generateSlackFunctions: new Tuple("", "", "") - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - generateSlackFunctions: new Tuple(f1, f2, f3) - ) - .CreateLogger(); - }); - } - - [Test] - public void MultiChannel_ConstructorTest_GenerateSlackFunctionsCast() + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + generateSlackFunctions: new Tuple("", "", "") + ) + .CreateLogger(); + }); + + Assert.DoesNotThrow(() => { - Func f1 = TestF1; - Func> f2 = TestF2; - Func> f3 = TestF3; - - Assert.Throws(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - generateSlackFunctions: new Tuple("", "", "") - ) - .CreateLogger(); - }); - - Assert.DoesNotThrow(() => - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannels: null, - generateSlackFunctions: new Tuple(f1, f2, f3) - ) - .CreateLogger(); - }); - } - - #endregion + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannels: null, + generateSlackFunctions: new Tuple(f1, f2, f3) + ) + .CreateLogger(); + }); } -} +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkLoggerTests.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkLoggerTests.cs index b944c63..521a529 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkLoggerTests.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkLoggerTests.cs @@ -1,152 +1,134 @@ -using NUnit.Framework; +using System; +using System.Threading; +using NUnit.Framework; using Serilog; using Serilog.Events; -using System; -namespace jjm.one.Serilog.Sinks.SlackWebHook.Tests +namespace jjm.one.Serilog.Sinks.SlackWebHook.Tests; + +[TestFixture] +public class SlackSinkLoggerTests { - [TestFixture] - public class SlackSinkLoggerTests + [SetUp] + public void SetUp() { - #region const - - public const string ValidWebHook = @"https://slack.com/api/api.test"; - - #endregion - - #region setup - - [SetUp] - public void SetUp() - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Slack( - slackWebHookUrl: ValidWebHook, - slackChannel: null, - periodicBatchingSinkOptionsBatchSizeLimit: 1, - periodicBatchingSinkOptionsPeriod: TimeSpan.FromTicks(1) - ) - .CreateLogger(); - } - - #endregion + Log.Logger = new LoggerConfiguration() + .WriteTo.Slack( + ValidWebHook, + slackChannel: null, + periodicBatchingSinkOptionsBatchSizeLimit: 1, + periodicBatchingSinkOptionsPeriod: TimeSpan.FromTicks(1) + ) + .CreateLogger(); + } - #region Logger test + public const string ValidWebHook = @"https://slack.com/api/api.test"; - [Test] - public void SingleChannel_LoggerTests_LogVerbose() + [Test] + public void SingleChannel_LoggerTests_LogVerbose() + { + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => + try { - try - { - throw new Exception("Test Exception!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Verbose, e, "Verbose Log Message"); - } - - System.Threading.Thread.Sleep(500); + throw new Exception("Test Exception!"); + } + catch (Exception e) + { + Log.Write(LogEventLevel.Verbose, e, "Verbose Log Message"); + } - }); - } + Thread.Sleep(500); + }); + } - [Test] - public void SingleChannel_LoggerTests_LogDebug() + [Test] + public void SingleChannel_LoggerTests_LogDebug() + { + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => + try { - try - { - throw new Exception("Test Exception!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Debug, e, "Debug Log Message"); - } - - System.Threading.Thread.Sleep(500); + throw new Exception("Test Exception!"); + } + catch (Exception e) + { + Log.Write(LogEventLevel.Debug, e, "Debug Log Message"); + } - }); - } + Thread.Sleep(500); + }); + } - [Test] - public void SingleChannel_LoggerTests_LogInformation() + [Test] + public void SingleChannel_LoggerTests_LogInformation() + { + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => + try { - try - { - throw new Exception("Test Exception!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Information, e, "Information Log Message"); - } - - System.Threading.Thread.Sleep(500); + throw new Exception("Test Exception!"); + } + catch (Exception e) + { + Log.Write(LogEventLevel.Information, e, "Information Log Message"); + } - }); - } + Thread.Sleep(500); + }); + } - [Test] - public void SingleChannel_LoggerTests_LogWarning() + [Test] + public void SingleChannel_LoggerTests_LogWarning() + { + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => + try { - try - { - throw new Exception("Test Exception!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Warning, e, "Warning Log Message"); - } - - System.Threading.Thread.Sleep(500); + throw new Exception("Test Exception!"); + } + catch (Exception e) + { + Log.Write(LogEventLevel.Warning, e, "Warning Log Message"); + } - }); - } + Thread.Sleep(500); + }); + } - [Test] - public void SingleChannel_LoggerTests_LogError() + [Test] + public void SingleChannel_LoggerTests_LogError() + { + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => + try { - try - { - throw new Exception("Test Exception!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Error, e, "Error Log Message"); - } - - System.Threading.Thread.Sleep(500); + throw new Exception("Test Exception!"); + } + catch (Exception e) + { + Log.Write(LogEventLevel.Error, e, "Error Log Message"); + } - }); - } + Thread.Sleep(500); + }); + } - [Test] - public void SingleChannel_LoggerTests_LogFatal() + [Test] + public void SingleChannel_LoggerTests_LogFatal() + { + Assert.DoesNotThrow(() => { - Assert.DoesNotThrow(() => + try { - try - { - throw new Exception("Test Exception!"); - } - catch (Exception e) - { - Log.Write(LogEventLevel.Fatal, e, "Fatal Log Message"); - } - - System.Threading.Thread.Sleep(500); - - }); - } + throw new Exception("Test Exception!"); + } + catch (Exception e) + { + Log.Write(LogEventLevel.Fatal, e, "Fatal Log Message"); + } - #endregion + Thread.Sleep(500); + }); } -} +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkOptionsTests.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkOptionsTests.cs index 05853bc..441e1c3 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkOptionsTests.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/SlackSinkOptionsTests.cs @@ -1,36 +1,26 @@ -using NUnit.Framework; -using System; +using System; +using NUnit.Framework; -namespace jjm.one.Serilog.Sinks.SlackWebHook.Tests +namespace jjm.one.Serilog.Sinks.SlackWebHook.Tests; + +[TestFixture] +public class SlackSinkOptionsTests { - [TestFixture] - public class SlackSinkOptionsTests + [SetUp] + public void SetUp() { - #region setup - - [SetUp] - public void SetUp() - { - - } - - #endregion - - #region init tests - - [Test] - public void DefaultConstructorTest() - { - var options = new SlackSinkOptions(); + } - Assert.IsTrue(options.SlackAttachmentColors.Count == 6); - Assert.IsTrue(options.SlackAttachmentFooterIcon.Count == 6); + [Test] + public void DefaultConstructorTest() + { + var options = new SlackSinkOptions(); - Assert.IsTrue(options.PeriodicBatchingSinkOptionsBatchSizeLimit >= 0); - Assert.IsTrue(!options.PeriodicBatchingSinkOptionsPeriod.Equals(TimeSpan.Zero)); - Assert.IsTrue(options.PeriodicBatchingSinkOptionsQueueLimit >= 0); - } + Assert.IsTrue(options.SlackAttachmentColors.Count == 6); + Assert.IsTrue(options.SlackAttachmentFooterIcon.Count == 6); - #endregion + Assert.IsTrue(options.PeriodicBatchingSinkOptionsBatchSizeLimit >= 0); + Assert.IsTrue(!options.PeriodicBatchingSinkOptionsPeriod.Equals(TimeSpan.Zero)); + Assert.IsTrue(options.PeriodicBatchingSinkOptionsQueueLimit >= 0); } -} +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/jjm.one.Serilog.Sinks.SlackWebHook.Tests.csproj b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/jjm.one.Serilog.Sinks.SlackWebHook.Tests.csproj index 140abb9..53b3ba8 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/jjm.one.Serilog.Sinks.SlackWebHook.Tests.csproj +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook.Tests/jjm.one.Serilog.Sinks.SlackWebHook.Tests.csproj @@ -1,45 +1,44 @@ - - net7.0 - disable - enable - 2.0.2 - Jonas Merkle [JJM] - © by Jonas Merkle [JJM], 2023. - jm.one.Serilog.Sinks.SlackWebHook.Tests - jm.one.Serilog.Sinks.SlackWebHook.Tests - A basic Slack Sink for the Serilog framwork. (Unit-Tests) - serilog, serilog-sink, slack, logging, csharp, unit-tests - https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook - git - https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook - false - true - + + net7.0 + disable + enable + 2.1.0 + Jonas Merkle [JJM] + © by Jonas Merkle [JJM], 2023. + jjm.one.Serilog.Sinks.SlackWebHook.Tests + A basic Slack Sink for the Serilog framwork. (Unit-Tests) + serilog, serilog-sink, slack, logging, csharp, unit-tests + https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook + git + https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook + false + true + - - latestmajor - ./jjm.one.MiscUtilFunctions.Tests.xml - - - latestmajor - ./jjm.one.MiscUtilFunctions.Tests.xml - + + latestmajor + ./jjm.one.MiscUtilFunctions.Tests.xml + + + latestmajor + ./jjm.one.MiscUtilFunctions.Tests.xml + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + - - - + + + diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackLoggerConfigurationExtensions.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackLoggerConfigurationExtensions.cs index fc9767c..b3e59d0 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackLoggerConfigurationExtensions.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackLoggerConfigurationExtensions.cs @@ -1,362 +1,454 @@ -using Serilog; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Net.Http; +using Serilog; using Serilog.Configuration; using Serilog.Core; using Serilog.Events; using Slack.Webhooks; -using System; -using System.Collections.Generic; -using System.Net.Http; -namespace jjm.one.Serilog.Sinks.SlackWebHook +namespace jjm.one.Serilog.Sinks.SlackWebHook; + +/// +/// This class contains the extenstion functions to add the Slack logger configuration to a existing logger +/// configuration. +/// +[SuppressMessage("ReSharper", "InconsistentNaming")] +public static class SlackLoggerConfigurationExtensions { - public static class SlackLoggerConfigurationExtensions + #region private constructors + + /// + /// extension that provides configuration chaining. + /// + /// Instance of object. + /// Slack WebHook URL. + /// Slack username (recommended). + /// Slack user-icon emoji string (optional). + /// Slack user-icon image URI (optional). + /// + /// A containing the name of all Slack channels in which the log + /// message should be posted (recommended). + /// + /// Slack message option 'DeleteOriginal' (optional). + /// Slack message option 'LinkNames' (optional). + /// Slack message option 'Markdown' (optional). + /// Slack message option 'Parse' as + /// Slack message option 'ReplaceOriginal' (optional). + /// Slack message option 'ResponseType' (optional). + /// Slack message option 'ThreadID' (optional). + /// + /// Slack message attachment color list as + /// (optional). + /// + /// + /// Slack message attachment footer icon list as + /// (optional). + /// + /// Add the short info attachment to the log message (optional). + /// Display the short info attachment in short form (optional). + /// Add the extended info attachment to the log message (optional). + /// Display the extended info attachment in short form (optional). + /// Add the short exception to the log message (optional). + /// Display the exception attachment in short form (optional). + /// Timeout for the connection to the Slack servers (optional). + /// The instance which the uses. + /// + /// A for message + /// text generation (optional). + /// + /// + /// A + /// message attachment list generation + /// (optional). + /// + /// + /// A for + /// message block list generation (optional). + /// + /// + /// Size of the batch of messages that get send at once to Slack + /// (recommended). + /// + /// Time period between sending of batches of messages (recommended). + /// + /// Maximum size of the queue that stores the messages before the + /// messages were send in batches to Slack (optional). + /// + /// + /// The absolute minimum a log message must have to + /// be send to Slack (optional). + /// + /// The template for the output format of the log messages (optional). + /// + /// A to change the minimum a + /// log message must have to be send to Slack (optional). + /// + /// A format provider (optional). + /// A Switch to change the activation status of the sink on the fly (optional). + /// Instance of object. + private static LoggerConfiguration Slack( + this LoggerSinkConfiguration loggerSinkConfiguration, + + // slack options + string slackWebHookUrl, + string? slackUsername = null, + string? slackEmojiIcon = null, + Uri? slackUriIcon = null, + List? slackChannels = null, + bool? slackDeleteOriginal = null, + bool? slackLinkNames = null, + bool? slackMarkdown = null, + ParseMode? slackParse = null, + bool? slackReplaceOriginal = null, + string? slackResponseType = null, + string? slackThreadId = null, + IDictionary? slackAttachmentColors = null, + IDictionary? slackAttachmentFooterIcon = null, + bool? slackAddShortInfoAttachment = null, + bool? slackDisplayShortInfoAttachmentShort = null, + bool? slackAddExtendedInfoAttachment = null, + bool? slackDisplayExtendedInfoAttachmentShort = null, + bool? slackAddExceptionAttachment = null, + bool? slackDisplayExceptionAttachmentShort = null, + int? slackConnectionTimeout = null, + HttpClient? slackHttpClient = null, + Func? generateSlackMessageText = null, + Func?>? generateSlackMessageAttachments = null, + Func?>? generateSlackMessageBlocks = null, + + // periodic batch sink options + int? periodicBatchingSinkOptionsBatchSizeLimit = null, + TimeSpan? periodicBatchingSinkOptionsPeriod = null, + int? periodicBatchingSinkOptionsQueueLimit = null, + + // sink options + LogEventLevel? sinkRestrictedToMinimumLevel = null, + string? sinkOutputTemplate = null, + LoggingLevelSwitch? sinkLevelSwitch = null, + IFormatProvider? sinkFormatProvider = null, + SlackSinkActivationSwitch? sinkActivationSwitch = null + ) { - #region public constructors - - /// - /// extension that provides configuration chaining. - /// - /// Instance of object. - /// Slack WebHook URL (required). - /// Name of the Slack channel in which the log message should be posted (recommended). - /// Slack username (recommended). - /// Slack user-icon emoji string (recommended). - /// Slack user-icon image URI (optional). - /// Slack message option 'DeleteOriginal' (optional). - /// Slack message option 'LinkNames' (optional). - /// Slack message option 'Markdown' (optional). - /// Slack message option 'Parse' as - /// Slack message option 'ReplaceOriginal' (optional). - /// Slack message option 'ResponseType' (optional). - /// Slack message option 'ThreadID' (optional). - /// Slack message attachment color list as (optional). - /// Slack message attachment footer icon list as (optional). - /// Add the short info attachment to the log message (optional). - /// Display the short info attachment in short form (optional). - /// Add the extended info attachment to the log message (optional). - /// Display the extended info attachment in short form (optional). - /// Add the short exception to the log message (optional). - /// Display the exception attachment in short form (optional). - /// Timeout for the connection to the Slack servers (optional). - /// The instance which the uses. - /// A containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 for message block list generation] for the Slack message generation (optional). - /// Size of the batch of messages that get send at once to Slack (recommended). - /// Time period between sending of batches of messages (recommended). - /// Maximum size of the queue that stores the messages before the messages were send in batches to Slack (optional). - /// The absolute minimum a log message must have to be send to Slack (optional). - /// The template for the output format of the log messages (optional). - /// A to change the minimum a log message must have to be send to Slack (optional). - /// A format provider (optional). - /// A Switch to change the activation status of the sink on the fly (optional). - /// Instance of object. - public static LoggerConfiguration Slack( - this LoggerSinkConfiguration loggerSinkConfiguration, - - // slack options - string slackWebHookUrl, - string slackChannel, - string slackUsername = null, - string slackEmojiIcon = null, - Uri slackUriIcon = null, - bool? slackDeleteOriginal = null, - bool? slackLinkNames = null, - bool? slackMarkdown = null, - object slackParseObj = null, - bool? slackReplaceOriginal = null, - string slackResponseType = null, - string slackThreadId = null, - - object slackAttachmentColorsObj = null, - object slackAttachmentFooterIconObj = null, - bool? slackAddShortInfoAttachment = null, - bool? slackDisplayShortInfoAttachmentShort = null, - bool? slackAddExtendedInfoAttachment = null, - bool? slackDisplayExtendedInfoAttachmentShort = null, - bool? slackAddExceptionAttachment = null, - bool? slackDisplayExceptionAttachmentShort = null, - - int? slackConnectionTimeout = null, - object slackHttpClientObj = null, - - Tuple generateSlackFunctions = null, - - // periodic batch sink options - int? periodicBatchingSinkOptionsBatchSizeLimit = null, - TimeSpan? periodicBatchingSinkOptionsPeriod = null, - int? periodicBatchingSinkOptionsQueueLimit = null, + if (slackWebHookUrl == null) + throw new ArgumentNullException(nameof(slackWebHookUrl), "The Slack WebHook can't be null!"); + if (string.IsNullOrEmpty(slackWebHookUrl)) + throw new ArgumentException("The Slack WebHook can't be empty!", nameof(slackWebHookUrl)); - // sink options - LogEventLevel? sinkRestrictedToMinimumLevel = null, - string sinkOutputTemplate = null, - LoggingLevelSwitch sinkLevelSwitch = null, - IFormatProvider sinkFormatProvider = null, - SlackSinkActivationSwitch sinkActivationSwitch = null - ) + var slackSinkOptions = new SlackSinkOptions { - return Slack(loggerSinkConfiguration, slackWebHookUrl, slackUsername, slackEmojiIcon, slackUriIcon, - string.IsNullOrEmpty(slackChannel) ? null : new List { slackChannel }, slackDeleteOriginal, - slackLinkNames, slackMarkdown, slackParseObj, slackReplaceOriginal, - slackResponseType, slackThreadId, slackAttachmentColorsObj, slackAttachmentFooterIconObj, - slackAddShortInfoAttachment, slackDisplayShortInfoAttachmentShort, slackAddExtendedInfoAttachment, - slackDisplayExtendedInfoAttachmentShort, slackAddExceptionAttachment, - slackDisplayExceptionAttachmentShort, slackConnectionTimeout, slackHttpClientObj, generateSlackFunctions, periodicBatchingSinkOptionsBatchSizeLimit, - periodicBatchingSinkOptionsPeriod, periodicBatchingSinkOptionsQueueLimit, sinkRestrictedToMinimumLevel, - sinkOutputTemplate, sinkLevelSwitch, sinkFormatProvider, sinkActivationSwitch); - } - - /// - /// extension that provides configuration chaining. - /// - /// Instance of object. - /// Slack WebHook URL. - /// Slack username (recommended). - /// Slack user-icon emoji string (optional). - /// Slack user-icon image URI (optional). - /// A containing the name of all Slack channels in which the log message should be posted (recommended). - /// Slack message option 'DeleteOriginal' (optional). - /// Slack message option 'LinkNames' (optional). - /// Slack message option 'Markdown' (optional). - /// Slack message option 'Parse' as - /// Slack message option 'ReplaceOriginal' (optional). - /// Slack message option 'ResponseType' (optional). - /// Slack message option 'ThreadID' (optional). - /// Slack message attachment color list as (optional). - /// Slack message attachment footer icon list as (optional). - /// Add the short info attachment to the log message (optional). - /// Display the short info attachment in short form (optional). - /// Add the extended info attachment to the log message (optional). - /// Display the extended info attachment in short form (optional). - /// Add the short exception to the log message (optional). - /// Display the exception attachment in short form (optional). - /// Timeout for the connection to the Slack servers (optional). - /// The instance which the uses. - /// A containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 for message block list generation] for the Slack message generation (optional). - /// Size of the batch of messages that get send at once to Slack (recommended). - /// Time period between sending of batches of messages (recommended). - /// Maximum size of the queue that stores the messages before the messages were send in batches to Slack (optional). - /// The absolute minimum a log message must have to be send to Slack (optional). - /// The template for the output format of the log messages (optional). - /// A to change the minimum a log message must have to be send to Slack (optional). - /// A format provider (optional). - /// A Switch to change the activation status of the sink on the fly (optional). - /// Instance of object. - public static LoggerConfiguration Slack( - this LoggerSinkConfiguration loggerSinkConfiguration, - - // slack options - string slackWebHookUrl, - string slackUsername = null, - string slackEmojiIcon = null, - Uri slackUriIcon = null, - List slackChannels = null, - bool? slackDeleteOriginal = null, - bool? slackLinkNames = null, - bool? slackMarkdown = null, - object slackParseObj = null, - bool? slackReplaceOriginal = null, - string slackResponseType = null, - string slackThreadId = null, - - object slackAttachmentColorsObj = null, - object slackAttachmentFooterIconObj = null, - bool? slackAddShortInfoAttachment = null, - bool? slackDisplayShortInfoAttachmentShort = null, - bool? slackAddExtendedInfoAttachment = null, - bool? slackDisplayExtendedInfoAttachmentShort = null, - bool? slackAddExceptionAttachment = null, - bool? slackDisplayExceptionAttachmentShort = null, - - int? slackConnectionTimeout = null, - object slackHttpClientObj = null, - - Tuple generateSlackFunctions = null, - - // periodic batch sink options - int? periodicBatchingSinkOptionsBatchSizeLimit = null, - TimeSpan? periodicBatchingSinkOptionsPeriod = null, - int? periodicBatchingSinkOptionsQueueLimit = null, - - // sink options - LogEventLevel? sinkRestrictedToMinimumLevel = null, - string sinkOutputTemplate = null, - LoggingLevelSwitch sinkLevelSwitch = null, - IFormatProvider sinkFormatProvider = null, - SlackSinkActivationSwitch sinkActivationSwitch = null - ) - { - ParseMode? slackParse = null; - if (slackParseObj != null) slackParse = (ParseMode)slackParseObj; - - IDictionary slackAttachmentColors = null; - if (slackAttachmentColorsObj != null) slackAttachmentColors = (IDictionary)slackAttachmentColorsObj; - - IDictionary slackAttachmentFooterIcon = null; - if (slackAttachmentFooterIconObj != null) slackAttachmentFooterIcon = (IDictionary)slackAttachmentFooterIconObj; - - HttpClient slackHttpClient = null; - if (slackHttpClientObj != null) slackHttpClient = (HttpClient)slackHttpClientObj; - - Func generateSlackMessageText = null; - Func> generateSlackMessageAttachments = null; - Func> generateSlackMessageBlocks = null; - - if (generateSlackFunctions != null) - { - if (generateSlackFunctions.Item1 != null) - generateSlackMessageText = - (Func)generateSlackFunctions.Item1; - if (generateSlackFunctions.Item2 != null) - generateSlackMessageAttachments = - (Func>)generateSlackFunctions.Item2; - if (generateSlackFunctions.Item3 != null) - generateSlackMessageBlocks = - (Func>)generateSlackFunctions.Item3; - } - - return Slack(loggerSinkConfiguration, slackWebHookUrl, slackUsername, slackEmojiIcon, slackUriIcon, - slackChannels, slackDeleteOriginal, slackLinkNames, slackMarkdown, slackParse, slackReplaceOriginal, - slackResponseType, slackThreadId, slackAttachmentColors, slackAttachmentFooterIcon, - slackAddShortInfoAttachment, slackDisplayShortInfoAttachmentShort, slackAddExtendedInfoAttachment, - slackDisplayExtendedInfoAttachmentShort, slackAddExceptionAttachment, - slackDisplayExceptionAttachmentShort, slackConnectionTimeout, slackHttpClient, generateSlackMessageText, - generateSlackMessageAttachments, generateSlackMessageBlocks, periodicBatchingSinkOptionsBatchSizeLimit, - periodicBatchingSinkOptionsPeriod, periodicBatchingSinkOptionsQueueLimit, sinkRestrictedToMinimumLevel, - sinkOutputTemplate, sinkLevelSwitch, sinkFormatProvider, sinkActivationSwitch); - } - - #endregion - - #region private constructors + SlackWebHookUrl = slackWebHookUrl + }; + + if (slackUsername is not null) slackSinkOptions.SlackUsername = slackUsername; + if (slackEmojiIcon is not null) slackSinkOptions.SlackEmojiIcon = slackEmojiIcon; + if (slackUriIcon is not null) slackSinkOptions.SlackUriIcon = slackUriIcon; + if (slackChannels is not null) slackSinkOptions.SlackChannels = slackChannels; + + if (slackDeleteOriginal is not null) slackSinkOptions.SlackDeleteOriginal = (bool)slackDeleteOriginal; + if (slackLinkNames is not null) slackSinkOptions.SlackLinkNames = (bool)slackLinkNames; + if (slackMarkdown is not null) slackSinkOptions.SlackMarkdown = (bool)slackMarkdown; + if (slackParse is not null) slackSinkOptions.SlackParse = (ParseMode)slackParse; + if (slackReplaceOriginal is not null) slackSinkOptions.SlackReplaceOriginal = (bool)slackReplaceOriginal; + if (slackResponseType is not null) slackSinkOptions.SlackResponseType = slackResponseType; + if (slackThreadId is not null) slackSinkOptions.SlackThreadId = slackThreadId; + + if (slackAttachmentColors is not null) slackSinkOptions.SlackAttachmentColors = slackAttachmentColors; + if (slackAttachmentFooterIcon is not null) slackSinkOptions.SlackAttachmentFooterIcon = slackAttachmentFooterIcon; + if (slackAddShortInfoAttachment is not null) + slackSinkOptions.SlackAddShortInfoAttachment = (bool)slackAddShortInfoAttachment; + if (slackDisplayShortInfoAttachmentShort is not null) + slackSinkOptions.SlackDisplayShortInfoAttachmentShort = (bool)slackDisplayShortInfoAttachmentShort; + if (slackAddExtendedInfoAttachment is not null) + slackSinkOptions.SlackAddExtendedInfoAttachment = (bool)slackAddExtendedInfoAttachment; + if (slackDisplayExtendedInfoAttachmentShort is not null) + slackSinkOptions.SlackDisplayExtendedInfoAttachmentShort = (bool)slackDisplayExtendedInfoAttachmentShort; + if (slackAddExceptionAttachment is not null) + slackSinkOptions.SlackAddExceptionAttachment = (bool)slackAddExceptionAttachment; + if (slackDisplayExceptionAttachmentShort is not null) + slackSinkOptions.SlackDisplayExceptionAttachmentShort = (bool)slackDisplayExceptionAttachmentShort; + + if (slackConnectionTimeout is not null) slackSinkOptions.SlackConnectionTimeout = (int)slackConnectionTimeout; + + if (periodicBatchingSinkOptionsBatchSizeLimit is not null) + slackSinkOptions.PeriodicBatchingSinkOptionsBatchSizeLimit = (int)periodicBatchingSinkOptionsBatchSizeLimit; + if (periodicBatchingSinkOptionsPeriod is not null) + slackSinkOptions.PeriodicBatchingSinkOptionsPeriod = (TimeSpan)periodicBatchingSinkOptionsPeriod; + if (periodicBatchingSinkOptionsQueueLimit is not null) + slackSinkOptions.PeriodicBatchingSinkOptionsQueueLimit = (int)periodicBatchingSinkOptionsQueueLimit; + + if (sinkOutputTemplate is not null) slackSinkOptions.SinkOutputTemplate = sinkOutputTemplate; + + return loggerSinkConfiguration.Sink( + new SlackSink(slackSinkOptions, sinkFormatProvider, sinkActivationSwitch, slackHttpClient, + generateSlackMessageText, generateSlackMessageAttachments, generateSlackMessageBlocks), + sinkRestrictedToMinimumLevel ?? LevelAlias.Minimum, + sinkLevelSwitch); + } - /// - /// extension that provides configuration chaining. - /// - /// Instance of object. - /// Slack WebHook URL. - /// Slack username (recommended). - /// Slack user-icon emoji string (optional). - /// Slack user-icon image URI (optional). - /// A containing the name of all Slack channels in which the log message should be posted (recommended). - /// Slack message option 'DeleteOriginal' (optional). - /// Slack message option 'LinkNames' (optional). - /// Slack message option 'Markdown' (optional). - /// Slack message option 'Parse' as - /// Slack message option 'ReplaceOriginal' (optional). - /// Slack message option 'ResponseType' (optional). - /// Slack message option 'ThreadID' (optional). - /// Slack message attachment color list as (optional). - /// Slack message attachment footer icon list as (optional). - /// Add the short info attachment to the log message (optional). - /// Display the short info attachment in short form (optional). - /// Add the extended info attachment to the log message (optional). - /// Display the extended info attachment in short form (optional). - /// Add the short exception to the log message (optional). - /// Display the exception attachment in short form (optional). - /// Timeout for the connection to the Slack servers (optional). - /// The instance which the uses. - /// A for message text generation (optional). - /// A message attachment list generation (optional). - /// A for message block list generation (optional). - /// Size of the batch of messages that get send at once to Slack (recommended). - /// Time period between sending of batches of messages (recommended). - /// Maximum size of the queue that stores the messages before the messages were send in batches to Slack (optional). - /// The absolute minimum a log message must have to be send to Slack (optional). - /// The template for the output format of the log messages (optional). - /// A to change the minimum a log message must have to be send to Slack (optional). - /// A format provider (optional). - /// A Switch to change the activation status of the sink on the fly (optional). - /// Instance of object. - private static LoggerConfiguration Slack( - this LoggerSinkConfiguration loggerSinkConfiguration, + #endregion + + #region public constructors + + /// + /// extension that provides configuration chaining. + /// + /// Instance of object. + /// Slack WebHook URL (required). + /// Name of the Slack channel in which the log message should be posted (recommended). + /// Slack username (recommended). + /// Slack user-icon emoji string (recommended). + /// Slack user-icon image URI (optional). + /// Slack message option 'DeleteOriginal' (optional). + /// Slack message option 'LinkNames' (optional). + /// Slack message option 'Markdown' (optional). + /// Slack message option 'Parse' as + /// Slack message option 'ReplaceOriginal' (optional). + /// Slack message option 'ResponseType' (optional). + /// Slack message option 'ThreadID' (optional). + /// + /// Slack message attachment color list as + /// (optional). + /// + /// + /// Slack message attachment footer icon list as + /// (optional). + /// + /// Add the short info attachment to the log message (optional). + /// Display the short info attachment in short form (optional). + /// Add the extended info attachment to the log message (optional). + /// Display the extended info attachment in short form (optional). + /// Add the short exception to the log message (optional). + /// Display the exception attachment in short form (optional). + /// Timeout for the connection to the Slack servers (optional). + /// The instance which the uses. + /// + /// A + /// + /// containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 + /// for message block list generation] for the Slack message generation (optional). + /// + /// + /// Size of the batch of messages that get send at once to Slack + /// (recommended). + /// + /// Time period between sending of batches of messages (recommended). + /// + /// Maximum size of the queue that stores the messages before the + /// messages were send in batches to Slack (optional). + /// + /// + /// The absolute minimum a log message must have to + /// be send to Slack (optional). + /// + /// The template for the output format of the log messages (optional). + /// + /// A to change the minimum a + /// log message must have to be send to Slack (optional). + /// + /// A format provider (optional). + /// A Switch to change the activation status of the sink on the fly (optional). + /// Instance of object. + public static LoggerConfiguration Slack( + this LoggerSinkConfiguration loggerSinkConfiguration, + + // slack options + string slackWebHookUrl, + string? slackChannel, + string? slackUsername = null, + string? slackEmojiIcon = null, + Uri? slackUriIcon = null, + bool? slackDeleteOriginal = null, + bool? slackLinkNames = null, + bool? slackMarkdown = null, + object? slackParseObj = null, + bool? slackReplaceOriginal = null, + string? slackResponseType = null, + string? slackThreadId = null, + object? slackAttachmentColorsObj = null, + object? slackAttachmentFooterIconObj = null, + bool? slackAddShortInfoAttachment = null, + bool? slackDisplayShortInfoAttachmentShort = null, + bool? slackAddExtendedInfoAttachment = null, + bool? slackDisplayExtendedInfoAttachmentShort = null, + bool? slackAddExceptionAttachment = null, + bool? slackDisplayExceptionAttachmentShort = null, + int? slackConnectionTimeout = null, + object? slackHttpClientObj = null, + Tuple? generateSlackFunctions = null, + + // periodic batch sink options + int? periodicBatchingSinkOptionsBatchSizeLimit = null, + TimeSpan? periodicBatchingSinkOptionsPeriod = null, + int? periodicBatchingSinkOptionsQueueLimit = null, + + // sink options + LogEventLevel? sinkRestrictedToMinimumLevel = null, + string? sinkOutputTemplate = null, + LoggingLevelSwitch? sinkLevelSwitch = null, + IFormatProvider? sinkFormatProvider = null, + SlackSinkActivationSwitch? sinkActivationSwitch = null + ) + { + return Slack(loggerSinkConfiguration, slackWebHookUrl, slackUsername, slackEmojiIcon, slackUriIcon, + string.IsNullOrEmpty(slackChannel) ? null : new List { slackChannel }, slackDeleteOriginal, + slackLinkNames, slackMarkdown, slackParseObj, slackReplaceOriginal, + slackResponseType, slackThreadId, slackAttachmentColorsObj, slackAttachmentFooterIconObj, + slackAddShortInfoAttachment, slackDisplayShortInfoAttachmentShort, slackAddExtendedInfoAttachment, + slackDisplayExtendedInfoAttachmentShort, slackAddExceptionAttachment, + slackDisplayExceptionAttachmentShort, slackConnectionTimeout, slackHttpClientObj, generateSlackFunctions, + periodicBatchingSinkOptionsBatchSizeLimit, + periodicBatchingSinkOptionsPeriod, periodicBatchingSinkOptionsQueueLimit, sinkRestrictedToMinimumLevel, + sinkOutputTemplate, sinkLevelSwitch, sinkFormatProvider, sinkActivationSwitch); + } - // slack options - string slackWebHookUrl, - string slackUsername = null, - string slackEmojiIcon = null, - Uri slackUriIcon = null, - List slackChannels = null, - bool? slackDeleteOriginal = null, - bool? slackLinkNames = null, - bool? slackMarkdown = null, - ParseMode? slackParse = null, - bool? slackReplaceOriginal = null, - string slackResponseType = null, - string slackThreadId = null, + /// + /// extension that provides configuration chaining. + /// + /// Instance of object. + /// Slack WebHook URL. + /// Slack username (recommended). + /// Slack user-icon emoji string (optional). + /// Slack user-icon image URI (optional). + /// + /// A containing the name of all Slack channels in which the log + /// message should be posted (recommended). + /// + /// Slack message option 'DeleteOriginal' (optional). + /// Slack message option 'LinkNames' (optional). + /// Slack message option 'Markdown' (optional). + /// Slack message option 'Parse' as + /// Slack message option 'ReplaceOriginal' (optional). + /// Slack message option 'ResponseType' (optional). + /// Slack message option 'ThreadID' (optional). + /// + /// Slack message attachment color list as + /// (optional). + /// + /// + /// Slack message attachment footer icon list as + /// (optional). + /// + /// Add the short info attachment to the log message (optional). + /// Display the short info attachment in short form (optional). + /// Add the extended info attachment to the log message (optional). + /// Display the extended info attachment in short form (optional). + /// Add the short exception to the log message (optional). + /// Display the exception attachment in short form (optional). + /// Timeout for the connection to the Slack servers (optional). + /// The instance which the uses. + /// + /// A + /// + /// containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 + /// for message block list generation] for the Slack message generation (optional). + /// + /// + /// Size of the batch of messages that get send at once to Slack + /// (recommended). + /// + /// Time period between sending of batches of messages (recommended). + /// + /// Maximum size of the queue that stores the messages before the + /// messages were send in batches to Slack (optional). + /// + /// + /// The absolute minimum a log message must have to + /// be send to Slack (optional). + /// + /// The template for the output format of the log messages (optional). + /// + /// A to change the minimum a + /// log message must have to be send to Slack (optional). + /// + /// A format provider (optional). + /// A Switch to change the activation status of the sink on the fly (optional). + /// Instance of object. + public static LoggerConfiguration Slack( + this LoggerSinkConfiguration loggerSinkConfiguration, + + // slack options + string slackWebHookUrl, + string? slackUsername = null, + string? slackEmojiIcon = null, + Uri? slackUriIcon = null, + List? slackChannels = null, + bool? slackDeleteOriginal = null, + bool? slackLinkNames = null, + bool? slackMarkdown = null, + object? slackParseObj = null, + bool? slackReplaceOriginal = null, + string? slackResponseType = null, + string? slackThreadId = null, + object? slackAttachmentColorsObj = null, + object? slackAttachmentFooterIconObj = null, + bool? slackAddShortInfoAttachment = null, + bool? slackDisplayShortInfoAttachmentShort = null, + bool? slackAddExtendedInfoAttachment = null, + bool? slackDisplayExtendedInfoAttachmentShort = null, + bool? slackAddExceptionAttachment = null, + bool? slackDisplayExceptionAttachmentShort = null, + int? slackConnectionTimeout = null, + object? slackHttpClientObj = null, + Tuple? generateSlackFunctions = null, + + // periodic batch sink options + int? periodicBatchingSinkOptionsBatchSizeLimit = null, + TimeSpan? periodicBatchingSinkOptionsPeriod = null, + int? periodicBatchingSinkOptionsQueueLimit = null, + + // sink options + LogEventLevel? sinkRestrictedToMinimumLevel = null, + string? sinkOutputTemplate = null, + LoggingLevelSwitch? sinkLevelSwitch = null, + IFormatProvider? sinkFormatProvider = null, + SlackSinkActivationSwitch? sinkActivationSwitch = null + ) + { + ParseMode? slackParse = null; + if (slackParseObj is not null) slackParse = (ParseMode)slackParseObj; - IDictionary slackAttachmentColors = null, - IDictionary slackAttachmentFooterIcon = null, - bool? slackAddShortInfoAttachment = null, - bool? slackDisplayShortInfoAttachmentShort = null, - bool? slackAddExtendedInfoAttachment = null, - bool? slackDisplayExtendedInfoAttachmentShort = null, - bool? slackAddExceptionAttachment = null, - bool? slackDisplayExceptionAttachmentShort = null, + IDictionary? slackAttachmentColors = null; + if (slackAttachmentColorsObj is not null) + slackAttachmentColors = (IDictionary)slackAttachmentColorsObj; - int? slackConnectionTimeout = null, - HttpClient slackHttpClient = null, + IDictionary? slackAttachmentFooterIcon = null; + if (slackAttachmentFooterIconObj is not null) + slackAttachmentFooterIcon = (IDictionary)slackAttachmentFooterIconObj; - Func generateSlackMessageText = null, - Func> generateSlackMessageAttachments = null, - Func> generateSlackMessageBlocks = null, + HttpClient? slackHttpClient = null; + if (slackHttpClientObj is not null) slackHttpClient = (HttpClient)slackHttpClientObj; - // periodic batch sink options - int? periodicBatchingSinkOptionsBatchSizeLimit = null, - TimeSpan? periodicBatchingSinkOptionsPeriod = null, - int? periodicBatchingSinkOptionsQueueLimit = null, + Func? generateSlackMessageText = null; + Func?>? generateSlackMessageAttachments = null; + Func?>? generateSlackMessageBlocks = null; - // sink options - LogEventLevel? sinkRestrictedToMinimumLevel = null, - string sinkOutputTemplate = null, - LoggingLevelSwitch sinkLevelSwitch = null, - IFormatProvider sinkFormatProvider = null, - SlackSinkActivationSwitch sinkActivationSwitch = null - ) + if (generateSlackFunctions is not null) { - if (slackWebHookUrl == null) throw new ArgumentNullException(nameof(slackWebHookUrl), "The Slack WebHook can't be null!"); - if (string.IsNullOrEmpty(slackWebHookUrl)) throw new ArgumentException("The Slack WebHook can't be empty!", nameof(slackWebHookUrl)); - - var slackSinkOptions = new SlackSinkOptions - { - SlackWebHookUrl = slackWebHookUrl - }; - - if (slackUsername != null) slackSinkOptions.SlackUsername = slackUsername; - if (slackEmojiIcon != null) slackSinkOptions.SlackEmojiIcon = slackEmojiIcon; - if (slackUriIcon != null) slackSinkOptions.SlackUriIcon = slackUriIcon; - if (slackChannels != null) slackSinkOptions.SlackChannels = slackChannels; - - if (slackDeleteOriginal != null) slackSinkOptions.SlackDeleteOriginal = (bool)slackDeleteOriginal; - if (slackLinkNames != null) slackSinkOptions.SlackLinkNames = (bool)slackLinkNames; - if (slackMarkdown != null) slackSinkOptions.SlackMarkdown = (bool)slackMarkdown; - if (slackParse != null) slackSinkOptions.SlackParse = (ParseMode)slackParse; - if (slackReplaceOriginal != null) slackSinkOptions.SlackReplaceOriginal = (bool)slackReplaceOriginal; - if (slackResponseType != null) slackSinkOptions.SlackResponseType = slackResponseType; - if (slackThreadId != null) slackSinkOptions.SlackThreadId = slackThreadId; - - if (slackAttachmentColors != null) slackSinkOptions.SlackAttachmentColors = slackAttachmentColors; - if (slackAttachmentFooterIcon != null) slackSinkOptions.SlackAttachmentFooterIcon = slackAttachmentFooterIcon; - if (slackAddShortInfoAttachment != null) slackSinkOptions.SlackAddShortInfoAttachment = (bool)slackAddShortInfoAttachment; - if (slackDisplayShortInfoAttachmentShort != null) slackSinkOptions.SlackDisplayShortInfoAttachmentShort = (bool)slackDisplayShortInfoAttachmentShort; - if (slackAddExtendedInfoAttachment != null) slackSinkOptions.SlackAddExtendedInfoAttachment = (bool)slackAddExtendedInfoAttachment; - if (slackDisplayExtendedInfoAttachmentShort != null) slackSinkOptions.SlackDisplayExtendedInfoAttachmentShort = (bool)slackDisplayExtendedInfoAttachmentShort; - if (slackAddExceptionAttachment != null) slackSinkOptions.SlackAddExceptionAttachment = (bool)slackAddExceptionAttachment; - if (slackDisplayExceptionAttachmentShort != null) slackSinkOptions.SlackDisplayExceptionAttachmentShort = (bool)slackDisplayExceptionAttachmentShort; - - if (slackConnectionTimeout != null) slackSinkOptions.SlackConnectionTimeout = (int)slackConnectionTimeout; - - if (periodicBatchingSinkOptionsBatchSizeLimit != null) slackSinkOptions.PeriodicBatchingSinkOptionsBatchSizeLimit = (int)periodicBatchingSinkOptionsBatchSizeLimit; - if (periodicBatchingSinkOptionsPeriod != null) slackSinkOptions.PeriodicBatchingSinkOptionsPeriod = (TimeSpan)periodicBatchingSinkOptionsPeriod; - if (periodicBatchingSinkOptionsQueueLimit != null) slackSinkOptions.PeriodicBatchingSinkOptionsQueueLimit = (int)periodicBatchingSinkOptionsQueueLimit; - - if (sinkOutputTemplate != null) slackSinkOptions.SinkOutputTemplate = sinkOutputTemplate; - - return loggerSinkConfiguration.Sink( - logEventSink: new SlackSink(slackSinkOptions, sinkFormatProvider, sinkActivationSwitch, slackHttpClient, - generateSlackMessageText, generateSlackMessageAttachments, generateSlackMessageBlocks), - restrictedToMinimumLevel: sinkRestrictedToMinimumLevel ?? LevelAlias.Minimum, - levelSwitch: sinkLevelSwitch); + if (generateSlackFunctions.Item1 is not null) + generateSlackMessageText = + (Func)generateSlackFunctions.Item1; + if (generateSlackFunctions.Item2 is not null) + generateSlackMessageAttachments = + (Func?>)generateSlackFunctions.Item2; + if (generateSlackFunctions.Item3 is not null) + generateSlackMessageBlocks = + (Func?>)generateSlackFunctions.Item3; } - #endregion + return Slack(loggerSinkConfiguration, slackWebHookUrl, slackUsername, slackEmojiIcon, slackUriIcon, + slackChannels, slackDeleteOriginal, slackLinkNames, slackMarkdown, slackParse, slackReplaceOriginal, + slackResponseType, slackThreadId, slackAttachmentColors, slackAttachmentFooterIcon, + slackAddShortInfoAttachment, slackDisplayShortInfoAttachmentShort, slackAddExtendedInfoAttachment, + slackDisplayExtendedInfoAttachmentShort, slackAddExceptionAttachment, + slackDisplayExceptionAttachmentShort, slackConnectionTimeout, slackHttpClient, generateSlackMessageText, + generateSlackMessageAttachments, generateSlackMessageBlocks, periodicBatchingSinkOptionsBatchSizeLimit, + periodicBatchingSinkOptionsPeriod, periodicBatchingSinkOptionsQueueLimit, sinkRestrictedToMinimumLevel, + sinkOutputTemplate, sinkLevelSwitch, sinkFormatProvider, sinkActivationSwitch); } -} + + #endregion +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSerilogBatchedLogEventSink.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSerilogBatchedLogEventSink.cs index f4cd556..b66c7ab 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSerilogBatchedLogEventSink.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSerilogBatchedLogEventSink.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net.Http; using System.Threading.Tasks; @@ -7,168 +8,172 @@ using Serilog.Sinks.PeriodicBatching; using Slack.Webhooks; -namespace jjm.one.Serilog.Sinks.SlackWebHook +namespace jjm.one.Serilog.Sinks.SlackWebHook; + +/// +/// This class implements the for the use with slack as an endpoint. +/// +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class SlackSerilogBatchedLogEventSink : IBatchedLogEventSink { - public class SlackSerilogBatchedLogEventSink : IBatchedLogEventSink + #region constructor + + /// + /// Initializes new instance of . + /// + /// Slack Sink Options object. + /// FormatProvider object. + /// HttpClient instance. + /// GenerateSlackMessageText function. + /// GenerateSlackMessageAttachments function. + /// GenerateSlackMessageBlocks function. + /// A Switch to change the activation status of the sink on the fly (optional). + public SlackSerilogBatchedLogEventSink( + SlackSinkOptions slackSinkOptions, + IFormatProvider? formatProvider, + SlackSinkActivationSwitch? statusSwitch = null, + HttpClient? slackHttpClient = null, + Func? generateSlackMessageText = null, + Func?>? generateSlackMessageAttachments = null, + Func?>? generateSlackMessageBlocks = null + ) { - #region private members - - /// - /// instance for the SlackClient. - /// - private readonly HttpClient _slackHttpClient; - - /// - /// instance. - /// - private readonly SlackClient _slackClient; - - /// - /// object for this Sink. - /// - private readonly SlackSinkOptions _slackSinkOptions; - - /// - /// to change the activation status of the sink on the fly. - /// - private readonly SlackSinkActivationSwitch _slackSinkActivationSwitch; - - /// - /// object. - /// - private readonly IFormatProvider _formatProvider; - - /// - /// Function to generate the text of the slack message. - /// - private static Func _generateSlackMessageText; - - /// - /// Function to generate the attachments of the slack message. - /// - private static Func> _generateSlackMessageAttachments; - - /// - /// Function to generate the blocks of the slack message. - /// - private static Func> _generateSlackMessageBlocks; - - #endregion - - #region constructor - - /// - /// Initializes new instance of . - /// - /// Slack Sink Options object. - /// FormatProvider object. - /// HttpClient instance. - /// GenerateSlackMessageText function. - /// GenerateSlackMessageAttachments function. - /// GenerateSlackMessageBlocks function. - /// A Switch to change the activation status of the sink on the fly (optional). - public SlackSerilogBatchedLogEventSink( - SlackSinkOptions slackSinkOptions, - IFormatProvider formatProvider, - SlackSinkActivationSwitch statusSwitch = null, - HttpClient slackHttpClient = null, - Func generateSlackMessageText = null, - Func> generateSlackMessageAttachments = null, - Func> generateSlackMessageBlocks = null - ) - { - _slackSinkOptions = slackSinkOptions; - _formatProvider = formatProvider; - _slackSinkActivationSwitch = statusSwitch ?? new SlackSinkActivationSwitch(); - _slackHttpClient = slackHttpClient ?? new HttpClient(); - - // if no extern generation functions were specified, use the default ones - if (generateSlackMessageText == null) _generateSlackMessageText = SlackSinkMessageTools.GenerateSlackMessageText; - if (generateSlackMessageAttachments == null) _generateSlackMessageAttachments = SlackSinkMessageTools.GenerateSlackMessageAttachments; - if (generateSlackMessageBlocks == null) _generateSlackMessageBlocks = SlackSinkMessageTools.GenerateSlackMessageBlocks; - - // start new SlackClient - _slackClient = new SlackClient(slackSinkOptions.SlackWebHookUrl, slackSinkOptions.SlackConnectionTimeout, _slackHttpClient); - } + _slackSinkOptions = slackSinkOptions; + _formatProvider = formatProvider; + _slackSinkActivationSwitch = statusSwitch ?? new SlackSinkActivationSwitch(); + _slackHttpClient = slackHttpClient ?? new HttpClient(); + + // if no extern generation functions were specified, use the default ones + if (generateSlackMessageText == null) + _generateSlackMessageText = SlackSinkMessageTools.GenerateSlackMessageText; + if (generateSlackMessageAttachments == null) + _generateSlackMessageAttachments = SlackSinkMessageTools.GenerateSlackMessageAttachments; + if (generateSlackMessageBlocks == null) + _generateSlackMessageBlocks = SlackSinkMessageTools.GenerateSlackMessageBlocks; + + // start new SlackClient + _slackClient = new SlackClient(slackSinkOptions.SlackWebHookUrl, slackSinkOptions.SlackConnectionTimeout, + _slackHttpClient); + } - #endregion + #endregion - #region function override + #region private members - /// - /// Implements a function to close the and the . - /// - public void Dispose() - { - _slackClient.Dispose(); - _slackHttpClient.Dispose(); - } + /// + /// instance for the SlackClient. + /// + private readonly HttpClient _slackHttpClient; + + /// + /// instance. + /// + private readonly SlackClient _slackClient; + + /// + /// object for this Sink. + /// + private readonly SlackSinkOptions _slackSinkOptions; + + /// + /// to change the activation status of the sink on the fly. + /// + private readonly SlackSinkActivationSwitch _slackSinkActivationSwitch; + + /// + /// object. + /// + private readonly IFormatProvider? _formatProvider; + + /// + /// Function to generate the text of the slack message. + /// + private static Func? _generateSlackMessageText; + + /// + /// Function to generate the attachments of the slack message. + /// + private static Func?>? _generateSlackMessageAttachments; + + /// + /// Function to generate the blocks of the slack message. + /// + private static Func?>? _generateSlackMessageBlocks; + + #endregion - /// - /// Implements and sends the with a to Slack. - /// - /// A collection of . - /// An Awaitable Task. - async Task IBatchedLogEventSink.EmitBatchAsync(IEnumerable batch) + #region function override + + /// + /// Implements a function to close the and the + /// . + /// + public void Dispose() + { + _slackClient.Dispose(); + _slackHttpClient.Dispose(); + } + + /// + /// Implements and sends the with a + /// to Slack. + /// + /// A collection of . + /// An Awaitable Task. + async Task IBatchedLogEventSink.EmitBatchAsync(IEnumerable batch) + { + // check activation status + if (_slackSinkActivationSwitch.SlackSinkStatus == + SlackSinkActivationSwitch.SlackSinkActivationStatus.InActive) return; + + foreach (var logEvent in batch) { - // check activation status - if (_slackSinkActivationSwitch.SlackSinkStatus == SlackSinkActivationSwitch.SlackSinkActivationStatus.InActive) + // create new slack message + var msg = new SlackMessage { - return; - } + Attachments = _generateSlackMessageAttachments?.Invoke(logEvent, _formatProvider, _slackSinkOptions), + Blocks = _generateSlackMessageBlocks?.Invoke(logEvent, _formatProvider, _slackSinkOptions), + Channel = _slackSinkOptions.SlackChannels is not null && _slackSinkOptions.SlackChannels.Any() + ? _slackSinkOptions.SlackChannels[0] + : null, + DeleteOriginal = _slackSinkOptions.SlackDeleteOriginal, + IconEmoji = _slackSinkOptions.SlackEmojiIcon, + IconUrl = _slackSinkOptions.SlackUriIcon, + LinkNames = _slackSinkOptions.SlackLinkNames, + Markdown = _slackSinkOptions.SlackMarkdown, + Parse = _slackSinkOptions.SlackParse, + ReplaceOriginal = _slackSinkOptions.SlackReplaceOriginal, + ResponseType = _slackSinkOptions.SlackResponseType, + Text = _generateSlackMessageText?.Invoke(logEvent, _formatProvider, _slackSinkOptions), + ThreadId = _slackSinkOptions.SlackThreadId, + Username = _slackSinkOptions.SlackUsername + }; + + // check for multi channel post + if (_slackSinkOptions.SlackChannels is not null) + { + // multi channel post + var logMsgPosts = _slackClient.PostToChannelsAsync(msg, _slackSinkOptions.SlackChannels); - foreach (LogEvent logEvent in batch) + foreach (var logMsgPost in logMsgPosts) await logMsgPost; + } + else { - // create new slack message - var msg = new SlackMessage - { - Attachments = _generateSlackMessageAttachments(logEvent, _formatProvider, _slackSinkOptions), - Blocks = _generateSlackMessageBlocks(logEvent, _formatProvider, _slackSinkOptions), - Channel = _slackSinkOptions.SlackChannels != null && _slackSinkOptions.SlackChannels.Any() ? _slackSinkOptions.SlackChannels[0] : null, - DeleteOriginal = _slackSinkOptions.SlackDeleteOriginal, - IconEmoji = _slackSinkOptions.SlackEmojiIcon, - IconUrl = _slackSinkOptions.SlackUriIcon, - LinkNames = _slackSinkOptions.SlackLinkNames, - Markdown = _slackSinkOptions.SlackMarkdown, - Parse = _slackSinkOptions.SlackParse, - ReplaceOriginal = _slackSinkOptions.SlackReplaceOriginal, - ResponseType = _slackSinkOptions.SlackResponseType, - Text = _generateSlackMessageText(logEvent, _formatProvider, _slackSinkOptions), - ThreadId = _slackSinkOptions.SlackThreadId, - Username = _slackSinkOptions.SlackUsername - }; - - // check for multi channel post - if (_slackSinkOptions.SlackChannels != null) - { - // multi channel post - var logMsgPosts = _slackClient.PostToChannelsAsync(msg, _slackSinkOptions.SlackChannels); - - foreach (Task logMsgPost in logMsgPosts) - { - await logMsgPost; - } - } - else - { - // single channel post - await _slackClient.PostAsync(msg); - } + // single channel post + await _slackClient.PostAsync(msg); } } + } - /// - /// Implements . - /// - /// An Awaitable Task. + /// + /// Implements . + /// + /// An Awaitable Task. #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - async Task IBatchedLogEventSink.OnEmptyBatchAsync() + async Task IBatchedLogEventSink.OnEmptyBatchAsync() #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - { - return; - } - - #endregion + { } -} + #endregion +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSink.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSink.cs index e0b4ea6..3b9f127 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSink.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSink.cs @@ -1,56 +1,58 @@ -using Serilog.Events; -using Serilog.Sinks.PeriodicBatching; -using Slack.Webhooks; -using System; +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Serilog.Events; +using Serilog.Sinks.PeriodicBatching; +using Slack.Webhooks; + +namespace jjm.one.Serilog.Sinks.SlackWebHook; -namespace jjm.one.Serilog.Sinks.SlackWebHook +/// +/// This class provides functions for sending log events (serilog) to slack an implements therefor +/// . +/// +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class SlackSink : PeriodicBatchingSink { + #region constructor + /// - /// This class provides functions for sending log events (serilog) to slack an implements therefor . + /// Initializes new instance of . /// - public class SlackSink : PeriodicBatchingSink + /// Slack Sink Options object. + /// FormatProvider object. + /// HttpClient instance. + /// GenerateSlackMessageText function. + /// GenerateSlackMessageAttachments function. + /// GenerateSlackMessageBlocks function. + /// A Switch to change the activation status of the sink on the fly (optional). + public SlackSink( + SlackSinkOptions slackSinkOptions, + IFormatProvider? formatProvider, + SlackSinkActivationSwitch? statusSwitch = null, + HttpClient? slackHttpClient = null, + Func? generateSlackMessageText = null, + Func?>? generateSlackMessageAttachments = null, + Func?>? generateSlackMessageBlocks = null + ) + : base(new SlackSerilogBatchedLogEventSink( + slackSinkOptions, + formatProvider, + statusSwitch, + slackHttpClient, + generateSlackMessageText, + generateSlackMessageAttachments, + generateSlackMessageBlocks), + new PeriodicBatchingSinkOptions + { + BatchSizeLimit = slackSinkOptions.PeriodicBatchingSinkOptionsBatchSizeLimit, + Period = slackSinkOptions.PeriodicBatchingSinkOptionsPeriod, + QueueLimit = slackSinkOptions.PeriodicBatchingSinkOptionsQueueLimit + } + ) { - #region constructor - - /// - /// Initializes new instance of . - /// - /// Slack Sink Options object. - /// FormatProvider object. - /// HttpClient instance. - /// GenerateSlackMessageText function. - /// GenerateSlackMessageAttachments function. - /// GenerateSlackMessageBlocks function. - /// A Switch to change the activation status of the sink on the fly (optional). - public SlackSink( - SlackSinkOptions slackSinkOptions, - IFormatProvider formatProvider, - SlackSinkActivationSwitch statusSwitch = null, - HttpClient slackHttpClient = null, - Func generateSlackMessageText = null, - Func> generateSlackMessageAttachments = null, - Func> generateSlackMessageBlocks = null - ) - : base(new SlackSerilogBatchedLogEventSink( - slackSinkOptions: slackSinkOptions, - formatProvider: formatProvider, - statusSwitch: statusSwitch, - slackHttpClient: slackHttpClient, - generateSlackMessageText: generateSlackMessageText, - generateSlackMessageAttachments: generateSlackMessageAttachments, - generateSlackMessageBlocks: generateSlackMessageBlocks), - new PeriodicBatchingSinkOptions() - { - BatchSizeLimit = slackSinkOptions.PeriodicBatchingSinkOptionsBatchSizeLimit, - Period = slackSinkOptions.PeriodicBatchingSinkOptionsPeriod, - QueueLimit = slackSinkOptions.PeriodicBatchingSinkOptionsQueueLimit - } - ) - { - } - - #endregion } -} + + #endregion +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkActivationSwitch.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkActivationSwitch.cs index 819336a..cc716a0 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkActivationSwitch.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkActivationSwitch.cs @@ -1,39 +1,49 @@ -namespace jjm.one.Serilog.Sinks.SlackWebHook +using System.Diagnostics.CodeAnalysis; + +namespace jjm.one.Serilog.Sinks.SlackWebHook; + +/// +/// Provides a switch to set a slack sink active or inactive on the fly. +/// +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class SlackSinkActivationSwitch { + #region public enum + /// - /// Provides a switch to set a slack sink active or inactive on the fly. + /// Enum to represent an activation status. /// - public class SlackSinkActivationSwitch + public enum SlackSinkActivationStatus { - #region public enum - /// - /// Enum to represent an activation status. + /// deactivates the sink /// - public enum SlackSinkActivationStatus - { - InActive = 0, - Active = 1 - } - - #endregion - - #region SlackSinkActivationSwitch implementation + InActive = 0, /// - /// The current status. + /// activates the sink /// - public SlackSinkActivationStatus SlackSinkStatus { get; set; } + Active = 1 + } - /// - /// Initializes new instance of . - /// - /// The . - public SlackSinkActivationSwitch(SlackSinkActivationStatus slackSinkActivationStatus = SlackSinkActivationStatus.Active) - { - SlackSinkStatus = slackSinkActivationStatus; - } + #endregion - #endregion + #region SlackSinkActivationSwitch implementation + + /// + /// The current status. + /// + public SlackSinkActivationStatus SlackSinkStatus { get; set; } + + /// + /// Initializes new instance of . + /// + /// The . + public SlackSinkActivationSwitch( + SlackSinkActivationStatus slackSinkActivationStatus = SlackSinkActivationStatus.Active) + { + SlackSinkStatus = slackSinkActivationStatus; } -} + + #endregion +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkMessageTools.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkMessageTools.cs index 952951b..0424cc6 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkMessageTools.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkMessageTools.cs @@ -1,220 +1,225 @@ -using Serilog.Events; -using Serilog.Formatting.Display; -using Slack.Webhooks; -using System; +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using Serilog.Events; +using Serilog.Formatting.Display; +using Slack.Webhooks; + +namespace jjm.one.Serilog.Sinks.SlackWebHook; -namespace jjm.one.Serilog.Sinks.SlackWebHook +/// +/// Class with default tools for message generation. +/// +[SuppressMessage("ReSharper", "InconsistentNaming")] +public static class SlackSinkMessageTools { /// - /// Class with default tools for message generation. + /// DEFAULT GenerateSlackMessageText function. /// - public static class SlackSinkMessageTools + /// The log event. + /// A format provider + /// Sink Options as SlackSinkOptions. + /// The log message string. + public static string GenerateSlackMessageText(LogEvent logEvent, IFormatProvider? formatProvider, object options) { + // input check + var slackSinkOptions = (SlackSinkOptions)options ?? throw new InvalidCastException(); - /// - /// DEFAULT GenerateSlackMessageText function. - /// - /// The log event. - /// A format provider - /// Sink Options as SlackSinkOptions. - /// The log message string. - public static string GenerateSlackMessageText(LogEvent logEvent, IFormatProvider formatProvider, object options) - { - // input check - var slackSinkOptions = (SlackSinkOptions)options ?? throw new InvalidCastException(); + // generate the log message text + var textFormatter = new MessageTemplateTextFormatter(slackSinkOptions.SinkOutputTemplate, formatProvider); + var stringWriter = new StringWriter(); + textFormatter.Format(logEvent, stringWriter); - // generate the log message text - var textFormatter = new MessageTemplateTextFormatter(slackSinkOptions.SinkOutputTemplate, formatProvider); - var stringWriter = new StringWriter(); - textFormatter.Format(logEvent, stringWriter); - - return stringWriter.ToString(); - } + return stringWriter.ToString(); + } - /// - /// DEFAULT GenerateSlackMessageAttachments function. - /// - /// The log event. - /// A format provider - /// Sink Options as SlackSinkOptions. - /// The log message attachment list. - public static List GenerateSlackMessageAttachments(LogEvent logEvent, IFormatProvider formatProvider, object options) - { - // input check - var slackSinkOptions = (SlackSinkOptions)options ?? throw new InvalidCastException(); + /// + /// DEFAULT GenerateSlackMessageAttachments function. + /// + /// The log event. + /// A format provider + /// Sink Options as SlackSinkOptions. + /// The log message attachment list. + public static List? GenerateSlackMessageAttachments(LogEvent logEvent, + IFormatProvider? formatProvider, object options) + { + // input check + var slackSinkOptions = (SlackSinkOptions)options ?? throw new InvalidCastException(); - var attachments = new List(2); + var attachments = new List(2); - #region information attachment + #region information attachment - // Check if the short info attachment should be added - if (slackSinkOptions.SlackAddShortInfoAttachment && !slackSinkOptions.SlackAddExtendedInfoAttachment) + // Check if the short info attachment should be added + if (slackSinkOptions is { SlackAddShortInfoAttachment: true, SlackAddExtendedInfoAttachment: false }) + { + // create the attachment + var shotInfoAttach = new SlackAttachment { - // create the attachment - var shotInfoAttach = new SlackAttachment + Actions = null, + AuthorIcon = null, + AuthorLink = null, + AuthorName = null, + CallbackId = null, + Color = slackSinkOptions.SlackAttachmentColors[logEvent.Level], + Fallback = + $"{logEvent.Timestamp.ToString(formatProvider)} [{logEvent.Level}] - {logEvent.RenderMessage()}", + Fields = new List { - Actions = null, - AuthorIcon = null, - AuthorLink = null, - AuthorName = null, - CallbackId = null, - Color = slackSinkOptions.SlackAttachmentColors[logEvent.Level], - Fallback = $"{logEvent.Timestamp.ToString(formatProvider)} [{logEvent.Level}] - {logEvent.RenderMessage()}", - Fields = new List + new() { - new SlackField - { - Short = slackSinkOptions.SlackDisplayShortInfoAttachmentShort, - Title = "Level", - Value = logEvent.Level.ToString() - }, - new SlackField - { - Short = slackSinkOptions.SlackDisplayShortInfoAttachmentShort, - Title = "Timestamp", - Value = logEvent.Timestamp.ToString(formatProvider) - } + Short = slackSinkOptions.SlackDisplayShortInfoAttachmentShort, + Title = "Level", + Value = logEvent.Level.ToString() }, - Footer = null, - FooterIcon = slackSinkOptions.SlackAttachmentFooterIcon[logEvent.Level], - ImageUrl = null, - MarkdownIn = null, - Pretext = null, - Text = null, - ThumbUrl = null, - Timestamp = 0, - Title = "Details", - TitleLink = null - }; + new() + { + Short = slackSinkOptions.SlackDisplayShortInfoAttachmentShort, + Title = "Timestamp", + Value = logEvent.Timestamp.ToString(formatProvider) + } + }, + Footer = null, + FooterIcon = slackSinkOptions.SlackAttachmentFooterIcon[logEvent.Level], + ImageUrl = null, + MarkdownIn = null, + Pretext = null, + Text = null, + ThumbUrl = null, + Timestamp = 0, + Title = "Details", + TitleLink = null + }; + + attachments.Add(shotInfoAttach); + } + // Check if the extended info attachment should be added + else if (slackSinkOptions.SlackAddExtendedInfoAttachment) + { + var infoFields = new List(); + var stringWriter = new StringWriter(); - attachments.Add(shotInfoAttach); - } - // Check if the extended info attachment should be added - else if (slackSinkOptions.SlackAddExtendedInfoAttachment) + // collect all log event information + foreach (var property in logEvent.Properties) { - var infoFields = new List(); - var stringWriter = new StringWriter(); - - // collect all log event information - foreach (var property in logEvent.Properties) + property.Value.Render(stringWriter, formatProvider: formatProvider); + var field = new SlackField { - property.Value.Render(stringWriter, formatProvider: formatProvider); - var field = new SlackField - { - Short = slackSinkOptions.SlackDisplayExtendedInfoAttachmentShort, - Title = property.Key, - Value = stringWriter.ToString() - }; - infoFields.Add(field); - stringWriter.GetStringBuilder().Clear(); - } - - // create the attachment - var extInfoAttach = new SlackAttachment - { - Actions = null, - AuthorIcon = null, - AuthorLink = null, - AuthorName = null, - CallbackId = null, - Color = slackSinkOptions.SlackAttachmentColors[logEvent.Level], - Fallback = $"{logEvent.Timestamp.ToString(formatProvider)} [{logEvent.Level}] - {logEvent.RenderMessage()}", - Fields = infoFields, - Footer = null, - FooterIcon = slackSinkOptions.SlackAttachmentFooterIcon[logEvent.Level], - ImageUrl = null, - MarkdownIn = null, - Pretext = null, - Text = null, - ThumbUrl = null, - Timestamp = 0, - Title = "Details", - TitleLink = null + Short = slackSinkOptions.SlackDisplayExtendedInfoAttachmentShort, + Title = property.Key, + Value = stringWriter.ToString() }; - - attachments.Add(extInfoAttach); + infoFields.Add(field); + stringWriter.GetStringBuilder().Clear(); } - #endregion + // create the attachment + var extInfoAttach = new SlackAttachment + { + Actions = null, + AuthorIcon = null, + AuthorLink = null, + AuthorName = null, + CallbackId = null, + Color = slackSinkOptions.SlackAttachmentColors[logEvent.Level], + Fallback = + $"{logEvent.Timestamp.ToString(formatProvider)} [{logEvent.Level}] - {logEvent.RenderMessage()}", + Fields = infoFields, + Footer = null, + FooterIcon = slackSinkOptions.SlackAttachmentFooterIcon[logEvent.Level], + ImageUrl = null, + MarkdownIn = null, + Pretext = null, + Text = null, + ThumbUrl = null, + Timestamp = 0, + Title = "Details", + TitleLink = null + }; + + attachments.Add(extInfoAttach); + } + + #endregion - #region exception attachment + #region exception attachment - // Check if the exception attachment should be added & if an exception is provided with to log event - if (slackSinkOptions.SlackAddExceptionAttachment && logEvent.Exception != null) + // Check if the exception attachment should be added & if an exception is provided with to log event + if (slackSinkOptions.SlackAddExceptionAttachment && logEvent.Exception != null) + { + // create the attachment + var excAttach = new SlackAttachment { - // create the attachment - var excAttach = new SlackAttachment + Actions = null, + AuthorIcon = null, + AuthorLink = null, + AuthorName = null, + CallbackId = null, + Color = slackSinkOptions.SlackAttachmentColors[logEvent.Level], + Fallback = + $"{logEvent.Timestamp.ToString(formatProvider)} Exception: {logEvent.Exception.Message} \n {logEvent.Exception.StackTrace}", + Fields = new List { - Actions = null, - AuthorIcon = null, - AuthorLink = null, - AuthorName = null, - CallbackId = null, - Color = slackSinkOptions.SlackAttachmentColors[logEvent.Level], - Fallback = $"{logEvent.Timestamp.ToString(formatProvider)} Exception: {logEvent.Exception.Message} \n {logEvent.Exception.StackTrace}", - Fields = new List + new() { - new SlackField - { - Short = slackSinkOptions.SlackDisplayExceptionAttachmentShort, - Title = "Message", - Value = logEvent.Exception.Message - }, - new SlackField - { - Short = slackSinkOptions.SlackDisplayExceptionAttachmentShort, - Title = "Type", - Value = $"`{logEvent.Exception.GetType().Name}`" - }, - new SlackField - { - Short = false, - Title = "Stack Trace", - Value = $"```{logEvent.Exception.StackTrace}```" - }, - new SlackField - { - Short = false, - Title = "Exception", - Value = $"```{logEvent.Exception}```" - } + Short = slackSinkOptions.SlackDisplayExceptionAttachmentShort, + Title = "Message", + Value = logEvent.Exception.Message }, - Footer = null, - FooterIcon = slackSinkOptions.SlackAttachmentFooterIcon[logEvent.Level], - ImageUrl = null, - MarkdownIn = new List + new() { - "fields" + Short = slackSinkOptions.SlackDisplayExceptionAttachmentShort, + Title = "Type", + Value = $"`{logEvent.Exception.GetType().Name}`" }, - Pretext = null, - Text = null, - ThumbUrl = null, - Timestamp = 0, - Title = "Exception", - TitleLink = null - }; - - attachments.Add(excAttach); - } + new() + { + Short = false, + Title = "Stack Trace", + Value = $"```{logEvent.Exception.StackTrace}```" + }, + new() + { + Short = false, + Title = "Exception", + Value = $"```{logEvent.Exception}```" + } + }, + Footer = null, + FooterIcon = slackSinkOptions.SlackAttachmentFooterIcon[logEvent.Level], + ImageUrl = null, + MarkdownIn = new List + { + "fields" + }, + Pretext = null, + Text = null, + ThumbUrl = null, + Timestamp = 0, + Title = "Exception", + TitleLink = null + }; + + attachments.Add(excAttach); + } - #endregion + #endregion - return attachments.Any() ? attachments : null; - } + return attachments.Any() ? attachments : null; + } - /// - /// DEFAULT GenerateSlackMessageBlocks function. - /// - /// The log event. - /// A format provider - /// Sink Options as SlackSinkOptions. - /// The log message block list. - public static List GenerateSlackMessageBlocks(LogEvent logEvent, IFormatProvider formatProvider, object options) - { - return null; - } + /// + /// DEFAULT GenerateSlackMessageBlocks function. + /// + /// The log event. + /// A format provider + /// Sink Options as SlackSinkOptions. + /// The log message block list. + public static List? GenerateSlackMessageBlocks(LogEvent logEvent, IFormatProvider? formatProvider, + object options) + { + return null; } } \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkOptions.cs b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkOptions.cs index dd30ab8..946f789 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkOptions.cs +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/SlackSinkOptions.cs @@ -1,211 +1,217 @@ -using Serilog.Events; -using Slack.Webhooks; -using System; +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Serilog.Events; +using Slack.Webhooks; + +namespace jjm.one.Serilog.Sinks.SlackWebHook; -namespace jjm.one.Serilog.Sinks.SlackWebHook +/// +/// Class to contain all relevant options of this sink. +/// +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class SlackSinkOptions { + #region general sink options + + /// + /// OPTIONAL: The template for the output format of the log messages. + /// + // ReSharper disable once InconsistentNaming + public string SinkOutputTemplate { get; set; } = DefaultOutputTemplate; + + #endregion + + #region default values + + /// + /// Default value for the OutputTemplate. + /// + public const string DefaultOutputTemplate = "{Message:lj}"; + + /// + /// Default value for the BatchSizeLimit. + /// + public const int DefaultBatchSizeLimit = 10; + /// - /// Class to contain all relevant options of this sink. + /// Default value for the Period. /// - public class SlackSinkOptions - { - #region default values + public static readonly TimeSpan DefaultPeriod = TimeSpan.FromSeconds(2); - /// - /// Default value for the OutputTemplate. - /// - public const string DefaultOutputTemplate = "{Message:lj}"; + /// + /// Default value for the QueueLimit. + /// + public const int DefaultQueueLimit = 10000; + + /// + /// Default value for the Timeout. + /// + public const int DefaultTimeout = 1000; - /// - /// Default value for the BatchSizeLimit. - /// - public const int DefaultBatchSizeLimit = 10; + #endregion - /// - /// Default value for the Period. - /// - public static readonly TimeSpan DefaultPeriod = TimeSpan.FromSeconds(2); + #region slack options - /// - /// Default value for the QueueLimit. - /// - public const int DefaultQueueLimit = 10000; + #region slack connection options - /// - /// Default value for the Timeout. - /// - public const int DefaultTimeout = 1000; + /// + /// REQUIRED: Slack WebHook URL. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public string SlackWebHookUrl { get; set; } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - #endregion + /// + /// OPTIONAL: Timeout for the connection to the Slack servers. + /// + public int SlackConnectionTimeout { get; set; } = DefaultTimeout; - #region slack options + #endregion - #region slack connection options + #region generall slack & message options - /// - /// REQUIRED: Slack WebHook URL. - /// - public string SlackWebHookUrl { get; set; } + /// + /// RECOMMENDED: Slack username. + /// + public string? SlackUsername { get; set; } = null; - /// - /// OPTIONAL: Timeout for the connection to the Slack servers. - /// - public int SlackConnectionTimeout { get; set; } = DefaultTimeout; + /// + /// RECOMMENDED: Slack user-icon emoji string. + /// + public string? SlackEmojiIcon { get; set; } = null; - #endregion + /// + /// OPTIONAL: Slack user-icon image URI. + /// + public Uri? SlackUriIcon { get; set; } = null; - #region generall slack & message options + /// + /// RECOMMENDED: A containing the name of all Slack channels in which the log message + /// should be posted. + /// + public List? SlackChannels { get; set; } = null; - /// - /// RECOMMENDED: Slack username. - /// - public string SlackUsername { get; set; } = null; + /// + /// OPTIONAL: Slack message option 'DeleteOriginal'. + /// + public bool SlackDeleteOriginal { get; set; } = false; - /// - /// RECOMMENDED: Slack user-icon emoji string. - /// - public string SlackEmojiIcon { get; set; } = null; + /// + /// OPTIONAL: Slack message option 'LinkNames'. + /// + public bool SlackLinkNames { get; set; } = false; - /// - /// OPTIONAL: Slack user-icon image URI. - /// - public Uri SlackUriIcon { get; set; } = null; + /// + /// OPTIONAL: Slack message option 'Markdown'. + /// + public bool SlackMarkdown { get; set; } = false; - /// - /// RECOMMENDED: A containing the name of all Slack channels in which the log message should be posted. - /// - public List SlackChannels { get; set; } = null; + /// + /// OPTIONAL: Slack message option 'Parse'. + /// + public ParseMode SlackParse { get; set; } = ParseMode.None; - /// - /// OPTIONAL: Slack message option 'DeleteOriginal'. - /// - public bool SlackDeleteOriginal { get; set; } = false; + /// + /// OPTIONAL: Slack message option 'ReplaceOriginal'. + /// + public bool SlackReplaceOriginal { get; set; } = false; - /// - /// OPTIONAL: Slack message option 'LinkNames'. - /// - public bool SlackLinkNames { get; set; } = false; + /// + /// OPTIONAL: Slack message option 'ResponseType'. + /// + public string? SlackResponseType { get; set; } = null; - /// - /// OPTIONAL: Slack message option 'Markdown'. - /// - public bool SlackMarkdown { get; set; } = false; + /// + /// OPTIONAL: Slack message option 'ThreadID'. + /// + public string? SlackThreadId { get; set; } = null; - /// - /// OPTIONAL: Slack message option 'Parse'. - /// - public ParseMode SlackParse { get; set; } = ParseMode.None; + #endregion - /// - /// OPTIONAL: Slack message option 'ReplaceOriginal'. - /// - public bool SlackReplaceOriginal { get; set; } = false; + #region slack attachment options - /// - /// OPTIONAL: Slack message option 'ResponseType'. - /// - public string SlackResponseType { get; set; } = null; - - /// - /// OPTIONAL: Slack message option 'ThreadID'. - /// - public string SlackThreadId { get; set; } = null; - - #endregion - - #region slack attachment options - - /// - /// OPTIONAL: Slack message attachment color list as . - /// - public IDictionary SlackAttachmentColors { get; set; } = new Dictionary + /// + /// OPTIONAL: Slack message attachment color list as . + /// + public IDictionary SlackAttachmentColors { get; set; } = + new Dictionary { - {LogEventLevel.Verbose, "#DFDFDF"}, - {LogEventLevel.Debug, "#00C9FF"}, - {LogEventLevel.Information, "#45FF00"}, - {LogEventLevel.Warning, "#FF7200"}, - {LogEventLevel.Error, "#FF0000"}, - {LogEventLevel.Fatal, "#900000"} + { LogEventLevel.Verbose, "#DFDFDF" }, + { LogEventLevel.Debug, "#00C9FF" }, + { LogEventLevel.Information, "#45FF00" }, + { LogEventLevel.Warning, "#FF7200" }, + { LogEventLevel.Error, "#FF0000" }, + { LogEventLevel.Fatal, "#900000" } }; - /// - /// OPTIONAL: Slack message attachment footer icon list as . - /// - public IDictionary SlackAttachmentFooterIcon { get; set; } = new Dictionary + /// + /// OPTIONAL: Slack message attachment footer icon list as . + /// + public IDictionary SlackAttachmentFooterIcon { get; set; } = + new Dictionary { - {LogEventLevel.Verbose, null}, - {LogEventLevel.Debug, Emoji.Bug}, - {LogEventLevel.Information, Emoji.InformationSource}, - {LogEventLevel.Warning, Emoji.Warning}, - {LogEventLevel.Error, Emoji.Bomb}, - {LogEventLevel.Fatal, Emoji.Fire} + { LogEventLevel.Verbose, null }, + { LogEventLevel.Debug, Emoji.Bug }, + { LogEventLevel.Information, Emoji.InformationSource }, + { LogEventLevel.Warning, Emoji.Warning }, + { LogEventLevel.Error, Emoji.Bomb }, + { LogEventLevel.Fatal, Emoji.Fire } }; - /// - /// OPTIONAL: Add the short info attachment to the log message. - /// - public bool SlackAddShortInfoAttachment { get; set; } = true; - - /// - /// OPTIONAL: Display the short info attachment in short form. - /// - public bool SlackDisplayShortInfoAttachmentShort { get; set; } = true; - - /// - /// OPTIONAL: Add the extended info attachment to the log message. - /// - public bool SlackAddExtendedInfoAttachment { get; set; } = false; - - /// - /// OPTIONAL: Display the extended info attachment in short form. - /// - public bool SlackDisplayExtendedInfoAttachmentShort { get; set; } = true; - - /// - /// OPTIONAL: Add the short exception to the log message. - /// - public bool SlackAddExceptionAttachment { get; set; } = true; - - /// - /// OPTIONAL: Display the exception attachment in short form. - /// - public bool SlackDisplayExceptionAttachmentShort { get; set; } = true; - - #endregion - - #endregion - - #region periodic batch sink options - - /// - /// RECOMMENDED: Size of the batch of messages that get send at once to Slack. - /// - // ReSharper disable once InconsistentNaming - public int PeriodicBatchingSinkOptionsBatchSizeLimit { get; set; } = DefaultBatchSizeLimit; - - /// - /// RECOMMENDED: Time period between sending of batches of messages. - /// - // ReSharper disable once InconsistentNaming - public TimeSpan PeriodicBatchingSinkOptionsPeriod { get; set; } = DefaultPeriod; - - /// - /// OPTIONAL: Maximum size of the queue that stores the messages before the messages were send in batches to Slack. - /// - // ReSharper disable once InconsistentNaming - public int PeriodicBatchingSinkOptionsQueueLimit { get; set; } = DefaultQueueLimit; - - #endregion - - #region general sink options - - /// - /// OPTIONAL: The template for the output format of the log messages. - /// - // ReSharper disable once InconsistentNaming - public string SinkOutputTemplate { get; set; } = DefaultOutputTemplate; - - #endregion - } -} + /// + /// OPTIONAL: Add the short info attachment to the log message. + /// + public bool SlackAddShortInfoAttachment { get; set; } = true; + + /// + /// OPTIONAL: Display the short info attachment in short form. + /// + public bool SlackDisplayShortInfoAttachmentShort { get; set; } = true; + + /// + /// OPTIONAL: Add the extended info attachment to the log message. + /// + public bool SlackAddExtendedInfoAttachment { get; set; } = false; + + /// + /// OPTIONAL: Display the extended info attachment in short form. + /// + public bool SlackDisplayExtendedInfoAttachmentShort { get; set; } = true; + + /// + /// OPTIONAL: Add the short exception to the log message. + /// + public bool SlackAddExceptionAttachment { get; set; } = true; + + /// + /// OPTIONAL: Display the exception attachment in short form. + /// + public bool SlackDisplayExceptionAttachmentShort { get; set; } = true; + + #endregion + + #endregion + + #region periodic batch sink options + + /// + /// RECOMMENDED: Size of the batch of messages that get send at once to Slack. + /// + // ReSharper disable once InconsistentNaming + public int PeriodicBatchingSinkOptionsBatchSizeLimit { get; set; } = DefaultBatchSizeLimit; + + /// + /// RECOMMENDED: Time period between sending of batches of messages. + /// + // ReSharper disable once InconsistentNaming + public TimeSpan PeriodicBatchingSinkOptionsPeriod { get; set; } = DefaultPeriod; + + /// + /// OPTIONAL: Maximum size of the queue that stores the messages before the messages were send in batches to Slack. + /// + // ReSharper disable once InconsistentNaming + public int PeriodicBatchingSinkOptionsQueueLimit { get; set; } = DefaultQueueLimit; + + #endregion +} \ No newline at end of file diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Extensions.Logging.Helpers.xml b/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Extensions.Logging.Helpers.xml index 53a1576..86d2741 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Extensions.Logging.Helpers.xml +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Extensions.Logging.Helpers.xml @@ -4,25 +4,40 @@ jjm.one.Serilog.Sinks.SlackWebHook - + - extension that provides configuration chaining. + This class contains the extenstion functions to add the Slack logger configuration to a existing logger + configuration. - Instance of object. - Slack WebHook URL (required). - Name of the Slack channel in which the log message should be posted (recommended). + + + + extension that provides configuration chaining. + + Instance of object. + Slack WebHook URL. Slack username (recommended). - Slack user-icon emoji string (recommended). + Slack user-icon emoji string (optional). Slack user-icon image URI (optional). + + A containing the name of all Slack channels in which the log + message should be posted (recommended). + Slack message option 'DeleteOriginal' (optional). Slack message option 'LinkNames' (optional). Slack message option 'Markdown' (optional). - Slack message option 'Parse' as + Slack message option 'Parse' as Slack message option 'ReplaceOriginal' (optional). Slack message option 'ResponseType' (optional). Slack message option 'ThreadID' (optional). - Slack message attachment color list as (optional). - Slack message attachment footer icon list as (optional). + + Slack message attachment color list as + (optional). + + + Slack message attachment footer icon list as + (optional). + Add the short info attachment to the log message (optional). Display the short info attachment in short form (optional). Add the extended info attachment to the log message (optional). @@ -30,37 +45,67 @@ Add the short exception to the log message (optional). Display the exception attachment in short form (optional). Timeout for the connection to the Slack servers (optional). - The instance which the uses. - A containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 for message block list generation] for the Slack message generation (optional). - Size of the batch of messages that get send at once to Slack (recommended). + The instance which the uses. + + A for message + text generation (optional). + + + A + message attachment list generation + (optional). + + + A for + message block list generation (optional). + + + Size of the batch of messages that get send at once to Slack + (recommended). + Time period between sending of batches of messages (recommended). - Maximum size of the queue that stores the messages before the messages were send in batches to Slack (optional). - The absolute minimum a log message must have to be send to Slack (optional). + + Maximum size of the queue that stores the messages before the + messages were send in batches to Slack (optional). + + + The absolute minimum a log message must have to + be send to Slack (optional). + The template for the output format of the log messages (optional). - A to change the minimum a log message must have to be send to Slack (optional). + + A to change the minimum a + log message must have to be send to Slack (optional). + A format provider (optional). A Switch to change the activation status of the sink on the fly (optional). - Instance of object. + Instance of object. - + - extension that provides configuration chaining. + extension that provides configuration chaining. - Instance of object. - Slack WebHook URL. + Instance of object. + Slack WebHook URL (required). + Name of the Slack channel in which the log message should be posted (recommended). Slack username (recommended). - Slack user-icon emoji string (optional). + Slack user-icon emoji string (recommended). Slack user-icon image URI (optional). - A containing the name of all Slack channels in which the log message should be posted (recommended). Slack message option 'DeleteOriginal' (optional). Slack message option 'LinkNames' (optional). Slack message option 'Markdown' (optional). - Slack message option 'Parse' as + Slack message option 'Parse' as Slack message option 'ReplaceOriginal' (optional). Slack message option 'ResponseType' (optional). Slack message option 'ThreadID' (optional). - Slack message attachment color list as (optional). - Slack message attachment footer icon list as (optional). + + Slack message attachment color list as + (optional). + + + Slack message attachment footer icon list as + (optional). + Add the short info attachment to the log message (optional). Display the short info attachment in short form (optional). Add the extended info attachment to the log message (optional). @@ -68,37 +113,64 @@ Add the short exception to the log message (optional). Display the exception attachment in short form (optional). Timeout for the connection to the Slack servers (optional). - The instance which the uses. - A containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 for message block list generation] for the Slack message generation (optional). - Size of the batch of messages that get send at once to Slack (recommended). + The instance which the uses. + + A + + containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 + for message block list generation] for the Slack message generation (optional). + + + Size of the batch of messages that get send at once to Slack + (recommended). + Time period between sending of batches of messages (recommended). - Maximum size of the queue that stores the messages before the messages were send in batches to Slack (optional). - The absolute minimum a log message must have to be send to Slack (optional). + + Maximum size of the queue that stores the messages before the + messages were send in batches to Slack (optional). + + + The absolute minimum a log message must have to + be send to Slack (optional). + The template for the output format of the log messages (optional). - A to change the minimum a log message must have to be send to Slack (optional). + + A to change the minimum a + log message must have to be send to Slack (optional). + A format provider (optional). A Switch to change the activation status of the sink on the fly (optional). - Instance of object. + Instance of object. - + - extension that provides configuration chaining. + extension that provides configuration chaining. - Instance of object. + Instance of object. Slack WebHook URL. Slack username (recommended). Slack user-icon emoji string (optional). Slack user-icon image URI (optional). - A containing the name of all Slack channels in which the log message should be posted (recommended). + + A containing the name of all Slack channels in which the log + message should be posted (recommended). + Slack message option 'DeleteOriginal' (optional). Slack message option 'LinkNames' (optional). Slack message option 'Markdown' (optional). - Slack message option 'Parse' as + Slack message option 'Parse' as Slack message option 'ReplaceOriginal' (optional). Slack message option 'ResponseType' (optional). Slack message option 'ThreadID' (optional). - Slack message attachment color list as (optional). - Slack message attachment footer icon list as (optional). + + Slack message attachment color list as + (optional). + + + Slack message attachment footer icon list as + (optional). + Add the short info attachment to the log message (optional). Display the short info attachment in short form (optional). Add the extended info attachment to the log message (optional). @@ -106,98 +178,122 @@ Add the short exception to the log message (optional). Display the exception attachment in short form (optional). Timeout for the connection to the Slack servers (optional). - The instance which the uses. - A for message text generation (optional). - A message attachment list generation (optional). - A for message block list generation (optional). - Size of the batch of messages that get send at once to Slack (recommended). + The instance which the uses. + + A + + containing custom functions [Item1 for message text generation, Item2 for message attachment list generation, Item3 + for message block list generation] for the Slack message generation (optional). + + + Size of the batch of messages that get send at once to Slack + (recommended). + Time period between sending of batches of messages (recommended). - Maximum size of the queue that stores the messages before the messages were send in batches to Slack (optional). - The absolute minimum a log message must have to be send to Slack (optional). + + Maximum size of the queue that stores the messages before the + messages were send in batches to Slack (optional). + + + The absolute minimum a log message must have to + be send to Slack (optional). + The template for the output format of the log messages (optional). - A to change the minimum a log message must have to be send to Slack (optional). + + A to change the minimum a + log message must have to be send to Slack (optional). + A format provider (optional). A Switch to change the activation status of the sink on the fly (optional). - Instance of object. + Instance of object. + + + + This class implements the for the use with slack as an endpoint. + + + + + Initializes new instance of . + + Slack Sink Options object. + FormatProvider object. + HttpClient instance. + GenerateSlackMessageText function. + GenerateSlackMessageAttachments function. + GenerateSlackMessageBlocks function. + A Switch to change the activation status of the sink on the fly (optional). - instance for the SlackClient. + instance for the SlackClient. - instance. + instance. - object for this Sink. + object for this Sink. - to change the activation status of the sink on the fly. + to change the activation status of the sink on the fly. - object. + object. - Function to generate the text of the slack message. + Function to generate the text of the slack message. - Function to generate the attachments of the slack message. + Function to generate the attachments of the slack message. - Function to generate the blocks of the slack message. - - - - - Initializes new instance of . + Function to generate the blocks of the slack message. - Slack Sink Options object. - FormatProvider object. - HttpClient instance. - GenerateSlackMessageText function. - GenerateSlackMessageAttachments function. - GenerateSlackMessageBlocks function. - A Switch to change the activation status of the sink on the fly (optional). - Implements a function to close the and the . + Implements a function to close the and the + . - Implements and sends the with a to Slack. + Implements and sends the with a + to Slack. - A collection of . + A collection of . An Awaitable Task. - Implements . + Implements . An Awaitable Task. - This class provides functions for sending log events (serilog) to slack an implements therefor . + This class provides functions for sending log events (serilog) to slack an implements therefor + . - Initializes new instance of . + Initializes new instance of . Slack Sink Options object. FormatProvider object. @@ -209,33 +305,43 @@ - Provides a switch to set a slack sink active or inactive on the fly. + Provides a switch to set a slack sink active or inactive on the fly. - Enum to represent an activation status. + Enum to represent an activation status. + + + + + deactivates the sink + + + + + activates the sink - The current status. + The current status. - Initializes new instance of . + Initializes new instance of . - The . + The . - Class with default tools for message generation. + Class with default tools for message generation. - DEFAULT GenerateSlackMessageText function. + DEFAULT GenerateSlackMessageText function. The log event. A format provider @@ -244,7 +350,7 @@ - DEFAULT GenerateSlackMessageAttachments function. + DEFAULT GenerateSlackMessageAttachments function. The log event. A format provider @@ -253,7 +359,7 @@ - DEFAULT GenerateSlackMessageBlocks function. + DEFAULT GenerateSlackMessageBlocks function. The log event. A format provider @@ -262,157 +368,158 @@ - Class to contain all relevant options of this sink. + Class to contain all relevant options of this sink. + + + + + OPTIONAL: The template for the output format of the log messages. - Default value for the OutputTemplate. + Default value for the OutputTemplate. - Default value for the BatchSizeLimit. + Default value for the BatchSizeLimit. - Default value for the Period. + Default value for the Period. - Default value for the QueueLimit. + Default value for the QueueLimit. - Default value for the Timeout. + Default value for the Timeout. - REQUIRED: Slack WebHook URL. + REQUIRED: Slack WebHook URL. - OPTIONAL: Timeout for the connection to the Slack servers. + OPTIONAL: Timeout for the connection to the Slack servers. - RECOMMENDED: Slack username. + RECOMMENDED: Slack username. - RECOMMENDED: Slack user-icon emoji string. + RECOMMENDED: Slack user-icon emoji string. - OPTIONAL: Slack user-icon image URI. + OPTIONAL: Slack user-icon image URI. - RECOMMENDED: A containing the name of all Slack channels in which the log message should be posted. + RECOMMENDED: A containing the name of all Slack channels in which the log message + should be posted. - OPTIONAL: Slack message option 'DeleteOriginal'. + OPTIONAL: Slack message option 'DeleteOriginal'. - OPTIONAL: Slack message option 'LinkNames'. + OPTIONAL: Slack message option 'LinkNames'. - OPTIONAL: Slack message option 'Markdown'. + OPTIONAL: Slack message option 'Markdown'. - OPTIONAL: Slack message option 'Parse'. + OPTIONAL: Slack message option 'Parse'. - OPTIONAL: Slack message option 'ReplaceOriginal'. + OPTIONAL: Slack message option 'ReplaceOriginal'. - OPTIONAL: Slack message option 'ResponseType'. + OPTIONAL: Slack message option 'ResponseType'. - OPTIONAL: Slack message option 'ThreadID'. + OPTIONAL: Slack message option 'ThreadID'. - OPTIONAL: Slack message attachment color list as . + OPTIONAL: Slack message attachment color list as . - OPTIONAL: Slack message attachment footer icon list as . + OPTIONAL: Slack message attachment footer icon list as . - OPTIONAL: Add the short info attachment to the log message. + OPTIONAL: Add the short info attachment to the log message. - OPTIONAL: Display the short info attachment in short form. + OPTIONAL: Display the short info attachment in short form. - OPTIONAL: Add the extended info attachment to the log message. + OPTIONAL: Add the extended info attachment to the log message. - OPTIONAL: Display the extended info attachment in short form. + OPTIONAL: Display the extended info attachment in short form. - OPTIONAL: Add the short exception to the log message. + OPTIONAL: Add the short exception to the log message. - OPTIONAL: Display the exception attachment in short form. + OPTIONAL: Display the exception attachment in short form. - RECOMMENDED: Size of the batch of messages that get send at once to Slack. + RECOMMENDED: Size of the batch of messages that get send at once to Slack. - RECOMMENDED: Time period between sending of batches of messages. + RECOMMENDED: Time period between sending of batches of messages. - OPTIONAL: Maximum size of the queue that stores the messages before the messages were send in batches to Slack. - - - - - OPTIONAL: The template for the output format of the log messages. + OPTIONAL: Maximum size of the queue that stores the messages before the messages were send in batches to Slack. diff --git a/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Sinks.SlackWebHook.csproj b/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Sinks.SlackWebHook.csproj index eeb5ba5..5b8b681 100644 --- a/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Sinks.SlackWebHook.csproj +++ b/src/jjm.one.Serilog.Sinks.SlackWebHook/jjm.one.Serilog.Sinks.SlackWebHook.csproj @@ -1,48 +1,48 @@ - - netstandard2.0;netstandard2.1;net6;net7 - disable - enable - 2.0.2 - Jonas Merkle [JJM] - © by Jonas Merkle [JJM], 2023. - jjm.one.Serilog.Sinks.SlackWebHook - jjm.one.Serilog.Sinks.SlackWebHook - A basic Slack Sink for the Serilog framwork. - serilog, serilog-sink, slack, logging, csharp - https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook - git - https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook - README.md - LICENSE - True - True - + + netstandard2.0;netstandard2.1;net6;net7 + disable + enable + 2.1.0 + Jonas Merkle [JJM] + © by Jonas Merkle [JJM], 2023. + jjm.one.Serilog.Sinks.SlackWebHook + jjm.one.Serilog.Sinks.SlackWebHook + A basic Slack Sink for the Serilog framwork. + serilog, serilog-sink, slack, logging, csharp + https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook + git + https://github.com/jjm-one/jjm.one.Serilog.Sinks.SlackWebHook + README.md + LICENSE + True + True + - - latestmajor - .\jjm.one.Serilog.Extensions.Logging.Helpers.xml - - - latestmajor - .\jjm.one.Serilog.Extensions.Logging.Helpers.xml - - - - True - \ - - - True - \ - - + + latestmajor + .\jjm.one.Serilog.Extensions.Logging.Helpers.xml + + + latestmajor + .\jjm.one.Serilog.Extensions.Logging.Helpers.xml + + + + True + \ + + + True + \ + + - - - - - + + + + +