Mikarsoft.TimeLogger 0.9.2

dotnet add package Mikarsoft.TimeLogger --version 0.9.2
                    
NuGet\Install-Package Mikarsoft.TimeLogger -Version 0.9.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Mikarsoft.TimeLogger" Version="0.9.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mikarsoft.TimeLogger" Version="0.9.2" />
                    
Directory.Packages.props
<PackageReference Include="Mikarsoft.TimeLogger" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Mikarsoft.TimeLogger --version 0.9.2
                    
#r "nuget: Mikarsoft.TimeLogger, 0.9.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Mikarsoft.TimeLogger@0.9.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Mikarsoft.TimeLogger&version=0.9.2
                    
Install as a Cake Addin
#tool nuget:?package=Mikarsoft.TimeLogger&version=0.9.2
                    
Install as a Cake Tool

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 of timestamps.bin it 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 = 0 to 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.2 365 6/30/2026
0.9.1 143 6/22/2026
0.9.0 123 6/22/2026

Initial release: binary time-indexed storage, background writer, retention, in-process live streaming, optional self-hosted HTML viewer, and fail-soft initialization.