Search code examples
javabashshellcommand-line-tool

Command line script to pretty print Java serialized objects in logs?


I have to review lots of java logs from various sources, that contain java objects dumped to a single long line. Sometimes I'd like to see them in a more formatted fashion. Note that I'm not in control of the logging or the logs I receive.

Are there any command line tools that will format these types of objects nicely? I'm not looking for perfectly, but something like json formatting?

A sample object

[sampleObject{objId=c1, request=sampleRequest(bean=bean1, method=method1), env=job(pattern=*), step=1, state=SUCCESS}, sampleObject{objId=c2, request=sampleRequest(bean=bean1, method=method1), env=job(pattern=*), step=1, state=SUCCESS}, sampleObject{objId=c2, request=sampleRequest(bean=bean1, method=method2), env=job(pattern=*), step=2, state=SUCCESS}, sampleObject{objId=c3, request=sampleRequest(bean=bean1, method=method1), env=job(pattern=*), step=1, state=SUCCESS}, sampleObject{objId=c3, request=sampleRequest(bean=bean1, method=method2), env=job(pattern=*), step=2, state=SUCCESS}]

Sample desired output

[
  sampleObject{
    objId=c1,
    request=sampleRequest(
        bean=bean1,
        method=method1
    ),
    env=job(
        pattern=*
    ),
    step=1,
    state=SUCCESS
  },
  sampleObject{
    objId=c2,
    request=sampleRequest(
        bean=bean1,
        method=method2
    ),
    env=job(
        pattern=test
    ),
    step=2,
    state=SUCCESS
  },
]

Solution

  • A quick google for convert java object to json so you could then use jq or similar to pretty-print produced hits for tools named Jackson and GSON as well as the obvious suggestion of reading the Java output into a Java script and printing it however you like from there.

    If you can't do any of that, though, then below is a character-by-character brute-force approach using any awk. Your expected output doesn't match your sample input so idk if this does what you want or not but it looks like it might, or at least be close.

    $ cat tst.awk
    BEGIN { incIn = 3 }
    {
        out = ""
        numChars = length()
        for ( i=1; i<=numChars; i++ ) {
            char = substr($0,i,1)
            if ( char ~ /[[{(]/ ) {
                indent += incIn
                out = out sprintf("%s\n%*s", char, indent, "")
            }
            else if ( char ~ /[]})]/ ) {
                indent -= incIn
                out = out sprintf("\n%*s%s", indent, "", char)
            }
            else if ( char == "," ) {
                out = out sprintf("%s\n%*s", char, indent, "")
            }
            else if ( char != " " ) {
                out = out char
            }
        }
        print out
    }
    

    $ awk -f tst.awk file
    [
       sampleObject{
          objId=c1,
          request=sampleRequest(
             bean=bean1,
             method=method1
          ),
          env=job(
             pattern=*
          ),
          step=1,
          state=SUCCESS
       },
       sampleObject{
          objId=c2,
          request=sampleRequest(
             bean=bean1,
             method=method1
          ),
          env=job(
             pattern=*
          ),
          step=1,
          state=SUCCESS
       },
       sampleObject{
          objId=c2,
          request=sampleRequest(
             bean=bean1,
             method=method2
          ),
          env=job(
             pattern=*
          ),
          step=2,
          state=SUCCESS
       },
       sampleObject{
          objId=c3,
          request=sampleRequest(
             bean=bean1,
             method=method1
          ),
          env=job(
             pattern=*
          ),
          step=1,
          state=SUCCESS
       },
       sampleObject{
          objId=c3,
          request=sampleRequest(
             bean=bean1,
             method=method2
          ),
          env=job(
             pattern=*
          ),
          step=2,
          state=SUCCESS
       }
    ]
    

    Obviously if any of the chars being specifically tested by the script can appear in other contexts (e.g. inside strings or comments) then you'd need to modify the code to handle those cases.