Avoiding of printing full package name of method in log4j - log4j

I have an API that uses log4j for logging. When I have used the API in my project, though log statements related to project printed with ontl method name, but log statements coming from API is printed full package name format.
In log4j.properties file I am using "%c" (lowercase).
How I can force all project log statements get printed only method name.
Lets say;
I have two classes Main.java and AlarmCategoryImpl.java
AlarmCategroryImpl.java is located on API class, Main.java is defined in my project class.
static Logger logger = Logger.getLogger(AlarmCategoryImpl.class);
static Logger logger = Logger.getLogger(Main.class);
and its log4j output.
2012-12-01/18:13:22.220/EET [INFO][Main->main] starting...
2012-12-01/18:13:22.447/EET [INFO][com.monitor.base.alarmmanagement.alarmconfigurationImpl.AlarmCategoryImpl->copyStructureRecursive] Copying AlarmCategoryImpl

%c means "category name", which is synonymous to "logger name". That means that %c will be expanded to the logger's name.
The logger name is not necessarily the fully-qualified class name. The logger name is the string that is passed in to Logger.getLogger(). Therefore, if you have a class named x.y.z.MyClass, and it has this:
private static final Logger logger = Logger.getLogger("hello");
Then log statements will be generated with hello expanded instead of %c.
That means that the classes in your API are using getLogger(), passing the class name as a parameter. That causes %c to be expanded to the fully-qualified class name when the logs print.
I'm guessing that your non-API classes (in other words, your own project's classes) don't pass-in any value to Logger.getLogger(), or perhaps they use the root logger. To be sure, paste here the line of your code that retrieves the Logger instance.
EDIT as per comment:
Well, is it possible that your Main class is inside the default package? (that is, it is not associated with any package)? If yes, then I don't see any problem.
[INFO][Main->main]: INFO is the level, Main is the class, main is the method.
[INFO][com.monitor.base.alarmmanagement.alarmconfigurationImpl.AlarmCategoryImpl->copyStructureRecursive]: INFO is the level, com.monitor.base.alarmmanagement.alarmconfigurationImpl.AlarmCategoryImpl is the class, copyStructureRecursive is the method.

Related

Different loggers for classes in python

I have several classes in the same module - I want each to have its own class attribute of a logger from the logging module. Because of the structure of the logging module, when I add:
logger = logging.getLogger(__name__)
each of their loggers has the same name (the module) so they are actually all the same logger. I'd prefer to have each logger to be class specific (so their names are something like package.module.ClassName). I'm aware "best practice" is generally to name your loggers name and also aware I could just rename them whatever I want. But I was mainly looking for what's recommended for this use case?
Solution
Consider adding contextual information required via logging.LoggingAdapter
Example
class CustomAdapter(logging.LoggerAdapter):
"""
This example adapter expects the passed in dict-like object to have a
'connid' key, whose value in brackets is prepended to the log message.
"""
def process(self, msg, kwargs):
return '[%s] %s' % (self.extra['connid'], msg), kwargs
logger = logging.getLogger(__name__)
adapter = CustomAdapter(logger, {'connid': some_conn_id })
References
Logging cookbook (search for LoggingAdapter): https://docs.python.org/3/howto/logging-cookbook.html

How to Configure Log4Net to Enable Logging for a Particular Class

Given an assembly with 2 classes, Foo and Bar, via the configuration file, how to I enable logging at the Info Level for Foo, and the Warning level for Bar?
What configuration you use, depends on how the Logger is created. The basic configuration looks like this:
<logger name="(INSERT LOGGER NAME HERE)">
<level value="(WHATEVER LOG LEVEL TO APPLY FOR THIS PARTICULAR LOGGER)" />
</logger>
What determines your Logger Name is how you create it.
LogManager.GetCurrentClassLogger() // The name will be "namespace.name" of the current class.
LogManager.GetLogger<T>() // The name will be "namespace.name" of the Type T.
LogManager.GetLogger(Type type) // The name will be "namespace.name" of the type.
LogManager.GetLogger(string name) // The name will be name.
So if you have a particular process that you want to log in multiple classes / files, define the name of the process and use the string overload.
If you want to be able to turn on logging for a single class, use one of the other overloads.

switching FileAppenders on the fly

I've got a legacy logging class. Its got a static Logger reference (named logger) and a bunch of static methods.
Each method takes a String input and writes it to System.out.println and to logger if logger is not null.
Its got a constructor that initializes logger. But this constructor only has package scope and I'm pretty sure its not being called anywhere. Therefore logger is always null and the class essentially only ever executes System.out.println
I want to change this so it can be used in a multi threaded application where each thread writes to its own unique FileAppender.
And that's where I'm stuck.
Basically, what I want to do is have this static class associated with a bunch of different log4j FileAppenders. Each FileAppender can be created by the Thread, and the file name can be derived from unique information known to the Thread.
What I can't figure out how to do is magically use Log4j to communicate that Thread's unique FileAppender to this legacy logging class.
Ideas? Hints? Suggestions?
Mark
It is possible to change the target log file name dynamically using a RoutingAppender and the ThreadContext map.
This can all be done with configuration (no need for custom code where threads create FileAppenders). In the RoutingAppender configuration you can specify a ThreadContext key you want to use to switch the target FileAppender. For example, you can use the string "ROUTINGKEY". Each thread puts a unique value in the ThreadContext map for key "ROUTINGKEY", and this value is used to select the Appender that the log event is routed to. You can even set it up to dynamically create log files that have the ROUTINGKEY value in the file name, so not all target log files need to be known in advance.
The FAQ page has a good example: http://logging.apache.org/log4j/2.x/faq.html#separate_log_files

Log4J pass logger to helper class

if I have two classes with one logger each. Each logger has one appender to its own logfile.
Now each class calls one helper class (both classes call the same helper class) and within the helper class I want to make some logging. How can I write the logs from the helper class to its corresponding logfile?
The only way I thought about is to pass the instance of the logger to the helper class (or the name of the logger). But isn't there a better way to do that? Up to now I declare one new logger inside the helper class, but then the logs will not go to the right appender.
Hopefully you understand my question.
Many greetings,
Hauke

Proper way to declare log4j

I'd like to receive a clarification on the following:
Every class that has something to say in my program , creates its own logger like this
public final static Logger logger = Logger.getLogger(ClassName.class);
I was thinking ....
Why is it public? Why is it customary to make it public?
- Logger is never reused from outside the class it was created
Can there be a generic logger used throughout the program instead of having each class maintain its own?
- Seems like ClassName is used as part of logging only to indicate WHAT class said what. Perhaps it is possible to pass a reference to the class name to the logger instead.
Please help me clarify
The only reason to make it public is if you want it to be reused outside of the class.
You can have a single logger instance per you application, but you lose granularity of the messages available for configuring package or class level logging facilities.

Resources