Reputation: 1115
I'm working on an e-commerce enterprise j2ee application using spring framework, jersey framework. Currently we are logging all the transactions (transaction created by consuming messages from the queue/through web service requests).
Lets say, I have an message that failed when processing in my component. I want to get all the logs (all log levels info, debug, error...) for that transaction. Currently I'm looking at thread name to determine all the logs for that transaction. I don't want to rely on this for long, Since it is possible that the thread names can be same after a certain point of time.
2016-07-14 02:45:50,716 [DefaultMessageListenerContainer-3] DEBUG SomeClass – someMethod1() - Method Entry
2016-07-14 02:45:50,724 [DefaultMessageListenerContainer-3] SomeClass1 – someMethod2() number of rows inserted: [1]
2016-07-14 02:45:50,724 [DefaultMessageListenerContainer-3] DEBUG SomeClass - someMethod1() - Method Exit
Is it possible that I can have logs with something like this
2016-07-14 02:45:50,716 [sometransactionnbr] [DefaultMessageListenerContainer-3] DEBUG SomeClass – someMethod1() - Method Entry
2016-07-14 02:45:50,724 [sometransactionnbr] [DefaultMessageListenerContainer-3] SomeClass1 – someMethod2() number of rows inserted: [1]
2016-07-14 02:45:50,724 [sometransactionnbr] [DefaultMessageListenerContainer-3] DEBUG SomeClass - someMethod1() - Method Exit
How can this "sometransactionnbr" be added easily without changing code for every method I have written?
Upvotes: 2
Views: 5359
Reputation: 3424
Sadly, there is no fast change...
First, you need to use the Mapped Diagnostic Context (MDC), to set your transactionID. This utility class allows to set context information related to the operation been executed (you can set any information that will help you to audit logs in a more clear way).
Ideally, your transansationID must be set at the beginning of your operation (business method) and remove at the end. After been configured, the transactionID is available for any logged event (even if those events are logged by inner methods calls. So you don't need to pass such info to inner methods ... the logger will manage this for you).
(Very Important: the MDC links the context to the thread that executes the MDC.put()
method ... so, if you application server is reusing threads (most of them do) and you don't clean the context correctly, you will log events with outdated contexts (those of previous executions at that same thread)... Also, the context will be local to one thread, so if you're calling another method that is executed at another thread, such context info will not be transfer!!! (In that case, you will need to pass such info in another way).
Second, you must modify your logger configuration to include this context parameters to your pattern.... Example:
%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] [%X{txID}] (%t) %m%n
Where %X retrieve parameters from the MDC.
Hope this help...
UPDATE: Example Use...
public class MyBusinessClass {
private static TxIDGenerator generator = new TxIDGenerator();
...
public void myBusinessMethod() {
String txID = generator.nextValue();
MDC.put("txID", txID);
try {
businessStuffA();
businessStuffB();
...
//some business stuff
} finally {
MDC.remove("txID");
}
}
}
Upvotes: 3