I have spent enough time looking at application logs to know that finding the actual error is sometimes harder than fixing it.
You run kubectl logs, get hundreds or thousands of lines, and start searching for something useful. If the application logs JSON, the output is technically structured but not particularly pleasant to read in a terminal. If you're debugging a request, you might end up grepping for a request ID and hoping you haven't missed anything important.
I wanted to make that workflow a little less painful, so I built LogLens.
It's a small Java CLI that reads logs from a file or stdin, makes them easier to read, and provides a couple of useful tools for investigating failures.
What does it actually do?
Take a JSON log entry like this:
{"timestamp":"2026-08-15T10:24:10.489Z","level":"error","trace_id":"9f2c-a1","message":"Connection to 10.0.3.14:5432 timed out after 30012ms","service":"api","status":500}
That's fine for a machine to process, but reading hundreds of entries in this format gets tedious.
LogLens turns it into something more useful in a terminal:
10:24:10 ERROR Connection to 10.0.3.14:5432 timed out after 30012ms req=9f2c-a1 service=api status=500
The information is still there. It's just easier to scan.
The part I care about most is that LogLens doesn't need an agent, a backend, or changes to the application producing the logs. It reads a file or stdin and writes the result to stdout.
That means it can fit into commands you're already using.
Following a request without the usual grep gymnastics
This was one of the main reasons I started the project.
I was working with a Spring Boot service that logged single-line JSON and included an X-Request-Id on every line. When something went wrong, investigating a single request meant searching through a lot of output to find the relevant entries.
LogLens has a --trace flag for that.
kubectl logs -f mypod | loglens --trace 9f2c-a1

Instead of manually filtering the stream, you can focus on entries associated with that correlation ID.
It also keeps stack traces attached to their parent error, so the exception details don't become disconnected from the log entry that explains what happened.
The idea isn't complicated. I just wanted that workflow to be one command instead of a collection of ad hoc filters.
What about an incident with hundreds of errors?
Filtering helps when you know what you're looking for. It's less helpful when you're not sure where to start.
Imagine a service is returning 500s and the logs contain repeated connection timeouts, refused connections, and warnings about an exhausted database connection pool.
Reading every entry individually isn't necessarily the best first step. It helps to understand the overall shape of the problem.
That's what the --stats option is for.
loglens --stats --quiet incident.log
The summary includes counts by log level and source, recurring problems grouped by similar messages, and the minute when errors peaked.
For example, several connection timeouts that differ only in IP address or duration can be grouped into one finding.
That gives you a shorter list of things to investigate before you start following individual requests.
I find this particularly useful as a starting point for an investigation. It doesn't tell you the root cause, but it can help you decide where to look next.
Logs don't always come in one format
Another thing I wanted to handle was mixed-format output.
A Kubernetes log stream might contain JSON from an application, klog output from a component, logfmt from another service, and a Java stack trace in the middle of it all.
LogLens supports formats including:
- JSON lines
- logfmt
- klog
- Airflow logs
- Python logging
- Log4j-style logs from tools such as Spark, Hadoop, and Kafka
- Generic timestamp and log-level formats
It processes each line independently and renders supported formats in a consistent shape.
If a line doesn't match a supported parser, it passes the line through rather than trying to guess what it means.
That fallback is important. A log tool shouldn't silently turn unfamiliar output into misleading data.
Keeping it small
I built LogLens in Java 21 using Picocli and Jackson.
The implementation is deliberately small. The project has eight Java classes and uses two runtime dependencies.
The parser runs through an ordered chain of format-specific parsers. Each line goes through that chain, and the first matching parser handles it. Stack trace continuation lines are attached to their parent entries.
The processing model is streaming, so LogLens doesn't need to load an entire log file into memory before producing output.
That also makes it suitable for live streams:
kubectl logs -f mypod | loglens
You can combine it with existing terminal tools instead of introducing another interface or service to maintain.
Why native binaries?
I wanted someone to be able to try LogLens without first installing a JDK.
The project started as a Java CLI, but distributing a JAR means asking users to have a compatible Java runtime available. For a small command-line utility, that's extra setup.
I used GraalVM native-image compilation to build standalone executables.
The current releases include binaries for macOS Apple Silicon, Linux x86-64, Linux ARM64, and Windows x86-64.
You can install it with:
curl -fsSL https://raw.githubusercontent.com/SushrutVaidya/loglens/main/install.sh | sh
Or build it yourself with JDK 21 or later:
git clone https://github.com/SushrutVaidya/loglens
cd loglens
mvn package
java -jar target/loglens.jar --help
The native build is available through the Maven native profile when using a GraalVM JDK.
This was a useful part of the project for me because it meant thinking about distribution and the experience of someone using the tool, not just the Java implementation.
What LogLens doesn't do
LogLens isn't a replacement for an observability platform.
It doesn't collect logs, store or index them, or provide a dashboard. Tools such as kubectl, tail, and your existing logging infrastructure still handle collection and retrieval.
It's a pipe-friendly utility for making the output easier to inspect.
There are also things I'd like to improve. The project is still early, and some log formats have gaps. Time-based filtering isn't implemented yet either.
I'd rather be clear about those limitations than pretend a small CLI can solve every logging problem.
Give it a try
The project is open source under the Apache 2.0 license.
GitHub: github.com/SushrutVaidya/loglens
Website [Loglens]
If you work with application logs, Kubernetes, or distributed services, I'd be interested to hear whether this fits into your workflow.
Bug reports, feature requests, and contributions are welcome. I'm especially interested in feedback about formats that don't parse correctly and workflows that could be simpler.
Thanks for checking it out.
Top comments (0)