Auto-prefix selected SLF4J logged messages - java

I'd like messages logged from a testing library to be auto-prefixed with "TEST" so they are easier to highlight or filter from the primary output.
Libraries: SLF4J / Logback
I'd prefer this as a feature of the logging rather than making every test class have to implement something special it although I wouldn't be against making them all apply a consistent Marker if that helps.
How can certain loggers be intercepted and prefixed?
Is there a way that doesn't involve a test-only log config file?

Related

Functionality level configurable logger enable in Log4j2

I want to implement a logger at a functionality level in my application. so when and where log needed for debugging I can turn on and start logged activities. For example, i want to enable logging for registration functionality only.
I am not sure that this is possible or not but my requirement is like that. If possible please give a solution or any insight on that is appreciatable.
If you use the slf4j/log4j API, this is a feature you get pretty much "for free". If you follow the standard practice of creating a logger for each of your classes, via a line like:
static Logger log = LoggerFactory.getLogger(UserRegistration.class);
and use that logger for all logging in that class. You also choose the appropriate log level for each of your logging calls (WARN, INFO, DEBUG, etc.). Then you can turn the log level up/down in your logging configuration file for just one class with a line like this:
<logger name="com.mycompany.util.registration.UserRegistration"><level value="DEBUG"/></logger>
You can also turn the logging level up/down for the whole module that this class comes from with a line like:
<logger name="com.mycompany.util.registration"><level value="DEBUG"/></logger>
You use config lines like these to turn on certain log calls by raising them above the default log level you've set. You set the default log level with something like this:
<root><level value="WARN" /></root>
So with just these lines, you would only get WARN level logging for most of your code, but for that one module or class file, you'd also get INFO and DEBUG level logging.
You can do more complicated things, like send logging for certain parts of your code to a special log file. Maybe that's what you're talking about when you say you only want to log "registration functionality". You could set up your logging config so that only classes involved in "registration" are sent to a special file.
The main point of this is that you don't need to think about this too much in advance. You just attach the name of each class to all the logging calls made in that class, and choose the appropriate log level (WARN, INFO, DEBUG) for each of your logging calls, and you can decide later via your logging config file what you want to see or not see, and where you want logging information to go.
You can use API calls to configure logging more dynamically when your program first starts, or even while it is running. The main point, again, is that you don't think ahead about which parts of your code you want to see detailed logging for. You just put logging calls everywhere, and then decide which ones you actually see the output from later on.

Creating Custom LoggingContext (Logging Separation)

I've been experimenting with different logging frameworks for use in a Java library I've been developing. I'd like to separate the logging configuration of the library from logging done by users implementing the library. I want users of my library to be able to specify their own LOG2J2 configuration and log their own information without it having ANY effect on the logging configuration of the library. The best way I can see to accomplish this is to have the library create and use it's own LoggerContext. I have two questions: Is it possible to create and use a special LoggerContext specifically for my library or is there perhaps an easier way to accomplish what I'm trying to do? Once I've created a LoggerContext and applied its configuration is it possible to somehow tie it back to the LogManager so that when I call LogManager.getLogger() from my library it will use my custom LoggerContext?
To try and put it simply, I want to separate the framework logging from the implementation logging. Similar to what is being described here. Unfortunately, that link seems to focus more on Web logging separation rather than application/framework logging separation.

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.

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 ;)

Log4j - Logging to multiple log files based on the project modules

Consider this scenario:
I have a project with two modules and one common module as below (the package structure):
com.mysite.moduleone
com.mysite.moduletwo
com.mysite.commonmodule
In the above, the commonmodule classes can be used by other two modules.
The question:
I need to configureLog4J such a way that the log messages from moduleone and moduletwo goes to different log file. I can always do this using using category.
But the real problem is when I want to log the messages from the commonmodule also. So, when the commonmodule classes are called from moduleone the commonmodule log messages should go to the moduleone log file. If the commonmodule is accesse from moduletwo the commonmodule log messages should go to moduletwo log file.
Is it possible to configure Log4J in this fashion? Any comments?
PS: I think I made my question clear. If any confusion, leave a comment, wil try to clear it. :)
Is it possible to configure Log4J in this fashion?
In short, it is not with log4j unless you write a custom filter. And that filter would need to capture and analyse the call stack for each log event that makes it to each log appender ... which would be expensive.
I'm in agreement with #Stephen C about not being able to do so with Log4j without an expensive custom logger.
Another similar logging framework called Logback supports two options which may be enough to remove the need for a custom appender. They are called MDC (Mapped Diagnostic Contexts) and Markers.
Markers provide a way to add a custom piece of information to a logging statement, and you could (depending on how the common package is used) pass in a Marker to use depending on which module is using it.
MDCs could be used by setting them just before going into code in the common module and then unsetting them when leaving.
It also has a filter which can filter by appender on either.

Categories

Resources