Setting a custom user defined formatter in logger.properties file - java

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.

Related

When is ".level" required in java util logging properties?

I've seen java util logging configured in a number of ways. Usually the fully qualified class name is used for the logger name. In the corresponding logging.properties file, I've seen log level configured at either the package level or the class level in a couple different ways. For example, to set the loglevel to FINE for com.example.MyClass:
com.example.level = FINE
com.example.* = FINE
com.example.MyClass = FINE
com.example.MyClass.level = FINE
Do all four of these variants work (assuming they are not overridden later in the file)?
Are any of the options "more correct" than the others?
Does java.util.logging just assume .level if its not there?
I tried finding the definitive guidance on this config file but stopped at
https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html#a1.8 which seems quite underspecified.
Do all four of these variants work (assuming they are not overridden later in the file)?
Most of the online tutorials I've seen use the explicit .level suffix...is that preferred (and why)?
Under the standard LogManager, com.example.* = FINE and com.example.MyClass = FINE would not change the level. The key has to end with .level in order to change the level.
Per the LogManager documentation:
All properties whose names end with ".level" are assumed to define log levels for Loggers. Thus "foo.level" defines a log level for the logger called "foo" and (recursively) for any of its children in the naming hierarchy. Log Levels are applied in the order they are defined in the properties file. Thus level settings for child nodes in the tree should come after settings for their parents. The property name ".level" can be used to set the level for the root of the tree.
If you are using a subclass of LogManager then you need to consult that documentation to verify the syntax.
Does java.util.logging just assume .level if its not there?
According to the documentation it does not. If you declare something without the .level it would just be considered a LogManager entry.
Are any of the options "more correct" than the others?
The LogManager properties file can't create loggers. This means that your log file must match how the code is creating the loggers. For instance, if your file is using com.example.level = FINE and your code is using com.example.MyClass1 and com.example.MyClass2 as the logger name you will never see MyClass1 or MyClass2 switch to FINE because the code never created package parent logger. Root is the parent of all named loggers so that is the ideal way to change multiple loggers at once. If you need to do anything really complicated then you use the config option supported by the LogManager.

How to modify a message in Log4J 2?

I'm trying to MODIFY, not DENY, certain messages before being logged using Log4J 2. I'm currently trying to use a Filter, but I can't seem to be able to modify a message from any of it's methods.
Please be patient with me as I'm totally new to Log4j.
Log4j purposely does not let you modify the LogEvent as it might get passed on to other Filters and Appenders that expected the original event. However, the RewriteAppender will let you create a copy of the LogEvent that is modified and then pass that to a subordinate Appender. The RoutingAppender also supports a RewritePolicy that does the same thing.

Pass log event specific data with slf4j (and log4j)

Is there a way to pass further information which just applies to the current log event with slf4j? Request based information like user, ip address or application name can be stored and accessed via the MDC. Later I can access that information in a layout or a converter and dont have to parse the log message. If I use a JSON based format I have another field with "appName":myApp and if I log with log4j in plaint text I can access it via the %{appName} notation.
Is there a way to achieve this with information which just applies to one log event? For example I want to pass an exception id(even for exceptions I do not own). The best but still ugly solution is to pass the id to the MDC, log the exception and delete it afterwards. Does anyone know a better solution?
If you don't need to use slf4j and log4j is good enough - you can use custom messages with log4j: https://logging.apache.org/log4j/2.x/manual/messages.html
If you want slf4j - you could implement your own Logger adapter which would treat any extra parameters appropriately (just like http://www.slf4j.org/xref/org/slf4j/impl/JDK14LoggerAdapter.html)

Simple logger, how to?

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.

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