Enabling and Disabling Logging At Run Time
Sometimes when an issue happens in production, you will want to enable tracing for a specific type or namespace dynamically, without rebuilding the application. To prepare for this scenario, you need to add as much logging as reasonable at build time, but disable it by default at run time, and then enable it selectively.
This topic contains the following sections:
To enable or disable logging for a specific type or namespace:
Call the LoggingNamespaceSource.SetLevel(LogLevel) method to set the minimal severity for which logging is enabled. Calling this method will override the Level property for the current type or namespace and all nested types or namespaces.
PostSharp Logging does not implement a mechanism to enable or disable tracing through a configuration file. If you need to be able to configure logging without editing source code, you will have to implement yourself the code reading the configuration and calling the LoggingNamespaceSource.SetLevel(LogLevel) method with proper arguments. Alternatively, you can use back-end configuration mechanism (see below).
The following code will cause PostSharp to log only exceptions for the MyCompany namespace, but everything for the MyCompany.BusinessLayer namespace. The order of the two lines of code is important.
LoggingServices.DefaultBackend.GetSource(LoggingRoles.Tracing, "MyCompany").SetLevel(LogLevel.Error); LoggingServices.DefaultBackend.GetSource(LoggingRoles.Tracing, "MyCompany.BusinessLayer").SetLevel(LogLevel.Debug);
If you want to change the minimal severity for custom log records, use the role LoggingRoles.Custom additionally to LoggingRoles.Tracing.
Logging is enabled for all types and any severity by default.
By default, PostSharp generates code that allows you to dynamically enable or disable logging for a specific type and severity. However, even if logging is disabled, your CPU still needs to execute the code that evaluates whether logging is enabled.
By setting the AllowDynamicEnabling property of the logging profile to false, you can ask PostSharp to generate instructions that will be fully eliminated by the JIT compiler when logging is disabled. Therefore, the cost of inactive logging will be strictly zero.
When you set the AllowDynamicEnabling property to false, you need to call the LoggingNamespaceSource.SetLevel(LogLevel) method when the application initializes. Any change done after a logged type is JIT-compiled will be ignored for this specific type.
The following postsharp.config enables the JIT-compiler for the default profile.
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.postsharp.org/1.0/configuration"> <Logging xmlns="clr-namespace:PostSharp.Patterns.Diagnostics;assembly:PostSharp.Patterns.Diagnostics"> <Profiles> <LoggingProfile Name="default" AllowDynamicEnabling="False"/> </Profiles> </Logging> </Project>
Several logging frameworks offer a configuration mechanism that allows you to enable or disable logging. For a PostSharp log record to be emitted, two conditions need to be met: logging must be enabled by PostSharp (see above) and by the back-end logging framework.
Logging frameworks generally have a concept of category or source (the terminology can vary), which typically is just determined by a string (typically a type or namespace). The corresponding concept in PostSharp Logging is the LoggingTypeSource class, which is determined by two strings: a role (see LoggingRoles) and a type name or namespace.
By default, a LoggingTypeSource is mapped to a category according to the value of the Role property. If you want to control logging using the back-end framework, you will need to customize this mapping. This can be done by setting a property of the LoggingBackendOptions class. This property is different for each back-end framework.
When the mapping is properly set up, you enable or disable logging using the facilities implemented by the back-end logging framework.
The following code shows how to configure PostSharp Logging with log4net so that type name and namespace is used instead of the role.
((Log4NetLoggingBackend) LoggingServices.DefaultBackend).Options.GetLogger = ts => LogManager.GetLogger( ts.DisplayFullName );