LittyLogs.File 0.2.3

dotnet add package LittyLogs.File --version 0.2.3
                    
NuGet\Install-Package LittyLogs.File -Version 0.2.3
                    
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="LittyLogs.File" Version="0.2.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LittyLogs.File" Version="0.2.3" />
                    
Directory.Packages.props
<PackageReference Include="LittyLogs.File" />
                    
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 LittyLogs.File --version 0.2.3
                    
#r "nuget: LittyLogs.File, 0.2.3"
                    
#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 LittyLogs.File@0.2.3
                    
#: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=LittyLogs.File&version=0.2.3
                    
Install as a Cake Addin
#tool nuget:?package=LittyLogs.File&version=0.2.3
                    
Install as a Cake Tool

litty-logs ๐Ÿ”ฅ

yo your .NET logs are giving corporate dystopia energy rn and thats not it bestie. litty-logs fully rewrites all them boring built-in framework messages into gen alpha slang while also blessing your terminal with emojis and ANSI colors no cap

before (deadass boring) ๐Ÿ’€

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app

after (absolutely bussin) ๐Ÿ”ฅ

[๐Ÿ”ฅ info] [2026-02-18T21:45:00.420Z] [Lifetime] we vibing on http://localhost:5000 fr fr ๐ŸŽง
[๐Ÿ”ฅ info] [2026-02-18T21:45:00.421Z] [Lifetime] app is bussin and ready to slay bestie ๐Ÿ’… yeet Ctrl+C to dip out no cap
[๐Ÿ”ฅ info] [2026-02-18T21:45:00.421Z] [Lifetime] content root living at /app bestie ๐Ÿ“

installation

dotnet add package LittyLogs

# for xUnit test output (optional, separate package)
dotnet add package LittyLogs.Xunit

# for file sink with rotation and gzip compression (optional, separate package)
dotnet add package LittyLogs.File

# for webhook sink โ€” yeet logs to Matrix, Teams, etc (optional, separate package)
dotnet add package LittyLogs.Webhooks

# for the CLI tool that litty-fies build, test, publish, pack, and clean output
dotnet tool install --global LittyLogs.Tool

usage โ€” one line thats it thats the tweet

web api

using LittyLogs;

var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddLittyLogs(); // thats it bestie ๐Ÿ”ฅ
var app = builder.Build();
app.Run();

hosted service / background worker

using LittyLogs;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(logging => logging.AddLittyLogs())
    .ConfigureServices(services => services.AddHostedService<MyService>())
    .Build();

await host.RunAsync();

console script (the ten-liner speedrun)

using LittyLogs;
using Microsoft.Extensions.Logging;

using var factory = LoggerFactory.Create(logging =>
{
    logging.SetMinimumLevel(LogLevel.Trace);
    logging.AddLittyLogs();
});

var logger = factory.CreateLogger("MyScript");
logger.LogInformation("we in here bestie ๐Ÿ”ฅ");

xUnit tests

using LittyLogs.Xunit;
using Xunit;
using Xunit.Abstractions;

public class MyTests
{
    private readonly ILogger<MyTests> _logger;

    public MyTests(ITestOutputHelper output)
    {
        // one line to litty-fy your test output bestie ๐Ÿ’…
        _logger = output.CreateLittyLogger<MyTests>();
    }

    [Fact]
    public void MyTest()
    {
        _logger.LogInformation("this shows up litty-fied in test output ๐Ÿ”ฅ");
    }
}

JSON structured logging โ€” for when machines need to eat too ๐Ÿฝ๏ธ

same litty rewrites and emojis, but as valid JSON. your log aggregator is gonna love this no cap

using LittyLogs;

var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddLittyJsonLogs(); // structured JSON with emojis bestie ๐Ÿ”ฅ
var app = builder.Build();
app.Run();

output:

{"timestamp":"2026-02-19T10:45:00.420Z","level":"info","emoji":"๐Ÿ”ฅ","category":"Lifetime","message":"app is bussin and ready to slay bestie ๐Ÿ’… yeet Ctrl+C to dip out no cap"}

