I would like to be able to use my Log to emit events through Hangfires context.console, so that I don't need to use context.writeline to output log events to my hangfire dashboard.
I have attempted to implement a specific serilog sink for this purpose. But as I need the PerformContext from hangfire (which is injected during runtime into the task method), I can't configure the log sink at application startup. I have attempted to create a new logger inside the task method, just to see if the sink actually works, and it does not - can anyone either see why it wouldn't work, or maybe suggest a different approach?
Here is the sink:
class HangfireContextSink : ILogEventSink {
private readonly IFormatProvider formatProvider;
private readonly PerformContext context;
public HangfireContextSink(IFormatProvider formatProvider, PerformContext context) {
this.formatProvider = formatProvider;
this.context = context;
}
public void Emit(LogEvent logEvent) {
var message = logEvent.RenderMessage(formatProvider);
context.WriteLine(ConsoleTextColor.Blue, DateTimeOffset.Now.ToString() + " " + message);
}
The sink configuration:
public static class SinkExtensions {
public static LoggerConfiguration HangfireContextSink(this LoggerSinkConfiguration loggerSinkConfiguration, PerformContext context, IFormatProvider formatProvider = null) {
return loggerSinkConfiguration.Sink(new HangfireContextSink(formatProvider, context));
}
}
The task method:
public static bool TestJob(PerformContext context) {
using (LogContext.PushProperty("Hangfirejob", "TestJob")) {
try {
using (var hangfireLog = new LoggerConfiguration().WriteTo.HangfireContextSink(context).CreateLogger()) {
var progress = context.WriteProgressBar("Progress");
for (int i = 0; i < 10; i++) {
context.WriteLine("Working with {0}", i);
progress.SetValue((i + 1) * 10);
Log.Debug("Test serilog");
hangfireLog.Debug("Test from hangfirelog");
Thread.Sleep(5000);
}
}
Log.Debug("Done testjob");
return true;
} catch (Exception ex) {
Log.Error(ex, "Error!");
return false;
}
}
}