Simple logger, how to? - java

I want to write a default Logger for my application. Currently I am using the default Java API Class Logger .
I was wondering if it's possible to format my logs to look somthing like this:
[level] [dd:MM:YYYY] [hh:mm:ss] message
The logger should also be able to print the messages into the System.out and into a file ?
Where should I look for this functionality ?
Can you please give me some code snippets ?

Extend java.util.logging.Formatter, overide format(LogRecord record) method.
LogRecord contains all data you need to build up your custom message.
Then change standard SimpleFormatter in logging.properties file in properties
java.util.logging.ConsoleHandler.formatter/java.util.logging.FileHandler.formatter
to your formatter.

Have you considered using Log4j?
If that is not an option for you, you could change the output format of the logger you are currently using. The following article shows a way to do just that and provide a custom formatter for the java.util.logging API.
I should also mention that, unless doing this to learn and expand your knowledge, or beeing forced by ugly circumstances, it is never a good idea to write your own logger implementation.

Check this question. I think I was asking a similar one.
A simple log file format
EDIT:
As I wrote there, I found a tool called LogExpert. You can write to a file in a format like "level;dd:MM:YYYY;hh:mm:ss;message" and view it with this tool, changind columnizer to CSV.

Related

log4j2 new compression algorithm

I would like to use log4j2 RollingFileAppender with a customized compression algorithm (ZStd).
It seems that the compression algorithms supported so far are the ones in the FileExtension enum (zip, gz, bz2, ...), see https://github.com/apache/logging-log4j2/blob/efa64bfad3f67c5b5fed6b25d65ef5ca2212011b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileExtension.java, and I believe it is not possible to add a new one (apart from patching the library).
A solution could be to reimplement the RollingFileAppender using the approach suggested here: https://logging.apache.org/log4j/2.x/manual/extending.html#Appenders, but this would involve a lot of ugly copy and paste, this appender really does a lot of things.
The approach I would like to follow is to create instead a new Action, implementing the AbstractAction interface, but I do not know how to tell log4j2 to execute this action on rollover. Is this doable? Is this the correct way to achieve this goal?
Yes. The Rollover strategy uses FileExtension to automatically add a CompressAction based on the file extension, but you can do this yourself just by configuring a custom Action. While you can look at ZipoCompressAction as a template for how to implement the action, you would also need to look at DeleteAction to see how to declare your custom action as a plugin.

Setting a custom user defined formatter in logger.properties file

I have been asked to format logger messages so that they display on a single line. The problem is that the logger has programatically defined handlers and I cannot change any of these. Is it possible to override the format of the log messages in the .properties file even though the syntax has been defined in the logger class within a logp method? I apologise for not being able to provide code. I have tried creating a custom formatter and pointing to this in the logger.properties file but the changes are not visible.
Thanks,
Daniel
I have been asked to format logger messages so that they display on a single line.
If they are all using the SimpleFormatter then read the example in the API docs and configure it through the system properties or logging.properties as described in the SimpleFormatter class level documentation.
Is it possible to override the format of the log messages in the .properties file even though the syntax has been defined in the logger class within a logp method?
The only formatting that the logger is doing is order of the parameterized message format arguments. If you want to change that formatting you should use localization and parameterized logging. Then you can swap out different formats by providing a different resource bundles (per build) which allow you to change the format for each type of message key. However, that is only formatting the LogRecord message and params. The rest is controlled in the formatters.
I have tried creating a custom formatter and pointing to this in the logger.properties file but the changes are not visible.
The logging.properties is executed before the programatically defined handlers are setup. Call LogManager.readConfiguration or after that code runs. Keep in mind that will undo programatically defined handlers that are being setup. However, that may not help you because if you are able to write code to trigger a re-configuration you could just write code to install your formatter on the programatically defined handlers.

SLF4J: Use XLogger with LocLogger

