Mikarsoft.TimeLogger
0.9.2
dotnet add package Mikarsoft.TimeLogger --version 0.9.2
NuGet\Install-Package Mikarsoft.TimeLogger -Version 0.9.2
<PackageReference Include="Mikarsoft.TimeLogger" Version="0.9.2" />
<PackageVersion Include="Mikarsoft.TimeLogger" Version="0.9.2" />
<PackageReference Include="Mikarsoft.TimeLogger" />
paket add Mikarsoft.TimeLogger --version 0.9.2
#r "nuget: Mikarsoft.TimeLogger, 0.9.2"
#:package Mikarsoft.TimeLogger@0.9.2
#addin nuget:?package=Mikarsoft.TimeLogger&version=0.9.2
#tool nuget:?package=Mikarsoft.TimeLogger&version=0.9.2
Mikarsoft.TimeLogger
A fast, self-contained logger for .NET 8 that persists entries to compact, binary, time-indexed files for near-instant time-range queries. It writes human-readable lines to the console synchronously, hands persistence off to a single background writer, and can optionally serve a built-in web UI for browsing and live-tailing logs — no external log stack required.
Features
- Binary, time-indexed storage — columnar fixed-width records in per-day folders, so range queries are a binary search rather than a full scan.
- Hour skip-index — a tiny per-day
hours.bin(one 6-byte record per hour that has entries) lets a query jump straight to the slice oftimestamps.binit needs, instead of searching the whole day. Built automatically and backfilled once for existing folders. - Non-blocking writes — entries are captured on the caller's thread and drained by one background writer; the queue is bounded and durable-flushed per batch.
- Live streaming — subscribe in-process for a live tail with batching and a dropped-entry counter when a consumer falls behind.
- Self-hosted UI — an optional embedded HTML viewer over
HttpListener(load, filter by level/category/text, and live poll), bound per-OS automatically. - Retention — old day-folders are pruned automatically; set
RetentionDays = 0to keep everything. - Tracing-aware — optionally captures trace/span ids on errors via an
ActivitySource. - Fail-soft — if the configured log path isn't writable, the logger reports the reason, sets
IsInitialized = false, and becomes a complete no-op instead of throwing — your app keeps running.
Install
dotnet add package Mikarsoft.TimeLogger
Quick start
With dependency injection
builder.Services.AddTimeLogger(o =>
{
o.RootPath = "/var/log/myapp"; // must exist and be writable
o.InstanceName = "MyApp";
o.RetentionDays = 30;
o.ShowUI = builder.Environment.IsDevelopment();
o.UI = new TimeLoggerUI(port: 8090, path: "/timelogger");
});
Inject ITimeLogger anywhere and log:
public sealed class Worker(ITimeLogger log)
{
public void Run()
{
if (!log.IsInitialized)
{
// Persistent storage unavailable; fall back to your own console logging.
}
log.LogInfo("Worker started", category: "Worker");
}
}
Without DI (static singleton)
TimeLogger.Configure(o =>
{
o.RootPath = "/var/log/myapp";
o.InstanceName = "MyApp";
});
TimeLogger.Instance.LogWarning("Disk getting full", "Storage");
Querying
var entries = log.Query(
from: DateTimeOffset.UtcNow.AddHours(-1),
to: DateTimeOffset.UtcNow,
type: LogType.Error);
The 24-hour window (trim24h)
Query caps its window to 24 hours from from by default — a later to is pulled back to
from + 24h. This is deliberate: a bug hunt almost always means narrowing in on a specific
time-range of a few hours, and the cap guarantees a query never spans more than two day-folders,
so the hour skip-index always applies and reads stay cheap.
If you genuinely need a wider range, lift the cap explicitly — at the cost of scanning more day-folders:
var entries = log.Query(
from: DateTimeOffset.UtcNow.AddDays(-7),
to: DateTimeOffset.UtcNow,
trim24h: false); // opt out of the 24h cap at your own cost
The self-hosted UI exposes the same switch via a trim24h=false query-string parameter on its
/query endpoint.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 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. |
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- System.Diagnostics.DiagnosticSource (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release: binary time-indexed storage, background writer, retention, in-process live streaming, optional self-hosted HTML viewer, and fail-soft initialization.