java.logging to String? - java

Hiho,
i'm trying to log errors with the help of java.logging
i want my logger to log everything to a log file and to a string or something(for html output(my program is a servlet))
I haven't found something like a StringHandler. Is there a possibility to do this?
greetings

The rationale behind a logging famework is to decouple your application code from logging - it sounds like you want to re-couple the two together. The biggest issue you will probably need to overcome is that all your log messages will be consolidated together, so you will see messages from separate requests in the same file.
If you want to be able to display to the user all the messages that your servlet has logged during the lifetime of their request you'll need to add an Handler as the first thing in your servlet, remove it in a finally block and then handle the messages its accumulated.
I'm not aware of any way in which you could reliably capture all relevent logging per request, as your servlet container will be executing code before you get to the point where you can intercept it, but as that sort of logging will probably deal with errors which would prevent you ever reporting anything back to the user, its probably a non-issue.
As some of the other answers intimate, logging though java.util.logging is rather basic, hence a number of other projects which provide logging, Logback being one of the best.

I think you can use the usual logger like log4j and a StringBuilder. That should do the trick.

You could try creating your own appender called StringAppender, as a subclass of WriterAppender with a StringWriter to log to.

Related

Java conditional logging with the logging API

I understand that I can use
Logger.setLevel(<level here>);
To set the level of logging (turn it off, turn it on, etc). However, I'm not sure how I can conditionally log based on the log level the user specifies.
In essence, I have a class that uses the logging API. I wish to give the user of the class the power to configure the log level how they please. I've seen this done with log4j but not with the logging API.
Is there a best practice for this? Should I just have some function
setLogLevel()
that the user can pass a Level.INFO or whatever to? Or is there a better way?
Thank you!
I'm not sure, if understand this question correctly, but you shouldn't set the logging level from the code, which calls the logger. The idea behind logging is, that the developer logs all messages at the appropriate level. For example "Started to compute xyz" at DEBUG level, "New user have been set into DB" at INFO level and "Caught exception from..." at ERROR level. The logger will print the message only if it has the same or higher logging level. The logging level should be set according to environment, for example DEBUG for development and INFO for production, from outside the application.
Conditional logging is useful if the creation of the message is time consuming and you don't want to create the log message unless it will be really logged (check out this link). If you want to check, that the logger from the java.util.logging will actually log at given level, you can use this method.
However, I'm not sure how I can conditionally log based on the log level the user specifies.
Your question is unclear, but I think you are asking how log stuff depending on the log level that the user sets. The answer to that is that you just write your log statements normally; e.g.
logger.warning("Danger Will Robinson");
...
anotherLogger.info("It's good to be alive");
... and let the user specify what logging to capture using the logging configuration. Generally speaking the logging configuration is specified by a config file that is loaded at runtime, and can be altered by the user. It is also possible to create or alter the logging configuration programmatically, though presenting this functionality to the user via some kind of user-friendly UI is going to be something of a challenge.
In theory, it is also possible to a given log events at different levels depending on some condition. However, you are probably taking control away from the user by doing that.

For apache-tomcat using logger framework vs redirecting STDOUT to catalina.out

In apache-tomcat are there any performance benefits of using some logging framework like log4j or java.util.logging over printing to stdout which gets dumped to catalina.out (which is the default behavior)?
Functionally both are same for my use-case since I don't need any extra formatting for logged messages.
I would like to know the benefits of using a logging framework here.
Thanks in advance!
You won't see performance benefits, from that perspective just go with whatever provides your functionality.
Adding something like log4j is so easy anyway though, and provides so much more future flexibility, that I'd never even think of relying on stdout for a webapp output, no matter how limited my current requirement.
Edit: it's not just formatting of messages, stuff like including class-that-wrote-the-log-entry, line of code, thread name, etc - all of these can be included in logs "free" once you're using a logging framework, and they're just not available with stdout.
besides formatting there are many advantages to using logger instead print to console. And perfomance too. For example you can simple switch before log levels to achive better perfomance. You can achive additional perfomance when use right logger like logback.
For example logback has feature use placeholders in log message
log.debug ("Result of big function = {}", bigAndLongMethod())
this will be faster then
log.debug("Result of big function = " + bigAndLongMethod())
because in first case bigAndLongMethod() willn't be executed if your loglevel higher then debug.
Using some additional appenders can increase perfomance to, i.e. redirect log to other host or log into db.
As additional benefit you will get more standart-comliant log support in you project, and you be more sotisfacted with it in future, even you don't see any difference right now.

Repressing logging from another package

My code requests a DB to see if an object is present and then sets a value. The problem is even if the object is present, my logs get flooded with their logging code. How can I suppress these logging statements?
Yes! If you provide information about what logging system you use and other systematic information that could be helpful (like what db, where are the logs you want to suppress etc.) then someone will tell you how it can be done in your situation.

Implementing logging

