Skip to content

From Log Fatigue to GoMergeLog4Net

Published: at 09:30 AM

I spend most of my time reading my customers logs. As an Escalation Engineer I always find that for almost any problem the answer is always buried somewhere in the logs.

In practice those logs are:

Split across dozens of files (​app.log, app.log.1, app.log.2, …). Rotated at different times on different machines. Written in Log4Net’s multi-line format, where a single stack-trace may stretch over 20 lines.

The classic workflow therefore looked like this :

  1. Grep through file #1.
  2. Copy the interesting fragment to a scratchpad/notepad++.
  3. Repeat for file #2, file #3 …
  4. Paste everything into a new document, try to sort by eye, realise a trace is broken in half, go back to step 1.

After years of repeating this dance i found that its a waste time :smile:.

(\approx 45 ,\text{min}) per issue spent “just getting the logs into shape”. If we assume (\approx 40) tickets / month → (\approx 30) working hours literally copy-pasting :cry:. Zero added value for the customer :unamused:.

The “aha”:bangbang: moment came during yet another 2 a.m. :clock2: bridge call: “If the pipeline is always the same, why can’t a tool do it?”

Enter GoMergeLog4Net.

Written in pure GO, GoMergeLog4Net is a single-purpose CLI that turns a chaotic folder of rotated Log4Net files into one perfectly ordered timeline.

Recursively finds every file matching *.log, *.log.N, no matter how deep they are nested. Flattens each multi-line entry into one physical line so it can be sorted correctly. Uses a worker pool (default (2 \times) CPU cores) to process files in parallel. Merges all lines, orders them by timestamp (two common Log4Net patterns supported). Re-expands each line to its original multi-line shape. Purges the temporary files, leaving a single [timestamp][_FinalMerged.log.

Because CGO is disabled the resulting binaries are completely static: drop the file on Windows, Linux or macOS (Intel + ARM) and run it.

No Docker image, no runtime, no DLL hell.

Typical session:

# Linux / macOS
./GoMergeLog4Net -p /var/log/myLogsFolder -workers 8

# Windows
.\GoMergeLog4Net.exe -p C:\temp\myLogsFolder -workers 8

Result:

# Linux / macOS
/var/log/myLogsFolder/ProcessedLogs/20240617_103015_FinalMerged.log
# Windows
C:\temp\myLogsFolder\ProcessedLogs\20240617_103015_FinalMerged.log

The lessons learned

Finding the problem/issue should mean READ traces, NOT re-assemble them. Automate the boring parts. A tool that eliminates friction for me might help other people, that is why i wrote this . Where to get it: GoMergeLog4Net