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.
Related
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
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
What I need: a class with two parents, which are ContextBoundObject and another class.
Why: I need to access the ContextBoundOject to log the method calls.
Composition works? As of now, no (types are not recognized, among other things).
Are other ways to do this? Yes, but not so automatable and without third-party components (maybe a T4 could do, but I'm no expert).
A more detailed explanation.
I need to extend System classes (some of which have already MarshalByRefObject (which is the parent of ContextBoundObject) for parent, for example ServiceBase and FileSystemWatcher, and some not, for example Exception and Timer) to access some inner workings of the framework, so I can log method calls (for now; in future it may change).
If I use this way I only have to add a class name to the object I want to log, instead of adding the logging calls to every method, but obviously I can't do this:
public class MyService:ServiceBase,ContextBoundObject,IDisposable{
public MyService(){}
public Dispose(){}
}
so one could try the usual solution, interfaces, but then if I call Run as in:
ServiceBase.Run(new MyService());
using a hypotethical interface IServiceBase it wouldn't work, because the type ServiceBase is not castable to IServiceBase -- it doesn't inherit from any interface. The problem is even worse with exceptions: throw only accepts a type descending from Exception.
The reverse, producing a IContextBoundObject interface, doesn't seem to work either: the logging mechanism doesn't work by methods, so I don't need to implement any, just an attribute and some small internal classes (and inheriting from ContextBoundObject, not even from MarshalByRefObject, which the metadata present as practically the same).
From what I see, extending from ContextBoundObject puts the extended class in a Proxy (probably because in this way the method calls use SyncProcessMessage(IMessage) and so can be intercepted and logged), maybe there's a way to do it without inheritance, or maybe there could be pre or post compiling techniques available for surrounding methods with logging calls (like T4 Text Templates), I don't know.
If someone wants to give this a look, I used a customized version of MSTestExtentions in my program to do the logging (of the method calls).
Any ideas are appreciated. There could be the need for more explanations, just ask.
Logging method calls is usually done using attributes to annotate classes or methods for which you want to have logging enabled. This is called Aspect Oriented Programming.
For this to work, you need a software that understands those attributes and post-processes your assembly by adding the necessary code to the methods / classes that have been annotated.
For C# there exists PostSharp. See here for an introduction.
Experimenting with proxies I found a way that apparently logs explicit calls.
Essentially I create a RealProxy like in example in the msdn, then obtain the TransparentProxy and use that as the normal object.
The logging is done in the Invoke method overridden in the customized RealProxy class.
static void Main(){
...
var ServiceClassProxy=new ServiceRealProxy(typeof(AServiceBaseClass),new object[]{/*args*/});
aServiceInstance=(AServiceBaseClass)ServiceClassProxy.GetTransparentProxy();
ServiceBase.Run(aServiceInstance);
...
}
In the proxy class the Invoke will be done like this:
class ServiceRealProxy:RealProxy{
...
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
public override IMessage Invoke(IMessage myIMessage){
// remember to set the "__Uri" property you get in the constructor
...
/* logging before */
myReturnMessage = ChannelServices.SyncDispatchMessage(myIMessage);
/* logging after */
...
return myReturnMessage;
// it could be useful making a switch for all the derived types from IMessage; I see 18 of them, from
// System.Runtime.Remoting.Messaging.ConstructionCall
// ... to
// System.Runtime.Remoting.Messaging.TransitionCall
}
...
}
I have still to investigate extensively, but the logging happened. This isn't an answer to my original problem because I have still to test this on classes that don't inherit from MarshalByRefObject.
I think i understood how CDI works and in order to dive deep in it, i would like to try using it with something real world example. I am stuck with one thing where i need your help to make me understand. I would really appreciate your help in this regard.
I have my own workflow framework developed using Java reflection API and XML configurations where based on specific type of "source" and "eventName" i load appropriate Module class and invoke "process" method on that. Everything is working fine in our project.
I got excited with CDI feature and wanted to give it try with workflow framework where i am planning inject Module class instead of loading them using Reflection etc...
Just to give you an idea, I will try to keep things simple here.
"Message.java" is a kind of Transfer Object which carries "Source" and "eventName", so that we can load module appropriately.
public class Message{
private String source;
private String eventName;
}
Module configurations are as below
<modules>
<module>
<source>A</source>
<eventName>validate</eventName>
<moduleClass>ValidatorModule</moduleClass>
</module>
<module>
<source>B</source>
<eventName>generate</eventName>
<moduleClass>GeneratorModule</moduleClass>
</module>
</modules>
ModuleLoader.java
public class ModuleLoader {
public void loadAndProcess(Message message){
String source=message.getSource();
String eventName=message.getEventName();
//Load Module based on above values.
}
}
Question
Now , if i want to implement same via CDI to inject me a Module (in ModuleLoader class), I can write Factory class with #Produce method , which can do that. BUT my question is,
a) how can pass Message Object to #Produce method to do lookup based on eventName and source ?
Can you please provide me suggestions ?
Thanks in advance.
This one is a little tricky because CDI doesn't work the same way as your custom solution (if I understand it correctly). CDI must have all the list of dependencies and resolutions for those dependencies at boot time, where your solution sounds like it finds everything at runtime where things may change. That being said there are a couple of things you could try.
You could try injecting an InjectionPoint as a parameter to a producer method and returning the correct object, or creating the correct type.
There's also creating your own extension of doing this and creating dependencies and wiring them all up in the extension (take a look at ProcessInjectionTarget, ProcessAnnotatedType, and 'AfterBeanDiscovery` events. These two quickstarts may also help get some ideas going.
I think you may be going down the wrong path regarding a producer. Instead it more than likely would be much better to use an observer especially based on what you've described.
I'm making the assumption that the "Message" transfer object is used abstractly like a system wide event where basically you fire the event and you would like some handler defined in your XML framework you've created to determine the correct manager for the event, instantiate it (if need be), and then call the class passing it the event.
#ApplicationScoped
public class MyMessageObserver {
public void handleMessageEvent(#Observes Message message) {
//Load Module based on above values and process the event
}
}
Now let's assume you want to utilize your original interface (I'll guess it looks like):
public interface IMessageHandler {
public void handleMessage(final Message message);
}
#ApplicationScoped
public class EventMessageHandler implements IMessageHandler {
#Inject
private Event<Message> messageEvent;
public void handleMessage(Message message) {
messageEvent.fire(message);
}
}
Then in any legacy class you want to use it:
#Inject
IMessageHandler handler;
This will allow you to do everything you've described.
May be you need somthing like that:
You need the qualifier. Annotation like #Module, which will take two paramters source and eventName; They should be non qualifier values. See docs.
Second you need a producer:
#Produces
#Module
public Module makeAmodule(InjectionPoint ip) {
// load the module, take source and eventName from ip
}
Inject at proper place like that:
#Inject
#Module(source="A", eventName="validate")
Module modulA;
There is only one issue with that solution, those modules must be dependent scope, otherwise system will inject same module regardles of source and eventName.
If you want to use scopes, then you need make source and eventName qualified parameters and:
make an extension for CDI, register programmatically producers
or make producer method for each and every possible combinations of source and eventName (I do not think it is nice)
Our middleware team assignes logger names to each application and that is how they know where to direct our socket appenders to.
I would like to use the standard Logger.getLogger(Clazz.class) paradigm but that does not work with the above constraint. Also we can't log library statements out to our socket appender which would come in handy a lot.
Is there a fairly painless way to map everything from all loggers to this middleware assigned logger?
I think our middleware group messed up in how the configured the enterprise logging system. It looks like there is a setApplication property on the SocketAppender that should be used instead. Regardless, this is what we have to deal with...
You'd like to redirect your "regular" loggers' output to the "middleware logger" directly, i.e. without setting the middleware logger's appender on all the "regular" loggers, right?
If this is the case, try writing your own appender:
class MiddlewareRedirectingAppender extends AppenderSkeleton {
private Logger middlewareLogger = Logger.getLogger("your 'middleware' logger name");
public void doAppend(LoggingEvent event) {
// implement whatever filtering, etc. you want
middlewareLogger.log(...);
}
}
Attach this appender to your "regular" loggers, or just to the root logger (depending on how your "middleware" logger behaves).
Disclaimer: this is just a loose idea, I haven't tested it.