-
Notifications
You must be signed in to change notification settings - Fork 9
Logging
- Provide implementation agnostic logging contracts.
- Make loggers available through the composition.
The log manager is a service registered in the ambient services, with the ILogManager service contract. It provides the following method:
-
GetLogger(loggerName): ILogger: retrieves the logger with the provided name.
A logger implementes the ILogger contract, is identified by its name and is created by the log manager. For composition purposes, a generic ILogger<TService> service contract is provided to be imported by parts involved in composition.
It provides a single method which logs the provided arguments at the indicated level:
-
Log(level: LogLevel, exception: Exception, messageFormat: string, params args: object[]). Note to implementors: the exception may benull, so be cautious and handle this case too. For example, theLoggerExtensions.Logextension method passes anullexception.
For convenience, however, extension methods are provided to log fatal errors, errors, warnings, information, debug and trace data.
There are two kinds of components which can consume logging services:
- Composable components
- Non-composable components and static classes
To log anything, each consumer must firstly receive the logger it requires to consume its services by using specific means. Recommendations:
- Do not use directly specific loggers, like log4net or NLog, instead prefer the
ILoggerinterface. Reason: someday the circumstances may dictate to change the logging framework, and it will be a lot easier to change only the logger implementation compared to all logger specific code.
Composable components should just import the logger either through the constructor or as a writable property, with the type ILogger<ComponentType>, where ComponentType is the type of the composable component.
[SingletonAppServiceContract]
public interface IModelContainer
{
//...
}
public class ModelContainer : IModelContainer
{
/// <summary>
/// Gets or sets the logger.
/// </summary>
public ILogger<ModelContainer> Logger { get; set; }
}Non-composable components and static classes should use the extension method ambientServices.GetLogger<TypeToLog>() to get the logger for their type.
public static class ReflectionHelper
{
/// <summary>
/// Logger instance.
/// </summary>
private static readonly ILogger Logger = AmbientServices.Instance.GetLogger<ReflectionHelper>();
//...
}Caution: Make sure that at the time of calling GetLogger, the ambient services are properly initialized with the desired log manager, otherwise a logger doing nothing will be provided.
By default, a NullLoggerManager will be used, if not overwritten with a more meaningful implementation like the following:
- Kephas.Logging.NLog: use
ambientServices.WithNLogManager(). - Kephas.Logging.Serilog: use
ambientServices.WithSerilogManager(). - Kephas.Logging.Log4Net: use
ambientServices.WithLog4NetManager().