I was just wondering if following thing exists.
I have a TCP communicator which keeps communicating with thousands of devices.
Currently, the TCP communicator logs all the events in one log file.
Now, is it possible to log communication with every device in different files. The IMEI number of every device is different. So the logger will check if a file with name equal to the IMEI number of the device exists. If the file exists, logger will start logging events of the device in that file, otherwise it will create a new file with IMEI as the file's name and start logging the events in that file.
(We are developing our application in Java.)
LogBack is the future, and it's here!
Created as a successor of log4j and fully complaint with the slf4j framework, logback might be the easy (and clean) way to fulfill your need.
I'm not an expert but I guess that SiftingAppender might be the right answer. There should be a discriminator option for you. Maybe you can build your own discriminator, extend the SiftingAppender, or get some extra help from Janino library.
Hope this helps!
If you are implementing the logger yourself, there's nothing to stop you from doing this.
For example, give the log function as a parameter the number of the device you're currently communicating with, and implement it the way you described.
If you're using Apache log4j, which I highly recommend, create a custom logging appender by extending AppenderSkeleton and writing unique files for individual connections will be as simple as doing standard file I/O with a variable filename.
If you are using java.util.logging, look at the Handler base class, if you are using log4j, look at Appender. In both cases, you need to somehow get the IMEI associated with the message, so the code writing the log message can pick the appropriate file.
There are two approaches to doing this.
First is to extend the log event class (LogRecord or LoggingEvent respectively). This would allow you to log using your event, which contains the IMEI. However, this does not account for logging performed by other libraries etc while performing the conversation with a device.
The other alternative is to use a ThreadLocal. Set the IMEI associated with a socket whenever you receive a message or are formulating message. Make sure that the logging happens in the same thread, and any queuing is done at the log handler/appender. Look for / ask questions about ThreadLocals if you are unfamiliar with this approach. I believe that Log4J's NDC and MDC implements this sort of strategy, but I've not tried to do specialized processing of context at the appender.
Finally, be aware some operating systems will run out of file handles if you are indeed thinking of keeping "thousands" of log files open. Depending on just how many files, you may want to consider writing log messages (with IMEI) to a database, or doing some sort of LRU-based file closing. In the latter, you would basically not have file handles for log files that haven't been touched in a while.

Advantage in using Java Logger?

I want to log information to a file and want to know is there any advantage in using the Java Logger class versus my own personal method of logging?
I know using a logger I just add my own FileHandler to the logger. My personal method is just using a FileOutputStream.
Honestly your logger may be as good, it's pretty easy to put in log levels, filtering, etc.
The problem is when you start to put together code from 10 different groups each with their own logging. Some use System.out, some use some custom logger, some use log4j, ...
How do you parse or redirect the output? How do you filter all that output to just show your messages (For instance, filtering options in log4j won't prevent messages being sent straight to System.out).
It's a pretty big bulk change depending on which system you are moving from/to. Better just to use one very common one from the beginning and hope that it's the one everybody else on the project chooses.
The real question is: why would you bother writing your own logger when there are already existing libraries for doing that? Does your logger do something that the others don't? I kind of doubt it.
Standardization is another big issue - see Bill K's answer.
For most scenarios, a standard logging framework is the way to go. They are pretty flexible. But using your own implementation can also be a valid option, specially if we are not speaking of traditional logging (global debugging, problems, warning messages) but about specific informational meesages or accounting.
Among other factors, bear in mind that the standarization of logging allows third party libraries to cooperate. For example, if you have a standard web application using (say) Hibernate, and you have configured a standard Java logging lib, then you can not only log from your own code but also tell Hibernate to log debugging info to your log files (not necessarily the same files). That is very useful - almost a must.
If you code your own logging library with a plain FileOutputStream, you must decide -among other things- if you are going to keep the file opened, or reopen-append-close in each write - and you must take of synchronization and related issues. Nothing terribly complicated, though.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
A logging framework allows you specify logging levels (e.g. log only critical messages, log only debug messages etc.). It also allows you to log to multiple destinations (e.g. to a file, to syslog etc.) and you can do this even after your application is fully built by just changing a config file and not changing any code. It can also format your logs easily depending on various parameters.
There are numerous other advantages since proper logging is a rather involved problem and these packages have been written to solve them. I think the important question, why would you not use them?
Well I would always prefer tested thing and approved by community over something which still need a lot of test. Logger allows you many things which will consume you some time to implement and to test the robustness of your solution. A big plus will be the know-how of the next person who will do something with your code, in case it will be your logger, normally it would take more time to learn how its working out, since there is much more examples and documentation for java.util.logger.
Like all others mention, there are more advantages to using a more common logging system over writing your own. To be honest, the Java util logging api is not nearly as extensive and configurable as other libraries you might find out there on the internet.
Bare in mind that rolling your own always has the disadvantage of being less tested and therefore more prone to break or skip some potentially crucial messages.
Personally I prefer using SLF4J since it allows me to plug in adapters for more commonly used logging frameworks and then let's me pick my own actual logging implementation, this solves most of the problems with different library writers preferring different logging frameworks. And if you consider yourself up for the task you could writer an implementation for SLF4J yourself ;)

Categories

Resources