GithubHelp home page GithubHelp logo

serilog-contrib / serilog-sinks-slack Goto Github PK

View Code? Open in Web Editor NEW
41.0 3.0 27.0 131 KB

A simple (yet customizable) Slack logging sink for Serilog

License: MIT License

C# 100.00%
serilog serilog-sink slack

serilog-sinks-slack's Issues

Feature Request: Filtering Logs based on Properties

I have two Slack Sinks that log to different Channels.

One Channel is for logs and the other is for alerts. Like below:

.WriteTo.Slack(
webhookUrl: "https://hooks.slack.com/services/hook1",
//hook for alerting CST
customChannel: "aletr",
customUsername: $"alert-bot",
customIcon: ":radioactive_sign:",
restrictedToMinimumLevel: LogEventLevel.Fatal
)
.WriteTo.Slack(
webhookUrl: "https://hooks.slack.com/services/hook2",
customChannel: "logs",
customUsername: $"log-bot",
customIcon: ":radioactive_sign:",
restrictedToMinimumLevel: LogEventLevel.Error
);

Currently I am managing this by making the alert Channels log level as Fatal. But I wan to log Certain Errors as Alerts.

But I cant do that directly as then I will have decrease the logLevel for Alert Channel and it will be polluted by all the Error Logs

Stacktrace field with too long message causes incorrect display

First of all thank you for the great sink.

I've used it and noticed that if the the stack trace of an exception is too long, the message gets cut and the formatting gets lost: the texts starts with ``` but the matching end markdown is never reached (I see ...). Would it be possible to limit the message correctly in order to display the stack trace correctly formatted? It may even be interesting to have a max char configuration for this (since I don't know if this is configurable in Slack).

Does not force flush on disposal

I have a console app that executes quite quickly and the number of messages is inconsistently relayed to Slack. (i.e out of 6 log messages, sometimes I might see 1 or 2 or 3 but never the full 6.

I understand the limitations of posting to a webhook but I thought that as long as I am disposing correctly that the sink would be fully flushed? Maybe a synchronous option if people really want this enforced?

Thoughts?

Enhancement: Allow option to add custom attachments

I have implemented this in our web app project. I want to log Post Api body details in the error to have details about the API call. But right now there are only some fixed parameters that are auto-generated.

Allow one channel per log level

It would be good if each log level (info, debug, trace, warning, error, critical, etc) could have their own channel specified to send messages to.

Sign the Assembly with a Strong Name

When building a strong-named assembly referencing this sink, one will get the warning below during the build.

CSC : warning CS8002: Referenced assembly 'Serilog.Sinks.Slack, Version=1.2.56.0, Culture=neutral, PublicKeyToken=null' does not have a strong name.

Signing the assembly with a strong name is a best practice, and would cause no side-effects whatsoever to anyone.

Support custom timestamp attachment format

Currently, the timestamp attachment is not formatted and is just written as DateTimeOffset.ToString(), which is depending on the culture of the current thread.

https://github.com/mgibas/serilog-sinks-slack/blob/master/Serilog.Sinks.Slack/SlackSink.cs#L89

new Field{Title = "Timestamp", Value = logEvent.Timestamp.ToString(), Short = _options.DefaultAttachmentsShortFormat}

Would it be possible to add support for custom timestamp attachment formats, so you can use any format you like, without having to rely on the current machine culture?

Slack webhook only working in dotnet core

When I set my logger up to sink to a webhook, it works when I test it inside visual studio.
The moment I build it however and run the executable, the webhook gets no messages whatsoever.
I've tried both Debug and Release mode, none seem to work.
[edit]: when running the build in .net 4.6.1 it doesn't work, however it works with .net core 1.1

Stack Overflow when using a newer version of Serilog.Sinks.PeriodicBatching

When using Serilog.Sinks.Slack together with the latest version of Serilog.Sinks.PeriodicBatching the call to Serilog.Log.CloseAndFlush() will crash with a StackOverflowException because the SlackSink Dispose method will call Dispose on PeriodicBatchSink which in turn calls Dispose on SlackSink, causing an endless loop.

This issue was discovered while using the Sink in a .NET Framework application where transient dependencies have to be explicitly included and where the dependency was updated to the latest version.

From my research into how PeriodicBatching code works and how other Sinks handle this it seems that maybe SinkSlack should be split up so that it doesn't pass a reference to itself to PeriodicBatchingSink. But I'm not sure how this change would affect people who use this library today.

Here is the sample code I used to reproduce the issue:

using Serilog;
using Serilog.Events;
using Serilog.Sinks.Slack;
using Serilog.Sinks.Slack.Models;

namespace SlackSinkStackOverflow;

internal static class Program
{
    private static void Main()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .WriteTo.Slack(new SlackSinkOptions
                { WebHookUrl = "https://hooks.slack.com/services/...", MinimumLogEventLevel = LogEventLevel.Error })
            .CreateLogger();

        try
        {
            Log.Information("Starting application");
        }
        catch (Exception exception)
        {
            Log.Fatal(exception, "Application terminated unexpectedly");
        }
        finally
        {
            // Causes a StackOverflowException
            Log.CloseAndFlush();
        }
    }
}

