1

Need help here. We have java apps started from our shell scripts in unix using java command and the output is redirected to a nohup file to ensure we capture any SystemOuts and any unhandled exceptions in a log file.

When the java app logs using the log4j, these logs are fine and they are formatted with a proper time stamp.

But when there are some systemouts in the code or any unhandled exceptions that are thrown back by the jvm process, they are logged in the nohup files but there is no timestamp on these log entries.

Can any one suggest if there are some scripting tweaks or jvm parameters that could help add timestamp to these jvm output logs?

Thanks in advance for the help

Achilles
  • 45
  • 1
  • 1
  • 5
  • 1
    What kind of system outs are those that they can't be replaced by logging just out of curiosity? As for exceptions - have you tried implementing uncaught exception handler? like here https://stackoverflow.com/a/19423233/8587732 – Vitaly Chura Oct 20 '22 at 13:29

1 Answers1

1

Edit the source code and add an uncaught exception handler to every thread.

Looks something like this:

package the.package.here;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
  public static void main(String[] args) throws Exception {
    updateUncaughtExceptionHandlers();
    ... rest of the code is here
  }

  static void updateUncaughtExceptionHandlers() {
    Thread.UncaughtExceptionHandler timestamped = (t, e) -> {
      String timestamp = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
      System.err.printf("[%s] Exception in thread \"%s\" ",
        timestamp, t.getName());
        e.printStackTrace(System.err);
    };

    Thread.setDefaultUncaughtExceptionHandler(timestamped);
  }
}

This will take care of uncaught exceptions, but won't take care of anything written out via System.err or System.out.

To take care of those, you'd use System.setErr() and System.setOut(), making PrintWriters that simply 'wrap' around the original System.out and System.err, and add a timestamp anytime a flag is true, then sets the flag false. The flag starts as true and is re-set to true every time you print a newline symbol.

I can show you how to do that, too, but before delving any deeper - can you change the source code? If you can't, your only option is to redirect standard out and standard err not to a file but pipe it to a different executable that adds these timestamps.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Thanks for the great answer. Unfortunately I don’t have access to the code as it is provided by a vendor. Would I be able to achieve it through shell scripting as well ? You mentioned about redirecting output to a different executable. Could you please elaborate on that. Thank you. – Achilles Oct 21 '22 at 14:46
  • No, and given that it's a 'vendor', "logging" to standard out is ridiculous, you should hold them accountable for their shoddy code. Sending output to a separate executable has nothing whatsoever to do with java, that' s a linux/windows/mac question and you should ask that, with the approrpriate tags (i.e., not a `java` tag), separately. – rzwitserloot Oct 21 '22 at 21:02