How to monitor STDERR in Java? - java

We are integrating with a 3rd party API and have purchased the license to use their Java library (wraps the API calls in object oriented fashion).
The only problem with this Java lib is that it doesn't throw exceptions or faults if the API calls fail. The only indication we get from the client-side is output to either STDOUT (on success) or STDERR (on fail).
Hence, running:
try {
com.the.third.party.java.lib.FizzBuzz.doSomething();
} catch(Throwable t) {
log.error(t);
}
...never catches anything. If an error occurs while doSomething() is running, we'll simply see the following String printed to STDERR:
Error: <details of the error here>
So I'm wondering if there is a way to monitor STDERR (System.err) for any output that contains the substring "Error:"? This could get somewhat complicated due to stream buffering, so I'm not sure what the correct approach should be.

First, if there's another way to detect errors that doesn't involve doing this, do that instead. Your future self will thank you.
But if you really need to listen to System.err, you might want to use System.setErr(PrintStream). Write your own PrintStream subclass that looks for "Error:" in the text being printed.

Related

What is the difference between System.err and java.lang.Error

I am a newbie in java. I am trying to implement a meeting room booking system with java. I want to print out all the error information to the prompt.
After searching, I find both System.err.println("error 101") and java.lang.Error("error 101") can create an error and output it.
Therefore, my questions are (1)What is the difference between them? (2)Which one is more effective when implementing a system?
The two have nothing to do with one another.
(1)What is the difference between them?
System.err is a PrintStream you can write to that will be output to the standard error stream of the console, for apps running in a console.
Error is an error class, which is a Throwable for serious errors that the program probably can't recover from.
(2)Which one is more effective when implementing a system?
"More effective" is a very vague term.
In the normal course of things, you might output error messages to System.err if your program is a command-line program. You are unlikely to directly throw Error or subclass it; instead, for exceptional conditions, you're likely to use one of the Exception classes and/or derive your own.
I suggest reading through the documentation linked above, and also the Java Exceptions Tutorial for more about exception handling.
Thats to different things.
System.err.println print a message to the error stream.
java.lang.Error
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
Is like an Exception wich not should be catched.
So these thinks can not be used in the same context.

printStackTrace() in a finished product. When and why?

I've come to the conclusion after reading from many sources that using printStackTrace for error handling is bad practice. Here's one.
Now I'm struck curious: in what cases is printing the stacktrace a valid solution? For the sake of the argument, let's assume we aren't working on a system such as a microwave or a banana, but a basic out-of-the-shelf PC.
The reason I'm asking this could be seen as a question in itself, but I'll tell you about it anyhoo:
I'm developing a snake-like game that can be played with AIs, and is intended for that purpose. All such AIs should extend an abstract class called SnakeLogic. All such AIs should also reside in their standalone .jar archives in a specific folder, from where the main program can find them and list them using classloaders.
The user can then choose one of his/her AIs from a list, should all stars fall in line, and play a game with this AI.
Now, I have a method in my main program that gets the next move from the AI like so:
public void startGame(int speed) {
gameInterface.showWindow();
Runnable moveCmd = () -> {
try {
for (Player player : snakeGame.getPlayers()) {
if (player.isDead()) {
continue;
}
String move = player.getLogicHandler().getMove();
Direction direction = Direction.directionFromString(move);
snakeGame.makeMove(player, direction);
}
gameInterface.getFrame().repaint();
snakeGame.wait(speed);
if (snakeGame.gameOver()) {
stopGame();
}
} catch (Exception ex) {
ex.printStackTrace();
stopGame();
}
};
/* moveSchedule is an instance of ScheduledExecutorService */
moveSchedule.scheduleAtFixedRate(moveCmd, 1000, speed, TimeUnit.MILLISECONDS);
}
I'm not going to get too involved with the code above. I'd like to draw your attention to the try-catch statement, however. As you can see I print the stacktrace and end the game, should an exception occur somewhere during the execution of the moveCmd runnable. This is the source of my curiosity: If I don't print the stacktrace like this, or if I remove the try-catch entirely, I never get any errors in the case of a runtime exception during the execution of that block. Why? Is it because it's wrapped inside the runnable? Note also that the line snakeGame.makeMove(player, direction); doesn't call any code in the main program; snakeGame is an instance of a SnakeLogic, which resides in an external .jar.
Why don't I get any errors if I remove the try-catch? Also, in this case, is printing the stacktrace a good idea?
I understand this imposes two questions for you: the topic and the above. I want to emphasize the topic, so don't get too sidetracked with the second question; though insight is duly noted, there's nothing broken in my code.
You need to shift your thought process a bit when dealing with error and exceptions. It is always a good practice to print the error trace. Now the question is where to print. by default printStackTrace prints to your standard console. of course you can redirect that output to a log file like Tomcat does but that is a work around, if you ask me.
In production and pre-prod systems and even in distributable spftware where you distribute a desktop application to users for running on PCs you may or may not have dedicated access to console. Further more what prints on console is lost once the console is closed or app finishes. You need to persist the errors somewhere for analysis later. Normally folks design the app to zip and send error logs periodically to developers for analysis.
Now if you think about the whole scenarios the bottom line is to preserve the errors somewhere for analysis later. So usually do it in a rotating log file or in DB. Console wont suffice. Thus incidentally the catch block should have a log statement to log the exception.
The problem with Exception.printStackTrace() is that it writes to your console (most probably) which is a synchronous operation. Not to mention that writing to console is slow in most platforms. You dont want to hold off your execution thread until the full stack trace is written. So its better to hand it over to a log framework like log4j which has the ability to write the complete stack trace into to file asynchronously (other appenders are available), so that the execution thread returns immediately to the callee and yet the log contains necessary details.
So its a question of synchronous write or asynchronous write. As Nazgul pointed out, you have to log exceptions in a system for later analysis where ever applicable.
NotE: A problem with asynchronous logging is that if the process dies abruptly, like in kill -9 or system powered down, you may loose the buffered content before OS has chance to write it to disk

