问题
In the WriteTo.Observer method I want to pass the formatted log message as it is rendered using the formatting template. How might I accomplish that? Thanks
class Program
{
static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.LiterateConsole()
.WriteTo.RollingFile("log-{Date}.txt")
.WriteTo.Observers(events => events.Do(evt => { Console.WriteLine($"Observed event {evt.MessageTemplate.Text}"); }).Subscribe())
.WriteTo.Observers(events => events.Do(evt => { LogHandler(evt.MessageTemplate.Text);}).Subscribe())
.CreateLogger();
Log.Logger.Information("Log msg from Main");
Console.ReadLine();
}
public static void LogHandler(string logMsg)
{
Console.WriteLine("LogHandler: " + logMsg); //I want the complete formatted log message as it would appear in a file i.e. "[10:20:14 INF] Log msg from DoNothing"
}
}
回答1:
I managed to resolve this all by myself as well as a couple of other questions I had about Serilog.
I originally posted this question about NLog and in the process of resolving it I discovered Serilog. I'm glad I did.
This answer illustrates several concepts:
1.) Calling a custom handler from the Logger
2.) Formatting the log message
3.) Including calling method name in the log message. Thanks and credit go to @MovGP0 for his answer found here.
class Program
{
static void Main(string[] args)
{
var outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";
Serilog.Formatting.Display.MessageTemplateTextFormatter tf = new Serilog.Formatting.Display.MessageTemplateTextFormatter(outputTemplate, CultureInfo.InvariantCulture);
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.CustomSink(tf, LogHandler)
.CreateLogger();
Log.Logger.Here().Information("Hello world");
Console.ReadLine();
}
public static void LogHandler(string logMsg)
{
Console.WriteLine("LogHandler: " + logMsg);
}
}
public class CustomSink : ILogEventSink
{
private readonly ITextFormatter _formatter;
private readonly Action<string>[] _handlers;
public CustomSink(ITextFormatter formatter, params Action<string>[] handlers)
{
_formatter = formatter;
_handlers = handlers;
}
public void Emit(LogEvent logEvent)
{
var buffer = new StringWriter(new StringBuilder(256));
_formatter.Format(logEvent, buffer);
string message = buffer.ToString();
foreach (Action<string> handler in _handlers)
handler(message);
}
}
public static class MySinkExtensions
{
public static LoggerConfiguration CustomSink(
this LoggerSinkConfiguration loggerConfiguration,
ITextFormatter formatter = null, params Action<string>[] handlers)
{
return loggerConfiguration.Sink(new CustomSink(formatter, handlers));
}
public static ILogger Here(this ILogger logger,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
return logger
.ForContext("MemberName", memberName)
.ForContext("FilePath", sourceFilePath)
.ForContext("LineNumber", sourceLineNumber);
}
}
来源:https://stackoverflow.com/questions/48268854/how-to-get-formatted-output-from-logevent