emojis in JSON? absolutely bussin โ€” JSON is UTF-8 native so every parser on earth handles it perfectly ๐Ÿ†

file sink โ€” yeet logs to disk with rotation and compression ๐Ÿ“

using LittyLogs.File;

var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddLittyFileLogs(opts =>
{
    opts.FilePath = "logs/app.log";
    opts.OutputFormat = LittyFileOutputFormat.Text;  // or Json for structured output
    opts.RollingInterval = LittyRollingInterval.Daily;
    opts.MaxFileSizeBytes = 10 * 1024 * 1024;        // 10MB then rotate
    opts.CompressionMode = LittyCompressionMode.Gzip; // compress rotated files ๐Ÿ—œ๏ธ
});
var app = builder.Build();
app.Run();

features that go hard:

  • async I/O โ€” Channel<string> based, your app thread never blocks on disk writes ๐Ÿ‘‘
  • text or JSON โ€” human-readable or machine-parseable, your choice bestie
  • size + time rotation โ€” daily, hourly, or size-based. rotated files get timestamps in the name
  • gzip compression โ€” old rotated files auto-compress to .gz, active file stays uncompressed
  • startup safeguard โ€” never auto-rotates on startup, only rotates before writing the next entry ๐Ÿ”’
  • no ANSI codes โ€” files never get terminal escape chars, thats cursed ๐Ÿ’€

webhook sink โ€” yeet logs to Matrix and Teams chat ๐Ÿช

critical error hits? your group chat knows about it instantly, formatted all nice with emojis

using LittyLogs.Webhooks;

var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddLittyMatrixLogs("https://hookshot.example.com/webhook/abc123"); // one liner bestie ๐ŸŸฃ
var app = builder.Build();
app.Run();

with full options:

builder.Logging.AddLittyMatrixLogs("https://hookshot.example.com/webhook/abc123", opts =>
{
    opts.MinimumLevel = LogLevel.Warning;   // only Warning+ goes to chat (default)
    opts.Username = "LittyLogs";            // bot display name in chat
    opts.BatchSize = 10;                    // max messages per batch
    opts.BatchInterval = TimeSpan.FromSeconds(2); // flush interval
});

features that go hard:

  • async batching โ€” Channel<T> based, groups messages by interval (2s) or count (10), your app thread never blocks ๐Ÿ‘‘
  • Polly resilience โ€” retry with exponential backoff, circuit breaker, per-request timeout via Microsoft.Extensions.Http.Resilience ๐Ÿ”’
  • best-effort โ€” if the webhook is bricked after retries, we drop the batch and keep vibing. never crashes your app no cap
  • min level filtering โ€” default Warning so your chat dont get spammed with trace logs ๐Ÿ’€
  • IHttpClientFactory โ€” proper socket management, named client "LittyWebhooks" for custom config
  • Matrix hookshot format โ€” markdown messages with emojis, exceptions in code blocks
Teams Adaptive Cards ๐ŸŸฆ
builder.Logging.AddLittyTeamsLogs("https://your-org.webhook.office.com/webhook/..."); // one liner bestie ๐ŸŸฆ

with full options:

builder.Logging.AddLittyTeamsLogs("https://your-org.webhook.office.com/webhook/...", opts =>
{
    opts.MinimumLevel = LogLevel.Warning;   // only Warning+ goes to chat (default)
    opts.Username = "LittyLogs";            // shows in the card header
    opts.BatchSize = 10;                    // max messages per batch
    opts.BatchInterval = TimeSpan.FromSeconds(2); // flush interval
});

Teams-specific features that go hard:

  • Adaptive Card v1.5 โ€” proper card format, not just plain text messages ๐Ÿ’…
  • severity-colored containers โ€” green (info), yellow (warning), red (error/critical), neutral (trace/debug) ๐ŸŽจ
  • monospace TextBlocks โ€” log lines render in monospace for that dashboard energy
  • exception blocks โ€” subtle monospace blocks underneath the log line, dont overpower the message
  • same batching + resilience โ€” Channel<T> batching, Polly retry, circuit breaker, best-effort delivery