Serilog.Sinks.Slack version is 2.2.2.
Serilog.Sinks.PeriodicBatching version is 5.0.0

A suggested solution would look something similar to the following code:

public class SlackMessageFormatter
{
    private readonly SlackSinkOptions _options;
    private readonly ITextFormatter _textFormatter;

    public SlackMessageFormatter(SlackSinkOptions options, ITextFormatter textFormatter)
    {
        _options = options;
        _textFormatter = textFormatter;
    }

    public Message CreateMessage(LogEvent logEvent)
    {
        using (var textWriter = new StringWriter())
        {
            _textFormatter.Format(logEvent, textWriter);
            return new Message
            {
                Text = textWriter.ToString(),
                // Set other properties...
            };
        }
    }

    // Add methods for creating attachments, etc.
}
public class SlackClient : IDisposable
{
    private readonly HttpClient _httpClient;

    public SlackClient()
    {
        _httpClient = new HttpClient();
    }

    public async Task SendMessageAsync(string webhookUrl, Message message)
    {
        var json = JsonConvert.SerializeObject(message);
        await _httpClient.PostAsync(webhookUrl, new StringContent(json));
    }

    public void Dispose()
    {
        _httpClient.Dispose();
    }
}
public class SlackBatchingSink : IBatchedLogEventSink, IDisposable
{
    private readonly SlackMessageFormatter _formatter;
    private readonly SlackClient _client;
    private readonly SlackSinkOptions _options;

    public SlackBatchingSink(SlackMessageFormatter formatter, SlackClient client, SlackSinkOptions options)
    {
        _formatter = formatter;
        _client = client;
        _options = options;
    }

    public async Task EmitBatchAsync(IEnumerable<LogEvent> events)
    {
        foreach (var logEvent in events)
        {
            var message = _formatter.CreateMessage(logEvent);
            await _client.SendMessageAsync(_options.WebHookUrl, message);
        }
    }

    public Task OnEmptyBatchAsync()
    {
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _client.Dispose();
    }
}
public class SlackSink : ILogEventSink, IDisposable
{
    private readonly PeriodicBatchingSink _periodicBatchingSink;

    public SlackSink(SlackSinkOptions options, ITextFormatter textFormatter)
    {
        var formatter = new SlackMessageFormatter(options, textFormatter);
        var client = new SlackClient();
        var batchingSink = new SlackBatchingSink(formatter, client, options);

        _periodicBatchingSink = new PeriodicBatchingSink(batchingSink, options.ToPeriodicBatchingSinkOptions());
    }

    public void Emit(LogEvent logEvent)
    {
        _periodicBatchingSink.Emit(logEvent);
    }