Python: Multithreading between Java subproccess and Python listener?

I am monitoring and Minecraft server and I am making a setup file in Python. I need to be able to run two threads, one running the minecraft_server.jar in the console window, while a second thread is constantly checking the output of the minecraft_server. Also, how would I input into the console from Python after starting the Java process?
Example:
thread1 = threading.Thread(target=listener)
thread2 = minecraft_server.jar
def listener():
if minecraft_server.jarOutput == "Server can't keep up!":
sendToTheJavaProccessAsUserInputSomeCommandsToRestartTheServer
It's pretty hard to tell here, but I think what you're asking is how to:
Launch a program in the background.
Send it input, as if it came from a user on the console.
Read its output that it tries to display to a user on the console.
At the same time, run another thread that does other stuff.
The last one is pretty easy; in fact, you've mostly written it, you just need to add a thread1.start() somewhere.
The subprocess module lets you launch a program and control its input and output. It's easiest if you want to just feed in all the input at once, wait until it's done, then process all the output, but obviously that's not your case here, so it's a bit more involved:
minecraft = subprocess.Popen(['java', 'path/to/minecraft_server.jar', '-other', 'args],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
I'm merging stdout and stderr together into one pipe; if you want to read them separately, or send stderr to /dev/null, or whatever, see the docs; it's all pretty simple. While we're making assumptions here, I'm going to assume that minecraft_server uses a simple line-based protocol, where every command, every response, and every info message is exactly one line (that is, under 1K of text ending in a \n).
Now, to send it input, you just do this:
minecraft.stdin.write('Make me a sandwich\n')
Or, in Python 3.x:
minecraft.stdin.write(b'Make me a sandwich\n')
To read its output, you do this:
response = minecraft.stdout.readline()
That works just like a regular file. But note that it works like a binary file. In Python 2.x, the only difference is that newlines don't get automatically converted, but in Python 3.x, it means you can only write bytes (and compatible objects), not strs, and you will receive bytes back. There are good reasons for that, but if you want to get pipes that act like text files instead, see the universal_newlines (and possibly bufsize) arguments under Frequently Used Arguments and Popen Constructor.
Also, it works like a blocking file. With a regular file, this rarely matters, but with a pipe, it's quite possible that there will be data later, but there isn't data yet (because the server hasn't written it yet). So, if there is no output yet (or not a complete line's worth, since I used readline()), your thread just blocks, waiting until there is.
If you don't want that, you probably want to create another thread to service stdout. And its function can actually look pretty similar to what you've got:
def listener():
for line in minecraft.stdout:
if line.strip() == "Server can't keep up!":
minecraft.stdin.write("Restart Universe\n")
Now that thread can block all day and there's no problem, because your other threads are still going.
Well, not quite no problem.
First it's going to be hard to cleanly shut down your program.
More seriously, the pipes between processes have a fixed size; if you don't service stdout fast enough, or the child doesn't service stdin fast enough, the pipe can block. And, the way I've written things, if the stdin pipe blocks, we'll be blocked forever in that stdin.write and won't get to the next read off stdout, so that can block too, and suddenly we're both waiting on each other forever.
You can solve this by having another thread to service stdout. The subprocess module itself includes an example, in the Popen._communicate function used by all the higher-level functions. (Make sure to look at Python 3.3 or later, because earlier versions had bugs.)
If you're in Python 3.4+ (or 3.3 with a backport off PyPI), you can instead use asyncio to rewrite your program around an event loop and handle the input and output the same way you'd write a reactor-based network server. That's what all the cool kids are doing in 2017, but back in late 2014 many people still thought it looked new and scary.
If all of this is sounding like a lot more work than you signed on for, you may want to consider using pexpect, which wraps up a lot of the tedious details, and makes some simplifying assumptions that are probably true in your case.

Why is exception.printStackTrace() considered bad practice?

There is a lot of material out there which suggests that printing the stack trace of an exception is bad practice.
E.g. from the RegexpSingleline check in Checkstyle:
This check can be used [...] to find common bad practice such as calling ex.printStacktrace()
However, I'm struggling to find anywhere which gives a valid reason why since surely the stack trace is very useful in tracking down what caused the exception. Things that I am aware of:
A stack trace should never be visible to end users (for user experience and security purposes)
Generating a stack trace is a relatively expensive process (though unlikely to be an issue in most 'exceptional' circumstances)
Many logging frameworks will print the stack trace for you (ours does not and no, we can't change it easily)
Printing the stack trace does not constitute error handling. It should be combined with other information logging and exception handling.
What other reasons are there for avoiding printing a stack trace in your code?
Throwable.printStackTrace() writes the stack trace to System.err PrintStream. The System.err stream and the underlying standard "error" output stream of the JVM process can be redirected by
invoking System.setErr() which changes the destination pointed to by System.err.
or by redirecting the process' error output stream. The error output stream may be redirected to a file/device
whose contents may be ignored by personnel,
the file/device may not be capable of log rotation, inferring that a process restart is required to close the open file/device handle, before archiving the existing contents of the file/device.
or the file/device actually discards all data written to it, as is the case of /dev/null.
Inferring from the above, invoking Throwable.printStackTrace() constitutes valid (not good/great) exception handling behavior, only
if you do not have System.err being reassigned throughout the duration of the application's lifetime,
and if you do not require log rotation while the application is running,
and if accepted/designed logging practice of the application is to write to System.err (and the JVM's standard error output stream).
In most cases, the above conditions are not satisfied. One may not be aware of other code running in the JVM, and one cannot predict the size of the log file or the runtime duration of the process, and a well designed logging practice would revolve around writing "machine-parseable" log files (a preferable but optional feature in a logger) in a known destination, to aid in support.
Finally, one ought to remember that the output of Throwable.printStackTrace() would definitely get interleaved with other content written to System.err (and possibly even System.out if both are redirected to the same file/device). This is an annoyance (for single-threaded apps) that one must deal with, for the data around exceptions is not easily parseable in such an event. Worse, it is highly likely that a multi-threaded application will produce very confusing logs as Throwable.printStackTrace() is not thread-safe.
There is no synchronization mechanism to synchronize the writing of the stack trace to System.err when multiple threads invoke Throwable.printStackTrace() at the same time. Resolving this actually requires your code to synchronize on the monitor associated with System.err (and also System.out, if the destination file/device is the same), and that is rather heavy price to pay for log file sanity. To take an example, the ConsoleHandler and StreamHandler classes are responsible for appending log records to console, in the logging facility provided by java.util.logging; the actual operation of publishing log records is synchronized - every thread that attempts to publish a log record must also acquire the lock on the monitor associated with the StreamHandler instance. If you wish to have the same guarantee of having non-interleaved log records using System.out/System.err, you must ensure the same - the messages are published to these streams in a serializable manner.
Considering all of the above, and the very restricted scenarios in which Throwable.printStackTrace() is actually useful, it often turns out that invoking it is a bad practice.
Extending the argument in the one of the previous paragraphs, it is also a poor choice to use Throwable.printStackTrace in conjunction with a logger that writes to the console. This is in part, due to the reason that the logger would synchronize on a different monitor, while your application would (possibly, if you don't want interleaved log records) synchronize on a different monitor. The argument also holds good when you use two different loggers that write to the same destination, in your application.
You are touching multiple issues here:
1) A stack trace should never be visibile to end users (for user experience and security purposes)
Yes, it should be accessible to diagnose problems of end-users, but end-user should not see them for two reasons:
They are very obscure and unreadable, the application will look very user-unfriendly.
Showing a stack trace to end-user might introduce a potential security risk. Correct me if I'm wrong, PHP actually prints function parameters in stack trace - brilliant, but very dangerous - if you would you get exception while connecting to the database, what are you likely to in the stacktrace?
2) Generating a stack trace is a relatively expensive process (though unlikely to be an issue in most 'exception'al circumstances)
Generating a stack trace happens when the exception is being created/thrown (that's why throwing an exception comes with a price), printing is not that expensive. In fact you can override Throwable#fillInStackTrace() in your custom exception effectively making throwing an exception almost as cheap as a simple GOTO statement.
3) Many logging frameworks will print the stack trace for you (ours does not and no, we can't change it easily)
Very good point. The main issue here is: if the framework logs the exception for you, do nothing (but make sure it does!) If you want to log the exception yourself, use logging framework like Logback or Log4J, to not put them on the raw console because it is very hard to control it.
With logging framework you can easily redirect stack traces to file, console or even send them to a specified e-mail address. With hardcoded printStackTrace() you have to live with the sysout.
4) Printing the stack trace does not constitute error handling. It should be combined with other information logging and exception handling.
Again: log SQLException correctly (with the full stack trace, using logging framework) and show nice: "Sorry, we are currently not able to process your request" message. Do you really think the user is interested in the reasons? Have you seen StackOverflow error screen? It's very humorous, but does not reveal any details. However it ensures the user that the problem will be investigated.
But he will call you immediately and you need to be able to diagnose the problem. So you need both: proper exception logging and user-friendly messages.
To wrap things up: always log exceptions (preferably using logging framework), but do not expose them to the end-user. Think carefully and about error-messages in your GUI, show stack traces only in development mode.
First thing printStackTrace() is not expensive as you state, because the stack trace is filled when the exception is created itself.
The idea is to pass anything that goes to logs through a logger framework, so that the logging can be controlled. Hence instead of using printStackTrace, just use something like Logger.log(msg, exception);
Printing the exception's stack trace in itself doesn't constitute bad practice, but only printing the stace trace when an exception occurs is probably the issue here -- often times, just printing a stack trace is not enough.
Also, there's a tendency to suspect that proper exception handling is not being performed if all that is being performed in a catch block is a e.printStackTrace. Improper handling could mean at best an problem is being ignored, and at worst a program that continues executing in an undefined or unexpected state.
Example
Let's consider the following example:
try {
initializeState();
} catch (TheSkyIsFallingEndOfTheWorldException e) {
e.printStackTrace();
}
continueProcessingAssumingThatTheStateIsCorrect();
Here, we want to do some initialization processing before we continue on to some processing that requires that the initialization had taken place.
In the above code, the exception should have been caught and properly handled to prevent the program from proceeding to the continueProcessingAssumingThatTheStateIsCorrect method which we could assume would cause problems.
In many instances, e.printStackTrace() is an indication that some exception is being swallowed and processing is allowed to proceed as if no problem every occurred.
Why has this become a problem?
Probably one of the biggest reason that poor exception handling has become more prevalent is due to how IDEs such as Eclipse will auto-generate code that will perform a e.printStackTrace for the exception handling:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(The above is an actual try-catch auto-generated by Eclipse to handle an InterruptedException thrown by Thread.sleep.)
For most applications, just printing the stack trace to standard error is probably not going to be sufficient. Improper exception handling could in many instances lead to an application running in a state that is unexpected and could be leading to unexpected and undefined behavior.
I think your list of reasons is a pretty comprehensive one.
One particularly bad example that I've encountered more than once goes like this:
try {
// do stuff
} catch (Exception e) {
e.printStackTrace(); // and swallow the exception
}
The problem with the above code is that the handling consists entirely of the printStackTrace call: the exception isn't really handled properly nor is it allowed to escape.
On the other hand, as a rule I always log the stack trace whenever there's an unexpected exception in my code. Over the years this policy has saved me a lot of debugging time.
Finally, on a lighter note, God's Perfect Exception.
printStackTrace() prints to a console. In production settings, nobody is ever watching at that. Suraj is correct, should pass this information to a logger.
It is not bad practice because something is 'wrong' about PrintStackTrace(), but because it's 'code smell'.
Most of the time the PrintStackTrace() call is there because somebody failed to properly handle the exception. Once you deal with the exception in a proper way you generally don't care about the StackTrace any more.
Additionally, displaying the stacktrace on stderr is generally only useful when debugging, not in production because very often stderr goes nowhere. Logging it makes more sense. But just replacing PrintStackTrace() with logging the exception still leaves you with an application which failed but keeps running like nothing happened.
In server applications the stacktrace blows up your stdout/stderr file. It may become larger and larger and is filled with useless data because usually you have no context and no timestamp and so on.
e.g. catalina.out when using tomcat as container
As some guys already mentioned here the problem is with the exception swallowing in case you just call e.printStackTrace() in the catch block. It won't stop the thread execution and will continue after the try block as in normal condition.
Instead of that you need either try to recover from the exception (in case it is recoverable), or to throw RuntimeException, or to bubble the exception to the caller in order to avoid silent crashes (for example, due to improper logger configuration).

Have program recognize it crashed last time?

What is the best way to have a (Java) program recognize it crashed last time it ran and show a message along the lines of "it looks like this program crashed on you last time. Report this problem here: bla#foo.com ...."
Is there a recommended way of doing this? (Bad?) ideas I had would be:
Have the program store a temporary key file at startup and then delete it when closing regularly. If the file exists at startup, show the message.
Recognize deadlocks and store an "error file" in this case. If an "error file" exists at startup, show the error message and move the file into an archive or something similar.
There are three reasons why a Java program can crash:
Unhandled RuntimeException. This is easy to solve with a try-catch in main.
Unhandled Errors. These are rare but can be caught in main also. I usually catch Throwable in main. See below for a template.
If you use threads, then look at Thread.setDefaultUncaughtExceptionHandler().
Bugs in the VM, or program killed by the user, or hardware violent shutdown. These will lead to a crash which can't be caught. Here, your best option is to create a flag file somewhere with new File(...).deleteOnExit(). Java will clean it up for you if it gets a chance.
The problem with deadlocks is how to detect that you have a deadlock. I haven't seen a consistent way to do that, yet.
import org.apache.commons.lang.exception.ExceptionUtils;
public class Demo
{
public static void main (String[] args)
{
try
{
Demo obj = new Demo ();
obj.run (args);
System.out.println ("Done.");
}
catch (Throwable t)
{
ExceptionUtils.printRootCauseStackTrace (t);
}
}
}
Crash as in an uncaught exception? The use a Thread.setDefaultUncaughtExceptionHandler, and display the message as part of the crash.
On the first idea, how do you handle multiply instances of the applications running at the same time? (Also think about multi-user environments).
Recognize deadlocks - How often are deadlocks the problem? I guess you could monitor the thread states on all the "key" threads.
You then have external forces killing the application, should they be considered a problem that you should report? After all your application was not at fault in this case.
Finally, always store an "error file" in the form of a log. Use a proper logging framework (i.e. Java Logging or Log4J). You could check the last lines of this for a signal that the application exited normally but again you will need to be careful in multi-instance environments.
A variant of the first solution you propose is common enough on Un*x for processes: store the pid file of a running process in a file at startup. When the program is launched again you can check if this file still exists (and even if the process with this pid is running).
With Java you could probably adapt this idea using Threadid defined in ThreadMXBean. But any file would do. A file that contains a key as you propose seems a good enough way. You could also put some usefull information in it like last execution time. If it's still there at startup the program didn't stopped cleanly.
It could also become something like a launch log file that trace program events including startup and clean stops, and maybe locks.
What I do is redirect System.err to a file, so that any error message (like crashes) end up in a file I can later process...
The code to do this is quite simple...
String errLog = "c:\\myLog";
try
{
java.io.PrintStream err = new java.io.PrintStream(new java.io.FileOutputStream(errLog));
System.setErr(err);
}
catch (java.io.FileNotFoundException fnfe) {}
I'm going to mimic Marcos here. Create a configuration or log file that will host the last error message and last run date of the program. Then read that file during program load.
Many of these answers are about tracking exceptions that caused your app to quit working.
Another possibility is that the application just quit (i.e. user killed it, computer shutdown, power outage, etc.). I think your temporary key idea will work for that. It's similar to how text editing programs, such as vi or Word, automatically create a special copy of the file being edited. Upon opening it checks to see if the special copy exists and asks if you want to recover the file.

Categories

Resources