<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sushrut Vaidya</title>
    <description>The latest articles on DEV Community by Sushrut Vaidya (@sushrutvaidya).</description>
    <link>https://dev.to/sushrutvaidya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4118638%2F0511d9b9-ab23-4d8f-bcc2-8bd10c15e76f.jpeg</url>
      <title>DEV Community: Sushrut Vaidya</title>
      <link>https://dev.to/sushrutvaidya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sushrutvaidya"/>
    <language>en</language>
    <item>
      <title>I Built a Java CLI to Make Kubernetes Logs Easier to Read</title>
      <dc:creator>Sushrut Vaidya</dc:creator>
      <pubDate>Sun, 25 Oct 2026 18:29:39 +0000</pubDate>
      <link>https://dev.to/sushrutvaidya/i-built-a-java-cli-to-make-kubernetes-logs-easier-to-read-2kkb</link>
      <guid>https://dev.to/sushrutvaidya/i-built-a-java-cli-to-make-kubernetes-logs-easier-to-read-2kkb</guid>
      <description>&lt;p&gt;I have spent enough time looking at application logs to know that finding the actual error is sometimes harder than fixing it.&lt;/p&gt;

&lt;p&gt;You run &lt;code&gt;kubectl logs&lt;/code&gt;, 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.&lt;/p&gt;

&lt;p&gt;I wanted to make that workflow a little less painful, so I built &lt;a href="https://github.com/SushrutVaidya/loglens" rel="noopener noreferrer"&gt;LogLens&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it actually do?
&lt;/h2&gt;

&lt;p&gt;Take a JSON log entry like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2026-08-15T10:24:10.489Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"trace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"9f2c-a1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Connection to 10.0.3.14:5432 timed out after 30012ms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's fine for a machine to process, but reading hundreds of entries in this format gets tedious.&lt;/p&gt;

&lt;p&gt;LogLens turns it into something more useful in a terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10:24:10  ERROR  Connection to 10.0.3.14:5432 timed out after 30012ms  req=9f2c-a1  service=api  status=500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The information is still there. It's just easier to scan.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;That means it can fit into commands you're already using.&lt;/p&gt;
&lt;h2&gt;
  
  
  Following a request without the usual grep gymnastics
&lt;/h2&gt;

&lt;p&gt;This was one of the main reasons I started the project.&lt;/p&gt;

&lt;p&gt;I was working with a Spring Boot service that logged single-line JSON and included an &lt;code&gt;X-Request-Id&lt;/code&gt; on every line. When something went wrong, investigating a single request meant searching through a lot of output to find the relevant entries.&lt;/p&gt;

&lt;p&gt;LogLens has a &lt;code&gt;--trace&lt;/code&gt; flag for that.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &lt;span class="nt"&gt;-f&lt;/span&gt; mypod | loglens &lt;span class="nt"&gt;--trace&lt;/span&gt; 9f2c-a1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftz2hhgazoaiayz0ldk20.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftz2hhgazoaiayz0ldk20.gif" alt="LogLens demo" width="790" height="560"&gt;&lt;/a&gt;&lt;br&gt;
Instead of manually filtering the stream, you can focus on entries associated with that correlation ID.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The idea isn't complicated. I just wanted that workflow to be one command instead of a collection of ad hoc filters.&lt;/p&gt;
&lt;h2&gt;
  
  
  What about an incident with hundreds of errors?
&lt;/h2&gt;

&lt;p&gt;Filtering helps when you know what you're looking for. It's less helpful when you're not sure where to start.&lt;/p&gt;

&lt;p&gt;Imagine a service is returning 500s and the logs contain repeated connection timeouts, refused connections, and warnings about an exhausted database connection pool.&lt;/p&gt;

&lt;p&gt;Reading every entry individually isn't necessarily the best first step. It helps to understand the overall shape of the problem.&lt;/p&gt;

&lt;p&gt;That's what the &lt;code&gt;--stats&lt;/code&gt; option is for.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;loglens &lt;span class="nt"&gt;--stats&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt; incident.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The summary includes counts by log level and source, recurring problems grouped by similar messages, and the minute when errors peaked.&lt;/p&gt;

&lt;p&gt;For example, several connection timeouts that differ only in IP address or duration can be grouped into one finding.&lt;/p&gt;

&lt;p&gt;That gives you a shorter list of things to investigate before you start following individual requests.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;
  
  
  Logs don't always come in one format
&lt;/h2&gt;