what gets litty-fied

all the boring framework messages you see every dotnet run:

boring version ๐Ÿ’€ litty version ๐Ÿ”ฅ
Application started. Press Ctrl+C to shut down. app is bussin and ready to slay bestie ๐Ÿ’… yeet Ctrl+C to dip out no cap
Now listening on: {url} we vibing on {url} fr fr ๐ŸŽง
Content root path: {path} content root living at {path} bestie ๐Ÿ“
Hosting environment: {env} we in our {env} era rn โœจ
Application is shutting down... app said aight imma head out ๐Ÿ’€
Request starting {details} yo a request just slid in: {details} ๐Ÿ‘€
Request finished {details} request finished cooking: {details} ๐Ÿณ

plus hosting lifecycle, endpoint routing, and more fr fr

log level emojis

level emoji vibe
Trace ๐Ÿ‘€ lowkey peeking
Debug ๐Ÿ” investigating bestie
Information ๐Ÿ”ฅ bussin as usual
Warning ๐Ÿ˜ค not it
Error ๐Ÿ’€ big L
Critical โ˜ ๏ธ its giving death

options โ€” configure the vibe

builder.Logging.AddLittyLogs(options =>
{
    options.RewriteMessages = true;     // rewrite framework messages (default: true, thats the whole point)
    options.UseColors = true;           // ANSI colors (default: true)
    options.ShortenCategories = true;   // yeet namespace bloat (default: true)
    options.UseUtcTimestamp = true;     // UTC timestamps (default: true, international rizz)
    options.TimestampFormat = "yyyy-MM-ddTHH:mm:ss.fffK"; // ISO 8601 with milliseconds (default)
    options.TimestampFirst = false;     // false = RFC 5424 (level first), true = observability style (timestamp first)
});

dotnet litty CLI tool โ€” litty-fy your build, test, publish, pack, and clean output ๐Ÿงช

your app logs are litty but dotnet build, dotnet test, dotnet publish, dotnet pack, and dotnet clean output is still giving corporate energy? install the tool and never look at boring terminal output again no cap

# install the tool
dotnet tool install --global LittyLogs.Tool

# litty-fy your test output (auto-shows ITestOutputHelper output too)
dotnet litty test

# litty-fy your build output
dotnet litty build

# litty-fy your publish output
dotnet litty publish

# litty-fy your pack output โ€” nupkgs go brrr ๐Ÿ“ฆ
dotnet litty pack

# litty-fy your clean output โ€” watch artifacts get yeeted in style ๐Ÿ—‘๏ธ
dotnet litty clean

# all args pass through to the underlying dotnet command
dotnet litty test --filter "FullyQualifiedName~MyTests"
dotnet litty build -c Release
dotnet litty publish -c Release --self-contained
dotnet litty pack -c Release
dotnet litty clean -c Release

before (boring test output) ๐Ÿ’€

Passed!  - Failed:     0, Passed:    66, Skipped:     0, Total:    66, Duration: 80 ms - LittyLogs.Tests.dll (net10.0)

after (bussin test output) ๐Ÿ”ฅ

  [xUnit.net] scouting for tests in LittyLogs.Tests ๐Ÿ”
  [xUnit.net] found the squad in LittyLogs.Tests ๐Ÿ“‹
  [xUnit.net] lets gooo LittyLogs.Tests is cooking ๐Ÿ”ฅ
  โœ… LittyLogs.Tests.MyTest.SomeTest [26 ms]
  [xUnit.net] LittyLogs.Tests absolutely ate no crumbs ๐Ÿ’…

  all tests ate and left no crumbs ๐Ÿ†
  total vibes checked: 66
  ate: 66 โœ…
  cooked in 0.5 Seconds โฑ๏ธ

