Risser
Risser

Reputation: 585

Java logging across multiple threads

We have a system that uses threading so that it can concurrently handle different bits of functionality in parallel. We would like to find a way to tie all log entries for a particular "transaction" together. Normally, one might use 'threadName' to gather these together, but clearly that fails in a multithreaded situation.

Short of passing a 'transaction key' down through every method call, I can't see a way to tie these together. And passing a key into every single method is just ugly.

Also, we're kind of tied to Java logging, as our system is built on a modified version of it. So, I would be interested in other platforms for examples of what we might try, but switching platforms is highly unlikely.

Does anyone have any suggestions?
Thanks,
Peter

EDIT: Unfortunately, I don't have control over the creation of the threads as that's all handled by a workflow package. Otherwise, the idea of caching the ID once for each thread (on ThreadLocal maybe?) then setting that on the new threads as they are created is a good idea. I may try that anyway.

Upvotes: 2

Views: 3654

Answers (6)

leopoldkot
leopoldkot

Reputation: 181

However you mentioned that your transaction spans more than one thread, take a look at how log4j cope with binding additional information to current thread with MDC and NDC classes. It uses ThreadLocal as you were advised before, but interesting thing is how log4j injects data into log messages.

//In the code:

MDC.put("RemoteAddress", req.getRemoteAddr());

//In the configuration file, add the following:

%X{RemoteAddress}

Details:

http://onjava.com/pub/a/onjava/2002/08/07/log4j.html?page=3

http://wiki.apache.org/logging-log4j/NDCvsMDC

Upvotes: 1

Romain Hippeau
Romain Hippeau

Reputation: 24375

This is a perfect example for AspectJ crosscuts. If you know the methods that are being called you can put interceptors on them and bind dynamically.

This article will give you several options http://www.ibm.com/developerworks/java/library/j-logging/

Upvotes: 1

matt b
matt b

Reputation: 139921

A couple people have suggested answers that have the newly spawned thread somehow knowing what the transaction ID is. Unless I'm missing something, in order to get this ID into the newly spawned thread, I would have to pass it all the way down the line into the method that spawns the thread, which I'd rather not do.

I don't think you need to pass it down, but rather the code responsible for handing work to these threads needs to have the transactionID to pass. Wouldn't the work-assigner have this already?

Upvotes: 0

Zak
Zak

Reputation: 25205

If you are logging, then you must have some kind of logger object. You should have a spearate instance in each thread.

  • add a method to it called setID(String id).
  • When it is initialized in your thread, set a unique ID using the method.
  • prepend the set iD to each log entry.

Upvotes: 0

VeeArr
VeeArr

Reputation: 6178

You could consider creating a globally-accessible Map that maps a Thread's name to its current transaction ID. Upon beginning a new task, generate a GUID for that transaction and have the Thread register itself in the Map. Do the same for any Threads it spawns to perform the same task. Then, when you need to log something, you can simply lookup the transaction ID from the global Map, based on the current Thread's name. (A bit kludgy, but should work)

Upvotes: 1

Yishai
Yishai

Reputation: 91871

How about naming your threads to include the transaction ID? Quick and Dirty, admittedly, but it should work (until you need the thread name for something else or you start reusing threads in a thread pool).

Upvotes: 0

Related Questions