OzaLog 3.1.0
dotnet add package OzaLog --version 3.1.0
NuGet\Install-Package OzaLog -Version 3.1.0
<PackageReference Include="OzaLog" Version="3.1.0" />
<PackageVersion Include="OzaLog" Version="3.1.0" />
<PackageReference Include="OzaLog" />
paket add OzaLog --version 3.1.0
#r "nuget: OzaLog, 3.1.0"
#:package OzaLog@3.1.0
#addin nuget:?package=OzaLog&version=3.1.0
#tool nuget:?package=OzaLog&version=3.1.0
OzaLog
Disclaimer: OzaLog is not related to NLog (jkowalski's package). This is a separate, independent library.
Migrating from
Ozakboy.NLOGv2.x? See Migration Guide. The previous package has been deprecated and renamed toOzaLog.
A lean, lightweight .NET local file logging library with the simplest possible static API. No DI, no LoggerFactory, zero NuGet dependencies on net8+. Designed for high-throughput multi-threaded scenarios such as cryptocurrency tick streams.
Why OzaLog
- Simplest possible API —
LOG.Info_Log("hello")works without any setup - Single purpose — local file logging only, no abstractions
- Zero dependencies — net8+ targets have no NuGet dependencies
- HFT-tuned hot path — persistent FileStream pool with LRU eviction, cached timestamp, struct-based queue, drop-oldest backpressure
- Faster than NLog and Serilog in HFT-style multi-thread scenarios (see Benchmarks below)
What OzaLog is NOT
- ❌ Not a
Microsoft.Extensions.Loggingprovider — does not integrate withILogger<T>DI - ❌ Not a structured logger — no
{Property}placeholder capture - ❌ Not a multi-target logger — file output only (no Console / Database / remote sinks)
- ❌ Not configurable via XML / appsettings.json — programmatic configuration only
If any of the above is a hard requirement, use NLog or Serilog instead.
Supported Frameworks
- .NET 8.0 / 9.0 / 10.0 (LTS + current)
- .NET Standard 2.0 / 2.1 (legacy compatibility)
Dropped in OzaLog v3.0: .NET Framework 4.6.2, .NET 6.0, .NET 7.0 (all EOL).
Installation
dotnet add package OzaLog
Or via Package Manager Console:
Install-Package OzaLog
Quick Start
using OzaLog;
LOG.Info_Log("Hello, World!");
LOG.Error_Log("Something went wrong");
LOG.CustomName_Log("BTC", "tick: 67890.12");
That's it — no Configure call required (defaults work). For advanced configuration:
LOG.Configure(o =>
{
o.KeepDays = -7; // keep last 7 days of logs
o.SetFileSizeInMB(50); // split files at 50 MB
o.EnableAsyncLogging = true; // default true
o.EnableConsoleOutput = true; // also write to console
o.MaxOpenFileStreams = 100; // LRU upper bound
o.DiskFlushIntervalMs = 100; // periodic flush
o.EnableGlobalExceptionCapture = false; // opt-in: auto-log unhandled exceptions
o.OnDropped = () => Interlocked.Increment(ref _dropCount);
o.ConfigureAsync(a =>
{
a.MaxBatchSize = 1000;
a.MaxQueueSize = 100_000;
a.FlushIntervalMs = 100;
});
});
Log File Layout
{AppRoot}/
└── logs/
└── 20260509/ # yyyyMMdd date folder
└── LogFiles/ # type subfolder (configurable)
├── Info_Log.txt
├── Error_Log.txt
├── BTC_Log.txt # CustomName logs go here
└── ETH_Log.txt
Use options.LogPath to change the root, and options.TypeDirectories.*Path to give each level its own folder.
Logging Methods
Every level has the same 5 overloads:
LOG.Info_Log(string message);
LOG.Info_Log(string message, bool writeTxt);
LOG.Info_Log(string message, string[] args, bool writeTxt = true, bool immediateFlush = false);
LOG.Info_Log<T>(T obj, bool writeTxt = true, bool immediateFlush = false) where T : class;
LOG.Info_Log<T>(string message, T obj, bool writeTxt = true, bool immediateFlush = false) where T : class;
Available levels: Trace_Log / Debug_Log / Info_Log / Warn_Log / Error_Log / Fatal_Log.
For custom log buckets:
LOG.CustomName_Log("BTC", "tick: 67890.12"); // → BTC_Log.txt
LOG.CustomName_Log("API", "external call"); // → API_Log.txt
Exception Logging
try { /* code */ }
catch (Exception ex)
{
LOG.Error_Log(ex); // serialized as JSON
LOG.Error_Log("operation context", ex); // with custom message
}
Exception details (Type, Message, StackTrace, InnerException, Data dictionary, additional properties) are automatically captured.
Global Exception Capture (opt-in)
LOG.Configure(o => o.EnableGlobalExceptionCapture = true);
Subscribes to AppDomain.UnhandledException and TaskScheduler.UnobservedTaskException and logs them as Fatal with synchronous flush to ensure crash logs land on disk.
Note: This does not cover WPF/WinForms UI thread exceptions or ASP.NET Core middleware exceptions — those need to be hooked separately by the application.
Benchmarks
Measured against ZLogger 2.5.10, ZeroLog 2.6.1, Serilog 4.2.0 + Sinks.File 6.0.0 on .NET 10.0.7 (AMD Ryzen 9 9950X3D, BenchmarkDotNet 0.14):
S1 — Single short message
| Method | Mean | Allocated |
|---|---|---|
| OzaLog | 65.96 ns | 151 B |
| ZLogger | 219.53 ns | 278 B |
| ZeroLog | 12.19 ns | 0 B |
| Serilog | 168.87 ns | 160 B |
S3 — HFT 8 thread × 50 products × 2000 logs = 800 K writes
| Method | Mean | Allocated |
|---|---|---|
| OzaLog | 3,047 μs | 3.94 MB |
| ZLogger | 4,996 μs | 5.21 KB |
| ZeroLog | 649 μs | 3.35 KB |
| Serilog | 11,092 μs | 8.27 MB |
Verdict: OzaLog is faster than ZLogger and Serilog in both scenarios. ZeroLog wins on raw speed (it uses source generators for true zero-allocation), but OzaLog's static API is simpler.
→ Run benchmarks yourself: dotnet run -c Release --project OzaLog.Benchmarks
License
MIT License
Support
- GitHub Issues: Report Issues
- Pull Requests: Contribute Code
| 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 is compatible. 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 is compatible. 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 is compatible. 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 is compatible. |
| .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
- System.Text.Json (>= 9.0.16)
-
.NETStandard 2.1
- System.Text.Json (>= 9.0.16)
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v3.1.0 — Three new capabilities: customizable time/thread display, configurable output format, and a dedicated Quote pipeline for HFT tick/quote data. All additions are backward compatible (defaults preserve v3.0 behavior).
ADDED:
- Customizable time format: LogOptions.TimeFormat (free-form .NET DateTime format string, default "HH:mm:ss.fff").
- Independent thread ID / name display toggles: LogOptions.ShowThreadId (default true) + LogOptions.ShowThreadName (default false).
- High-precision timestamp opt-in: LogOptions.HighPrecisionTimestamp (Stopwatch-hybrid, reconstructs us-level precision from the 1ms cache).
- Multiple output formats: LogOptions.OutputFormat = Txt | Log | Json. JSON mode emits NDJSON with fixed schema {ts, lv, nm, tid?, tn?, msg, data?} and epoch_ms timestamps.
- Quote pipeline (opt-in via opt.ConfigureQuote(q => q.Enable = true)): LOG.Quote(...) and LOG.QuoteTicker(...) APIs with field names aligned to Binance REST 24hr Ticker schema (Last/LastQty/Bid/BidQty/Ask/AskQty/Open/PrevClose/High/Low/Volume/QuoteVolume).
- QuoteRecord (public readonly struct) with Extras (Dictionary, reflection-friendly) and ExtrasJson (raw JSON string, zero-overhead) — mutually exclusive.
- Filename auto-sanitization: filesystem-invalid chars in Symbol/Bucket replaced with '-' in filenames; original text preserved in content.
- 48 xUnit tests covering custom formats, NDJSON output, Quote schema/error paths, and sanitization.
IMPROVED:
- All Quote API overloads funnel through LOG.Quote(in QuoteRecord) for synchronous validation. Errors throw ArgumentException on the calling thread, not deferred to the dispatcher.
- LogFormatter retains the zero-alloc fast path for the default "HH:mm:ss.fff" format; other formats route through DateTime.ToString with FormatException fallback.
- FileStreamPool supports per-output extension (.txt / .log / .json) with corresponding part-detection.
TECHNICAL:
- System.Text.Json: 8.0.5 → 9.0.16 for netstandard2.0/2.1 (net8/9/10 still use BCL built-in — zero NuGet dependencies).
- Microsoft.SourceLink.GitHub: 8.0.0 → 10.0.300 (build-only, PrivateAssets=all, no consumer impact).
- New internal types: JsonLogFormatter, QuoteFormatter, QuoteFileStreamPool, QuoteLogHandler. Quote pipeline runs entirely in parallel with the main AsyncLogHandler.
- Verified across all 5 TargetFrameworks (netstandard2.0/2.1, net8.0/9.0/10.0) with 0 errors.
Full changelog: https://github.com/ozakboy/OzaLog/blob/main/docs/en/changelog.md
Migration guide (v2.x → v3.x): https://github.com/ozakboy/OzaLog/blob/main/docs/en/migration.md
Website: https://ozakboy.github.io/OzaLog/