your own logs stay untouched

litty-logs only rewrites known framework messages. your custom log messages pass through with the bussin formatting (emojis, colors, short categories) but the actual message text stays exactly how you wrote it no cap

logger.LogInformation("my custom message stays exactly like this");
// output: [๐Ÿ”ฅ info] [2026-02-18T21:45:00.420Z] [MyService] my custom message stays exactly like this

examples

seven example projects in examples/ so you can see litty-logs in every scenario:

example what it shows run it
WebApi startup demo with level-first โ†’ timestamp-first โ†’ JSON, then server runs just example web
HostedService startup demo with both timestamp modes, then background service vibes just example hosted
Console side-by-side text + JSON output comparison just example console
Xunit litty-fied xUnit test output with all log levels + TimestampFirst test just example xunit
Json structured JSON logging with both timestamp configs just example json
FileSink file sink with level-first โ†’ timestamp-first โ†’ JSON, reads em all back just example filesink
Webhooks dual webhook sink (Matrix + Teams) with mock listeners or live endpoints just example webhooks

every example auto-showcases ALL the modes when you run it โ€” no hidden flags, no secret handshakes. you run it, you see everything ๐Ÿ’…

the webhooks example runs three demos: Matrix-only, Teams-only, and dual mode (both firing simultaneously). set HOOKSHOT_URL and/or TEAMS_WEBHOOK_URL in .env to go live โ€” any sink without a URL falls back to a local mock listener so it always works bestie ๐Ÿช๐Ÿ”ฅ

development โ€” for the contributing besties ๐Ÿ› ๏ธ

just recipes

this project uses just as the task runner. here are the vibes:

recipe what it does
just build build the whole solution with litty-fied output ๐Ÿ—๏ธ๐Ÿ”ฅ
just test run all tests with litty-fied output ๐Ÿงช๐Ÿ”ฅ
just publish publish with litty-fied output ๐Ÿ“ค๐Ÿ”ฅ
just pack pack all five NuGet packages with litty-fied output ๐Ÿ“ฆ๐Ÿ”ฅ
just clean yeet all build artifacts with litty-fied output ๐Ÿ—‘๏ธ๐Ÿ”ฅ
just bump patch bump the patch version (also: minor, major)
just bump-pre dev.1 slap a pre-release label on (e.g. 0.1.0-dev.1)
just release patch full gitflow release โ€” bump, branch, finish, push ๐Ÿš€
just release-current gitflow release without bumping (for first release etc.)
just re-release nuke old releases + tags everywhere, re-do the current version ๐Ÿ”„
just release-dev patch dev/pre-release โ€” bump + label + ship (e.g. 0.1.1-dev) ๐Ÿงช
just hotfix patch start a gitflow hotfix branch off main ๐Ÿš‘
just finish finish whatever gitflow branch youre on (hotfix/release/support) + push ๐Ÿ
just nuget-push manually push packages to nuget.org
just example <name> run an example โ€” web, hosted, console, xunit, json, filesink, webhooks ๐Ÿ”ฅ
just setup-completions install shell tab-completions for just example <tab>

shell completions

tab-complete just example <tab> to see all available examples. works with zsh and bash:

# auto-install to your shell rc file
just setup-completions

# or source manually
source completions/just.zsh   # zsh
source completions/just.bash  # bash

versioning

version lives in one place: Directory.Build.props. all five packages inherit from it. we use gitflow via the git flow CLI โ€” main is production, develop is the integration branch, releases and hotfixes get their own branches ๐Ÿ”ฅ

release flow (gitflow)

# from develop โ€” full gitflow ceremony (bump, branch, finish, push โ€” all in one command)
just release patch    # 0.1.0 โ†’ 0.1.1, pushes everything, pipeline goes brrr
just release minor    # 0.1.0 โ†’ 0.2.0
just release major    # 0.1.0 โ†’ 1.0.0

