JustSomeLogging 3.1.0
dotnet add package JustSomeLogging --version 3.1.0
NuGet\Install-Package JustSomeLogging -Version 3.1.0
<PackageReference Include="JustSomeLogging" Version="3.1.0" />
<PackageVersion Include="JustSomeLogging" Version="3.1.0" />
<PackageReference Include="JustSomeLogging" />
paket add JustSomeLogging --version 3.1.0
#r "nuget: JustSomeLogging, 3.1.0"
#:package JustSomeLogging@3.1.0
#addin nuget:?package=JustSomeLogging&version=3.1.0
#tool nuget:?package=JustSomeLogging&version=3.1.0
<p align="center"> <img src="icon-v2.png" alt="icon"/> </p>
Overview
JustSomeLogging (JSL) is an incredibly simple logging library for C#. Its built as a framework for you to implement logging your own way, without worrying about the abstract structural details. JSL is designed to revolve around the following pattern: Source → Handler → Sink. Dont want to design your own? You can use the pre-built ready to go implementations! If you do want to design your own, the pre-built types provide an excellent reference for how you should structure your design.
TLDR just let me install: go to install
Why JSL?
- Dead-simple configuration
- Entire control flow in your hands
- Small learning curve
- Awesome performance
Performance
With your own implementations, you completely control the performance! But what about the default implementations?
<img width="634" height="95" alt="image" src="https://github.com/user-attachments/assets/d252f270-3375-4147-97b5-e6f6dec595a5" />
<sub>Log_EnqueueOnly - measures the actual caller thread time taken to send off the log</sub>
<sub>Log_EndToEnd_Throughput - measures the average full cycle completion time, Source → Handler → Sink (no formatting in sink), in a high throughput concurrent processing situation (50k logs)</sub>
Compatibility
Built around
Microsoft.Extensions.Logging.ILogger
so it should be generally compatibly with most other logging systems.
Serialization compatability with MessagePack via the DataContract attribute.
Quick Start
Getting the default LogHandler
var handler = new LogHandler();
// or
var handler = LogHandler.Instance;
Configuring the default LogHandler
// LogHandler has one configuration
var handler = new LogHandler().HookToProcessExit();
// HookToProcessExit adds an event hook to AppDomain.Current.ProcessExit,
// which will call Dispose() on the handler
// By default, this singleton version always uses HookToProcessExit()
var handler = LogHandler.Instance;
// Why Dispose like this? Disposing the LogHandler here will halt the exit until all logs are flushed to their sinks
Create a log source
var source = new StdLogger()
{
Handler = handler, // Specify our handler here, OR leave null to use the singleton default LogHandler
};
Now add some sinks
#if DEBUG
// Required for DebugConsoleSink to work.
// This configuration is off by default!
LoggingConfiguration.EnableDebugConsoleSink = true;
#else
LoggingConfiguration.EnableDebugConsoleSink = false;
#endif
// A sink that routes to console
var consoleSink = new DebugConsoleSink()
{
Formatter = DefaultFormatter.Instance
};
// A sink that routes to various file destinations per source
var fileSink = new FileSink()
{
BufferedCountBeforeFlush = 100, // How many logs must be buffered before flushing the underlying streams
FlushToDisk = true,
FileMappings = [new FileSink.Source2FileMapping
{
FileName = "C:\\MyFile.txt",
SourceName = nameof(StdLogger), // You want the ILogSource.Name here, which in this case is the type name
Encoding = System.Text.Encoding.Unicode // Defaults to UTF8 if not specified
}],
Formatter = null // No formatter means singleton instance of DefaultFormatter
}.HookToProcessExit(); // File sink uses its own thread, and therefore can also be hooked to exit to flush
// Tip: You can interweave multiple source's logs into a single file if you want
// but for this example I just do one source one file
Add the desired sinks to your source instance
source.Sinks = [consoleSink, fileSink];
And run!
// This log will be sent to both the debug console, and to the file buffering thread to be saved
source.Info("Hello world!");
Details
What actually can a log object store?
Since logs in JSL are not just strings, additional context can be captured, formatted, and serialized.
LogObject uses the following implementation:
[DataContract]
public readonly struct LogObject : ILogObject
{
[DataMember(Name = "src")] required public ILogSource Source { get; init; }
[DataMember(Name = "msg")] required public string Message { get; init; }
[DataMember(Name = "time")] required public DateTime Timestamp { get; init; }
[DataMember(Name = "ll")] required public LogLevel LogLevel { get; init; }
[DataMember(Name = "thr")] public string? ThreadName { get; init; }
[DataMember(Name = "ex")] public Exception? Exception { get; init; }
public StackFrame? StackFrame { get; }
[DataMember(Name = "stkfs")] public string? StackFrameString { get; }
public LogObject(StackFrame? stackFrame = null)
{
StackFrame = stackFrame;
StackFrameString = stackFrame?.ToString();
}
}
You can make your own ILogObject to expand upon context storage if this is not enough.
Support
JSL is built on Netstandard 2.0, so it can work just about anywhere. JSL doesn't have any platform specific restrictions.
Installation
Get it on NuGet:
Use the command:
dotnet package add JustSomeLogging
Or from the releases:
Add a reference to the DLL
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.11)
- Microsoft.Extensions.Logging (>= 10.0.11)
- System.Threading.Channels (>= 10.0.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.