We are currently using CAL10N to localize log messages generated by SLF4J. To do this, we need to use the LocLogger class to define a logger for every class.
Few weeks into development, there comes a time where you have a few bug reports with logs attached - they do have nicely logged stack traces (thanks to SLF4J) for exceptions being thrown, but turns out we have a hard time figuring out the flow since since everyone's new to the code and the flow of things keeps changing every other day!
What we need is ENTRY/EXIT logs for every method. I was hoping that SLF4J will provide a way to do that in the least painful and fastest possible way: and ho behold! It certainly does!
The XLogger class provides methods that aid in such verbose logging (see this link), but after looking at the API docs, looks like both LocLogger and XLogger implement the Logger interface.
So the question is (we got to it finally!) - is it possible to use the LocLogger with all the localization benefits of CAL10N in peaceful harmony with XLogger, that provides all the verbose logging goodies?
No real answer for this yet - worked around it by leveraging a feature of the underlying implementation.
We're using log4j as the implementation under slf4j. The PatternLayout supports printing the package name+method name of the origination of the log message with these specifiers: %C.%M
So we simply log well-defined strings, +++ as the first line in every method and --- just before returning, to a logger for that class.
Solves the purpose, but not a solution to the original question.

Java logging best practices about logger name

I just ask about the logger name...
It it possible to give a custom name for a logger, or to use class name.
But what to use in which case?
-> Using a custom name for each application module: some classes are used by 2 modules -> to which logger name should it belong to?
-> Using classname: it seems to require a good package organisation -> best practices for logging known about that?
I prefer using class names for the purpose of debugging. You can read the log trace (and the class name will be displayed) from the log file and view line code, etc. It's useful in that sense. If someone else maintains your code, they don't have to do hectic searches on finding where the "custom name" is populated (in which class).
I still prefer classnames. It does not require a good package organisation but reflects your (good - hey what else?) package orgnization. And it's a common pattern to use the class names.
You can read the logging class file from the logs and set log levels on packages.
And following the common pattern prevents me from spending too much time on thinking about good (perfect) custom logger names ;-)
I've never heard of anyone use anything other than class name. I think anything else would be a mistake, leading to potential loss of logging detail down the line.
Don't overthink this one, just run with class name.
I donno about anything else than class name because in any case it's very easy to read through class for locating the issue or anything else..! And it is also better to log the code using all kinda log levels e.g. trace for all possible details, fatal for exception and similarly the debud,error,info etc.

How to set javax logger handle to be refactor sensitive

Someone might yell at me to read the faqqing faq, but I'm in a hurry ...
Does anyone have a way to make javax or log4j logger refactor-sensitive?
Say, that currently utils.Something has the logger handle:
final static private Logger logger = Logger.getLogger(Something.class.getName());
And logging.properties has
.level = warning
utils.Something.level=info
Then using Eclipse to refactor Something to
nutilla.Somewhere
resulting in my logger handle and logger property becoming out of sync.
Perhaps, set logging levels programmatically?
Has anyone bothered to do it and was it worth the trouble?
Clarification:
After refactoring utils.Something to nutilla.Somewhere, the logger handle now would only log warning and not info, because of the entry in logging.properties file. So the question is, is there a way to replace the function of logging.properties file with programmatic means and if so, is it worth the trouble?
Reason and Motivation for question
I'm obstinate at not listening when advising me to avoid refactoring because ...
Refactoring is a constant habit of mine. I create classes by the hour, merge them, delete them, extract methods, etc ... I'm a restless class creator who finds no time wondering where to initially place a class. I dislike sitting down wasting time wondering where to place them initially - so I just place them in the most convenient package namespace.
After building a good amount of class/interface structure, it becomes apparent to me where certain classes, interfaces or methods shd have been then all the refactoring activities take place and ... tada ... that's when my logging.properties file is ruined a hundred lines.
If you configure logging using class (as opposed to package) names, checking "Update fully qualified class names in non-Java text files" in eclipse's rename refactoring dialog should do the trick.
I do not think there is a way out of the box that updated the package names and class names in your properties file as a result of refactoring actions.
You can:
update the properties file by hand when refactoring is done (refactoring should be an action that is not undertaken eveery week :=)
use fixed strings to create loggers (make logging more functional instead of physical)
load the properties file and adjust the property names on the basis of constants you declare in your class before initialising log4j with that properties collection
I would go for the first option myself, too much automagic behaviour can get you in a very non-transparent situation quickly.
I wouldn't use it (I think it makes more sense to be careful when refactoring) but here it goes:
private static Logger logger = Logger.getLogger(new Exception().getStackTrace()[0].getClassName());

Categories