    public void Dispose()
    {
        _periodicBatchingSink.Dispose();
    }
}

Benefits of the Redesign:

Each class now has a single responsibility, making the code easier to understand, maintain, and test.

The SlackSink no longer directly manages both its disposal and that of its components. The components (like SlackClient and PeriodicBatchingSink) handle their own lifecycles independently, reducing the risk of recursive disposal calls.

The SlackMessageFormatter and SlackClient can be reused or tested independently, providing more flexibility in the codebase.
Simplified Debugging:

If a stack overflow or other issue does occur, it’s easier to isolate the problem to a specific component, as each class now handles a distinct part of the process.

This redesign should help eliminate the stack overflow problem while also improving the overall architecture and maintainability of your logging infrastructure.

Missing license file

I would like to use this project but I need to know under which license I can use it.

Sink not writing to Slack

I have used your sink in my application and it was working fine, it has now stopped working at all, I get no exception and nothing strange in Output (visual Studio).
I then tried your example application with my Webhook and that isn't working either, I have tested my Slack Webhook in Command Prompt and it is working fine.
Is anyone else seeing this?

Can we show Event properties fullscreen?

Hi,

Here is Slack screenshots from pc, can we make Event property values fill the width so I don't need to scroll too much :) and it's hard to read the message too.
slack
slack1

Application exit before slack log is "slacked"

I've started using this project and I've noticed that alerts are not slacked before my console application exit.

I'm not sure if this is a bug? Or is this the expected behavior?

For now, I've added a thread sleep before exit but I'd like to know if it's a bug and if not how people using this library usually account for this...?

I've been using another slack sink (ServiceStack.Logging.Slack) and all slack alerts are slacked properly before the application exit without adding a thread sleep.

But I need to use ServiceStack.Logging.Serilog and if I want to use Slack I need to use serilog-sinks-slack with it.

It seems it's possible to do this without adding a Thread sleep since it works with the default ServiceStack.Logging.Slack.

Thanks for any pointers ;-)

Upgrading to the latest version of Serilog causes infinite loop

I haven't really dug into the problem yet but the symptoms first showed when a service wouldn't start up. Running the exe interactively resulted in:

Stack overflow.
Repeat 8733 times:
--------------------------------
   at Serilog.Sinks.PeriodicBatching.PeriodicBatchingSink.Dispose()
   at Serilog.Sinks.Slack.SlackSink.Dispose(Boolean)
   at Serilog.Sinks.Slack.SlackSink.Dispose()
