Skip to content

Chris-Wolfgang/Log-Compressor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

199 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Log-Compressor

A cross-platform .NET CLI (logc) for compressing log files. Built for unattended scheduled jobs on servers โ€” point it at a log directory, optionally filter by age, and it produces archives and removes the originals.

License: MIT .NET GitHub


โœจ Features

  • Two compression modes:
    • logc compress <path> โ€” produces one archive per source file (each log gets its own .zip / .tar.gz / .tar.br)
    • logc bundle <path> โ€” produces one archive containing many files (good for end-of-month rollups)
  • Three formats: ZIP (default), GZip (.tar.gz), Brotli (.tar.br)
  • Filtering:
    • -r|--recurse โ€” descend into subdirectories
    • --older-than <days> โ€” only files modified N+ calendar days ago
    • --min-datetime / --max-datetime โ€” explicit date-range window (mutually exclusive with --older-than)
  • Safe by default โ€” original is deleted only after the archive is written successfully
  • Self-contained single-file executable โ€” no .NET runtime required on the target server
  • Response-file support โ€” pass arguments via a config file for repeatable scheduled jobs
  • Structured logging via Serilog (console + file sinks); records what was compressed, skipped, errors, before/after sizes

๐Ÿš€ Quick Start

Status: v0.1.0 โ€” first release. Download a prebuilt archive from Releases, or build from source below.

Download & run (no .NET runtime required)

Each release attaches one self-contained archive per platform. Download the one for your OS (these links always resolve to the latest release):

Platform Download
Windows (x64) logc-win-x64.zip
Linux (x64) logc-linux-x64.tar.gz
macOS (Intel, x64) logc-osx-x64.tar.gz

Or browse every release on the Releases page.

Each archive contains the logc executable and its AppSettings.json โ€” keep the two together in the same folder (logc reads AppSettings.json from beside itself at startup).

Linux / macOS

# Download + extract (Linux x64 shown; swap in osx-x64 for macOS):
curl -L -o logc-linux-x64.tar.gz \
  https://github.com/Chris-Wolfgang/Log-Compressor/releases/latest/download/logc-linux-x64.tar.gz
mkdir -p ~/logc && tar -xzf logc-linux-x64.tar.gz -C ~/logc
cd ~/logc
chmod +x logc            # first run only
./logc compress /var/log/myapp --recurse --older-than 7

macOS may quarantine a downloaded binary. If you see "cannot be opened because the developer cannot be verified," run xattr -d com.apple.quarantine ./logc once.

Windows (PowerShell)

# Download + extract:
Invoke-WebRequest -Uri https://github.com/Chris-Wolfgang/Log-Compressor/releases/latest/download/logc-win-x64.zip -OutFile logc-win-x64.zip
Expand-Archive logc-win-x64.zip -DestinationPath C:\Tools\logc
cd C:\Tools\logc
.\logc.exe compress C:\Logs\myapp --recurse --older-than 7

Put the folder on your PATH to call logc from anywhere.

Build from source

git clone https://github.com/Chris-Wolfgang/Log-Compressor.git
cd Log-Compressor
git checkout v0.1.0
dotnet restore
dotnet build --configuration Release
dotnet test

Compress a single file

logc compress /var/log/myapp/app.log
# Produces: /var/log/myapp/app-2026-05-04_10-15-30.zip
# Then deletes: /var/log/myapp/app.log

Compress every old log in a directory (each to its own archive)

logc compress /var/log/myapp --recurse --older-than 7

Bundle a month's logs into a single archive

logc bundle /var/log/myapp --recurse --min-datetime 2026-04-01 --max-datetime 2026-04-30 --format gz
# Produces: /var/log/myapp/myapp-2026-04-01 to 2026-04-30.tar.gz

Output filename conventions

Mode Pattern
compress {filename}-{lastModified yyyy-MM-dd_HH-mm-ss}.{ext}
bundle {foldername}-{minModified} to {maxModified}.{ext}

๐Ÿ”ง CLI Reference

Shared flags (apply to both compress and bundle)

Flag Purpose Default
-r, --recurse Recurse subdirectories false
-o, --output <dir> Output directory source directory
--older-than <days> Only files modified N+ days ago (no filter)
--min-datetime <dt> Inclusive lower bound on last-modified date (no filter)
--max-datetime <dt> Inclusive upper bound on last-modified date (no filter)
-f, --format <fmt> zip | gz | brotli zip

--older-than is mutually exclusive with --min-datetime / --max-datetime. DateTime values are parsed using the local culture.

Response files

McMaster CommandLineUtils response-file support is enabled. Pass @path/to/args.txt and the file's lines become arguments โ€” useful for scheduled tasks where the command-line is awkward to express.

# example.rsp
compress
/var/log/myapp
--recurse
--older-than
7
--format
gz
--output
/archive/myapp
logc @example.rsp

๐Ÿงฉ Architecture

Three layers, all internal and exposed to the test project via InternalsVisibleTo:

Layer Examples
Command SharedOptions, Compress, Bundle (McMaster CommandLineUtils)
Service CompressService, BundleService, FileFilterService, FileNamingService, compression strategies
Abstraction IFileSystem, ICompressionStrategy, IFileFilter, IFileNamer

Compression strategies (ZipStrategy, GZipStrategy, BrotliStrategy) are dispatched via CompressionStrategyFactory. GZip and Brotli bundles use System.Formats.Tar.TarWriter to wrap many files into a single tar before compressing โ€” .tar.gz and .tar.br respectively.


๐ŸŽฏ Target Framework & Distribution

  • TFM: net10.0
  • Distribution: self-contained, per-platform archive attached to each GitHub Release (no .NET runtime required on the target)
  • Runtimes: win-x64, linux-x64, osx-x64
  • Not on NuGet: logc is an application, not a library, so it is not published as a NuGet package.

Releases are produced by the publish-binaries job in .github/workflows/release.yaml, which cross-compiles all three runtimes and uploads one archive each (.zip for Windows, .tar.gz for Linux/macOS).

Each archive contains two files:

File Purpose
logc (logc.exe on Windows) the self-contained single-file executable
AppSettings.json runtime configuration (logging sinks/levels) โ€” loaded from beside the executable at startup; required

To build the same artifact locally for one runtime:

dotnet publish src/Wolfgang.LogCompressor -c Release -r linux-x64 --self-contained -p:PublishSingleFile=true

The output lands in bin/Release/net10.0/linux-x64/publish/ as logc alongside AppSettings.json โ€” copy both to your server (keep them together) and run ./logc.


๐Ÿงช Quality

Metric Value
Unit tests (xunit 2.9.3, NSubstitute) 183
Integration tests (real file system, all OSes) 14
Code coverage 100% line, 95% branch; 90% per-module gate in CI
Benchmarks BenchmarkDotNet (compression-format throughput)

๐Ÿ“š Documentation


๐Ÿ›ฃ๏ธ Roadmap

Items deferred from v0.1.0:

  • decompress sub-command
  • Compressed-timestamp naming mode ({name}-{now} instead of {name}-{lastModified})
  • Custom name prefix (--name)
  • Glob-pattern input (*.log, app-*.log)
  • Mid-batch error-handling strategies (currently: skip & continue for compress, fail-fast for bundle)

๐Ÿค Contributing

Contributions welcome. The architecture is built around interfaces (ICompressionStrategy, IFileSystem, etc.) so adding a new compression format or filter is a single-file change plus tests. See CONTRIBUTING.md for code style and PR guidelines.


๐Ÿ“„ License

This project is licensed under the MIT License. See the LICENSE file for details.

About

A program for compressing log files for archive

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

โšก