Logging in Wolfringo
A bot is a background process - most often it'll be running in background, without user interaction. For that reason, it's important to log information.
Wolfringo on its own doesn't have a logger. It also doesn't have "Log" event or anything like that - these events often are error-prone, and require additional work when setting up.
Instead Wolfringo has full support for ILogger interface. This makes it fully compatible with any relevant .NET logging library - Serilog, NLog, Log4Net, you name it! (Well, as long as it works with Microsoft.Extensions.Logging.ILogger).
Setting logging up
The exact way to set up logging might vary between libraries. Here I show a few examples.
All examples will use a special method called "CreateLogger" in Program.cs. It'll be called before creating IWolfClient and ICommandsService. We'll also add it to service provider. You can also register other services - check Dependency Injection guide for more info.
You should install Microsoft.Extensions.Logging NuGet package and then alter Program.cs as follows:
using Microsoft.Extensions.Logging;
private static async Task MainAsync(string[] args)
{
// ... other code ...
_client = new WolfClientBuilder()
.WithLogging(CreateLoggerFactory()) // pass a new logger factory
.WithCommands() // enable commands - they'll automatically use the same factory!
.Build();
// ... other code ...
}
private static ILoggerFactory CreateLoggerFactory()
{
// creating a logger factory depends on the library - see below!
}
Note
You can find example on GitHub.
Serilog
Serilog is one of the most popular (if not the most popular) logging libraries for .NET. It is my personal choice in my projects, so let's start with it!
First, using your NuGet package manager, install Serilog, Serilog.Extensions.Logging, and any of the sinks you want to use. For the sake of example, I will use Serilog.Sinks.File and Serilog.Sinks.Console.
Once downloaded, add following using directives to your Program.cs:
using Serilog;
Finally, populate your CreateLoggerFactory method:
private static ILoggerFactory CreateLoggerFactory()
{
Log.Logger = new LoggerConfiguration() // initialize Serilog configuration
.MinimumLevel.Information() // set minimum logs level to Information - feel free to change it to whatever suits your needs
.Enrich.FromLogContext() // add log context to logs - optional, but Wolfringo makes use of it!
.WriteTo.Console() // enable logging to console
.WriteTo.File("logs.txt") // enable logging to "logs.txt" files
.CreateLogger(); // create logger instance
return new LoggerFactory() // create factory for Microsoft.Extensions.Logging.ILogger
.AddSerilog(Log.Logger); // add our Serilog logger
}
Check Serilog repo on GitHub for more guides how to configure Serilog.
Note: remember to add logger instance to IWolfClient and ICommandsService via constructor - if you only set Log.Logger, Wolfringo will not be able to log anything!
Microsoft.Extensions.Logging
Microsoft extensions logging also has some providers. These tend to be quite basic, and using logging libraries such as Serilog, NLog or Log4Net is recommended - but it is enough to get most basic logs!
First, using your NuGet package manager, install Microsoft.Extensions.Logging.Console 2.0.0.
Once downloaded, populate your CreateLoggerFactory method:
private static ILoggerFactory CreateLoggerFactory()
{
return new LoggerFactory( // create Microsoft.Extensions.Logging.ILogger factory
new[] { new ConsoleLoggerProvider((_, level) // enable logging to console
=> level != LogLevel.Trace && level != LogLevel.Debug, // disable any logs below Information - feel free to change it to whatever suits yourneeds
true) } // do include log scopes
);
}
Warning
Note that this ConsoleLoggerProvider constructor is removed since version 3.0.0 of Microsoft.Extensions.Logging.Console. The new versions require use of IOptionsMonitor<TOptions>.
If you don't want to hack your way around it, you can either switch to versions 2.0.0-2.2.0 of Microsoft.Extensions.Logging.Console, or use a different logging library.
Other libraries
Many other libraries support Microsoft.Extensions.Logging. Some might support it out of the box, while some might have a wrapper package available (like Serilog). Check out their documentations to see how to use them!
Tip
If you're searching on ILogger support for your library, you can use a phrase like "ASP.NET Core" - it includes native support for Microsoft.Extensions.Logging, so many articles focus on this use-case.
Logging in Handlers and Services
Any service registered with Dependency Injection and all Handlers that CommandsService loads can use ILogger - simply inject it via constructor or method parameters. Check Dependency Injection guide for more details.
You can inject either ILogger or ILogger<TCategoryName> - if you use the generic one, the logs will use that type's full name as a category.
[CommandsHandler]
private class ExampleCommandsHandler
{
private readonly ILogger _log;
public ExampleCommandsHandler(ILogger<ExampleCommandsHandler> log)
{
this._log = log;
}
[Command("example")]
public async Task ExampleAsync(CommandContext context, ILogger log)
{
log.LogInformation("Received a message from {SenderID}", context.Message.SenderID.Value);
// can also use _log instead of log
}
}