# dev/pre-release for testing the pipeline
just release-dev patch         # 0.1.0 โ†’ 0.1.1-dev
just release-dev minor beta.1  # 0.1.0 โ†’ 0.2.0-beta.1

# release the current version without bumping (e.g. first release)
just release-current

all release commands auto-push develop + main + tag to origin when done. no manual git push needed fr fr ๐Ÿ”ฅ

hotfix flow

# from main โ€” start a hotfix when something is bricked in prod
just hotfix patch

# make your fix, commit it, then finish + push
just finish

just finish auto-detects if youre on a hotfix, release, or support branch, does git flow finish, and pushes everything. one command to rule them all ๐Ÿ

CI/CD โ€” triple release pipeline ๐Ÿš€

forgejo actions on a self-hosted runner handles the whole squad:

  • CI (ci.yml) โ€” builds, tests (with litty output ๐Ÿ”ฅ), and packs on every push/PR to develop and main. if this fails your code is bricked and you should not merge no cap
  • Release (release.yml) โ€” triggered by v* tags. the full pipeline hits THREE destinations:
    1. nuget.org โ€” all five .nupkg files with --skip-duplicate so retries dont catch Ls
    2. forgejo releases โ€” via Gitea API with .nupkg assets attached ๐Ÿ 
    3. github mirror releases โ€” via gh CLI with .nupkg assets on the mirror repo ๐Ÿ™

pipeline features that go hard:

  • fully retryable โ€” every step checks if work is already done before doing it again. re-run from the forgejo UI all day, zero errors ๐Ÿ”„
  • pre-release auto-detection โ€” versions with - (like 0.1.0-dev, 1.0.0-beta.1) auto-flag as pre-release on both platforms ๐Ÿงช
  • changelog extraction โ€” release notes auto-pulled from CHANGELOG.md for that professional rizz ๐Ÿ“œ
  • version sanity check โ€” tag must match Directory.Build.props or the pipeline tells you its not it ๐Ÿ’€

see docs/runner-setup.md for runner setup and required secrets no cap

manifesting these features ๐Ÿง โœจ

stuff that would go absolutely crazy but aint started yet. vibes only rn no cap

  • ๐Ÿ’ฌ Slack webhook sink โ€” Block Kit formatter for the Slack besties
  • ๐ŸŸฃ Matrix Client-Server API โ€” direct room messages for power users who want full HTML control instead of hookshot
  • ๐ŸŽจ custom webhook templates โ€” user-defined message format strings so you can make it look however you want
  • ๐Ÿ—œ๏ธ zstd compression โ€” for file sink rotation (gzip is cool but zstd is faster and smaller fr fr)
  • ๐Ÿ“Š structured log enrichment โ€” auto-attach machine name, environment, correlation IDs to webhook messages

wanna see one of these happen? PRs are open bestie, or just vibe in the issues ๐Ÿ’…

security ๐Ÿ”’

litty-logs takes security seriously even though we dont take ourselves seriously no cap. heres the tldr:

  • webhook URL validation โ€” SSRF prevention, only http/https schemes allowed
  • log injection prevention โ€” newlines in messages get sanitized to spaces in text output
  • content injection prevention โ€” webhook messages get HTML-encoded (Matrix) or rendered as plain text (Teams Adaptive Cards), no tracking pixels or phishing links in your chat
  • HTTP category filtering โ€” prevents infinite recursion AND accidental webhook URL token exposure

full details in docs/security.md

found a vulnerability? dont yeet it in a public issue โ€” open a security advisory instead bestie ๐Ÿ”’

license

MIT โ€” share the vibes bestie โœŒ๏ธ

Product Compatible and additional computed target framework versions.
.NET 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. 
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.2.3 127 2/23/2026
0.2.2 92 2/22/2026
0.2.1 110 2/22/2026
0.2.0 89 2/22/2026
0.1.4 99 2/20/2026
0.1.3 90 2/19/2026
0.1.2-dev 88 2/19/2026
0.1.1-dev 86 2/19/2026
0.1.0-dev 85 2/19/2026