&lt;p&gt;Another thing I wanted to handle was mixed-format output.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;LogLens supports formats including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON lines&lt;/li&gt;
&lt;li&gt;logfmt&lt;/li&gt;
&lt;li&gt;klog&lt;/li&gt;
&lt;li&gt;Airflow logs&lt;/li&gt;
&lt;li&gt;Python logging&lt;/li&gt;
&lt;li&gt;Log4j-style logs from tools such as Spark, Hadoop, and Kafka&lt;/li&gt;
&lt;li&gt;Generic timestamp and log-level formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It processes each line independently and renders supported formats in a consistent shape.&lt;/p&gt;

&lt;p&gt;If a line doesn't match a supported parser, it passes the line through rather than trying to guess what it means.&lt;/p&gt;

&lt;p&gt;That fallback is important. A log tool shouldn't silently turn unfamiliar output into misleading data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Keeping it small
&lt;/h2&gt;

&lt;p&gt;I built LogLens in Java 21 using Picocli and Jackson.&lt;/p&gt;

&lt;p&gt;The implementation is deliberately small. The project has eight Java classes and uses two runtime dependencies.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The processing model is streaming, so LogLens doesn't need to load an entire log file into memory before producing output.&lt;/p&gt;

&lt;p&gt;That also makes it suitable for live streams:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &lt;span class="nt"&gt;-f&lt;/span&gt; mypod | loglens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can combine it with existing terminal tools instead of introducing another interface or service to maintain.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why native binaries?
&lt;/h2&gt;

&lt;p&gt;I wanted someone to be able to try LogLens without first installing a JDK.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I used GraalVM native-image compilation to build standalone executables.&lt;/p&gt;

&lt;p&gt;The current releases include binaries for macOS Apple Silicon, Linux x86-64, Linux ARM64, and Windows x86-64.&lt;/p&gt;

&lt;p&gt;You can install it with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/SushrutVaidya/loglens/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or build it yourself with JDK 21 or later:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/SushrutVaidya/loglens
&lt;span class="nb"&gt;cd &lt;/span&gt;loglens
mvn package
java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/loglens.jar &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The native build is available through the Maven native profile when using a GraalVM JDK.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;
  
  
  What LogLens doesn't do
&lt;/h2&gt;

&lt;p&gt;LogLens isn't a replacement for an observability platform.&lt;/p&gt;

&lt;p&gt;It doesn't collect logs, store or index them, or provide a dashboard. Tools such as &lt;code&gt;kubectl&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt;, and your existing logging infrastructure still handle collection and retrieval.&lt;/p&gt;

&lt;p&gt;It's a pipe-friendly utility for making the output easier to inspect.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I'd rather be clear about those limitations than pretend a small CLI can solve every logging problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  Give it a try
&lt;/h2&gt;

&lt;p&gt;The project is open source under the Apache 2.0 license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/SushrutVaidya/loglens" rel="noopener noreferrer"&gt;github.com/SushrutVaidya/loglens&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Website&lt;/strong&gt; [Loglens]&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://loglens.sushrutvaidya.in/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsushrutvaidya.in%2Fimg%2Fmeta.png" height="497" class="m-0" width="676"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://loglens.sushrutvaidya.in/" rel="noopener noreferrer" class="c-link"&gt;
            Sushrut Vaidya · Platform Engineer
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            I keep thousands of Airflow DAGs on schedule at Apple AdPlatforms. Java, Spring Boot, Kubernetes, AWS.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/data%3Aimage%2Fsvg%2Bxml%2C%253Csvg%2520xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%2520viewBox%3D%270%25200%2520100%2520100%27%253E%253Crect%2520fill%3D%27%2523f54e00%27%2520width%3D%27100%27%2520height%3D%27100%27%2520rx%3D%2720%27%2F%253E%253Ctext%2520x%3D%2750%27%2520y%3D%2772%27%2520text-anchor%3D%27middle%27%2520font-family%3D%27system-ui%2Csans-serif%27%2520font-weight%3D%27800%27%2520font-size%3D%2754%27%2520fill%3D%27%2523ffffff%27%253ESV%253C%2Ftext%253E%253C%2Fsvg%253E" width="" height=""&gt;
          loglens.sushrutvaidya.in
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;If you work with application logs, Kubernetes, or distributed services, I'd be interested to hear whether this fits into your workflow.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Thanks for checking it out.&lt;/p&gt;

</description>
      <category>java</category>
      <category>opensource</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