--------------------------------
   at Serilog.LoggerConfiguration+<>c__DisplayClass33_0.<CreateLogger>g__Dispose|1()
   at Serilog.Extensions.Hosting.ReloadableLogger.Reload(System.Func`2<Serilog.LoggerConfiguration,Serilog.LoggerConfiguration>)
   at Serilog.SerilogServiceCollectionExtensions+<>c__DisplayClass3_0.<AddSerilog>b__0(System.IServiceProvider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier)
   at System.Collections.Concurrent.ConcurrentDictionary`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAdd(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, System.Func`2<Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,System.__Canon>)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(System.Type)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(System.IServiceProvider, System.Type)
   at Serilog.SerilogServiceCollectionExtensions+<>c__DisplayClass3_0.<AddSerilog>b__2(System.IServiceProvider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier)
   at System.Collections.Concurrent.ConcurrentDictionary`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAdd(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, System.Func`2<Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,System.__Canon>)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(System.Type)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(System.IServiceProvider, System.Type)
   at Microsoft.Extensions.Hosting.HostBuilder+<>c__DisplayClass35_0.<PopulateServiceCollection>b__2(System.IServiceProvider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier)
   at System.Collections.Concurrent.ConcurrentDictionary`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAdd(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, System.Func`2<Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,System.__Canon>)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(System.Type)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(System.IServiceProvider, System.Type)
   at Microsoft.Extensions.Hosting.HostBuilder.ResolveHost(System.IServiceProvider, System.Diagnostics.DiagnosticListener)
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at System.Linq.Utilities+<>c__DisplayClass2_0`3[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<CombineSelectors>b__0(System.__Canon)
   at System.Linq.Enumerable+SelectArrayIterator`2[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at System.Threading.Tasks.Task.WhenAll(System.Collections.Generic.IEnumerable`1<System.Threading.Tasks.Task>)
   at ServiceBase.ServiceHost+<RunBackgroundServices>d__1.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[ServiceBase.ServiceHost+<RunBackgroundServices>d__1, ServiceBase, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]](<RunBackgroundServices>d__1 ByRef)
   at ServiceBase.ServiceHost.RunBackgroundServices(System.Collections.Generic.IEnumerable`1<System.Action`2<Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.Extensions.DependencyInjection.IServiceCollection>>)
   at Program+<<Main>$>d__0.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[Program+<<Main>$>d__0, ItemWorker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]](<<Main>$>d__0 ByRef)
   at Program.<Main>$(System.String[])
   at Program.<Main>(System.String[])

Add Message Token as field to Slack message

today, only the Level and the Timestamp are hard coded sent to slack.
what if my log message look like this:
_logger.LogInformation("{ClientIp} has Joined", IP);
i would expect to have another field ClientIp (the same as ElasticSerach Sink does).
any chance to have this in the next drop?

PeriodicBatchingSink Duplicates Messages on Failure

The current implementation uses Serilog's PeriodicBatchingSink. It is set up to receive a message batch, loop the collection, sending each message as a separate HTTP request (a Slack limitation, the API only allows one message).

This isn't a good use case for PeriodicBatchingSink, because if we have a batch of 10 messages, and HTTP request 9 out of 10 is throttled by Slack and fails, the batching sink will retry the entire batch. This will duplicate messages 1 - 8 until all requests for the batch succeed.

What the sink really needs to do is post one at a time, in a way Serilog can retry. Needs some investigation - maybe we can just set the batch size to 1?

Sink not working in .NET Framework 4.5.2

Based on a reproducible report by @GFoley83 in issue #23 . The following code should work (and does on .NET Core) but does not when targetting .NET Framework 4.5.2

var config = new LoggerConfiguration().WriteTo.Slack("https://hooks.slack.com/services/XXX");
Log.Logger = config.CreateLogger();

Log.Logger.Information("Hello world");
Log.CloseAndFlush();

Add support for outputTemplate message formatting

Hi,

we recently introduced Slack in our company and I would love to output Error/Fatal log messages into a channel. I managed to do so with this sink in minutes. πŸ‘

While fiddling around with it I tried to set an outputeTemplate parameter to control the rendered text messages in the logs, but couldn't find any such parameter. Does this sink not support this?
I want to have several web services log into a single channel and without contextual information like the SourceContext or a RequestID in the log message it would be impossible to tell from which web service a log came or what's related.

Could you add this parameter to support the typical way of formatting the log messages in Serilog?

Kind regards
Michael

MinimumLogEventLevel is ignored

Does this issue relate to a new feature or an existing bug?
Bug
What version of Serilog.Sinks.Elasticsearch is affected?
2.0.3
What is the target framework and operating system?
Net Core 3.1
Please describe the current behavior?
When using minimumLogEventLevel via json based configuration the set value is neither checked nor used. All events are being sent.
a minimal demo of the problem

create empty project
install Serilog
install Serilog.Sinks.Slak

configure something like this:
{
"Name": "Slack",
"Args": {
"WebHookUrl": "https://hooks.slack.com/services/XXXXX",
"CustomChannel": "#errors",
"CustomUserName": "User",
"MinimumLogEventLevel": "Warning",
"BatchSizeLimit": 1,
"ShowExceptionAttachments": true
}
you will find all logs in the channel

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.