Introducing the LogScope: the cleaner way of logging and tracing methods.
6/7/2021 by InstanceMaster
LogScope is not yet another logger. It is an extension of existing logging libraries that provides alternative way of logging and measuring a performance of critical parts of code. It also helps building a cleaner picture of executing asynchronous calls. It can used along with any existing logging provider.
The whole idea is based on a logging scope. Based on IDisposable
interface, scope:
- Logs it instantiation and disposal;
- Can log lines as part of the scope;
- Can be created from logging manager or as part of another scope (a nested scope);
Setup
LogScope package is available on NuGet (https://www.nuget.org/packages/DevInstance.LogScope/). The default implementation is based on simple Console.Log calls. There is an extension available for the standard Microsoft logger: https://www.nuget.org/packages/DevInstance.LogScope.Extensions.MicrosoftLogger/
So, add the package reference to your project:
PM>Install-Package DevInstance.LogScope.Extensions.MicrosoftLogger
Or
PM>Install-Package DevInstance.LogScope
We encourage people to write they own extension to the logging libraries they need. Please contribute to the open-source project: https://github.com/devInstance/LogScope.
Initialization
Initialization differs based on the type of the application and logging provider. If application uses dependency injection just call the AddConsoleScopeLogging extension method:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddConsoleScopeLogging(LogLevel.DEBUG);
...
}
For console application if can be instantiated by using DefaultScopeLogFactory
directly:
var manager = DefaultScopeLogFactory.CreateConsoleLogger(LogLevel.DEBUG);
For MicrosoftLogger extension, call:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMicrosoftScopeLogging(new DefaultFormattersOptions { ShowTimestamp = true, ShowThreadNumber = true });
...
}
Usage
Scope can be instantiated from the manager directly or from another scope. Later will create a nested scope. The following example demonstrates creation of the scope for the class directly from the manager and the nested method scopes for "MethodA" and "MethodB":
class TestClass
{
IScopeLog classScope;
public TestClass(IScopeManager manager)
{
classScope = manager.CreateLogger(this);
}
public void MethodA()
{
using (var methodScope = classScope.DebugScope())
{
methodScope.D("Wait for 200 msec");
Thread.Sleep(200);
methodScope.D("Done.");
using (var aScope = methodScope.DebugScope("a-scope"))
{
aScope.D("Inside of a scope");
}
MethodB();
}
}
private void MethodB()
{
using (var methodScope = classScope.DebugScope())
{
methodScope.D("Inside of method B scope");
Thread.Sleep(200);
}
}
}
Like most of logging techniques, every scope or log line should specify a logging level. LogScope provides a set of extension methods for creating scopes and logs such as DebugScope()
or TraceScope()
and D()
or T()
. So in example above, MethodA
logs few debug lines using D()
then creates another nested scope “a-scope” and logs another debug line inside that scope. Then it call MethodB
. Here is what will be the output:
21-01-29 23:07:24--> TestClass:MethodA
21-01-29 23:07:24 TestClass:MethodA:Wait for 200 msec
21-01-29 23:07:25 TestClass:MethodA:Done.
21-01-29 23:07:25--> TestClass:MethodA:a-scope
21-01-29 23:07:25 TestClass:MethodA:a-scope:Inside of a scope
21-01-29 23:07:25<-- TestClass:MethodA:a-scope, time:2.1252 msec
21-01-29 23:07:25--> TestClass:MethodB
21-01-29 23:07:25 TestClass:MethodB:Inside of method B scope
21-01-29 23:07:25<-- TestClass:MethodB, time:212.748 msec
21-01-29 23:07:25<-- TestClass:MethodA, time:480.5525 msec
Please refer to the documentation for more information: http://logscope.devinstance.net/