我在Java中有一个分层应用程序,它有一个多线程数据访问层,可以从不同的点调用。对该层的单次调用可能会产生多个线程来并行化对数据库的请求。
我正在寻找的是一个日志工具,它允许我定义由各种线程组成的“活动”。因此,数据访问层中的相同方法应根据其调用者记录不同的输出。将不同的输出分组以总结操作的总成本的能力也很重要。
虽然应用程序是Java语言,但语言不是限制;我需要的是设计指南,以便最终实现它。我们目前正在使用log4j,但无法从中获得此行为。
答案 0 :(得分:4)
您还应该查看log4j的nested diagnostic context功能。针对不同的呼叫者向记录器推送不同的上下文可能会为您提供帮助。
答案 1 :(得分:4)
您应该能够传递记录器,因此您可以根据任务数据的某些“常用”创建记录器 - 即用户名等。然后,将此记录器作为参数传递给您需要的所有方法。这样,您就可以在log4j配置文件中设置不同的过滤器和/或规则。或者根据记录器名称刮取输出文件。
编辑:还要检查log4j中的MDC和NDC类。您可以添加上下文数据。
答案 2 :(得分:2)
在log4j中,您可以使用“%t”模式记录线程名称。请参阅log4j Pattern Layout。
答案 3 :(得分:2)
在我的一个(web)应用程序中,我使用ThreadLocal记录器将记录信息捕获到StringBuilder中。如果设置了跟踪参数,则在HttpServlet #service方法中初始化logger对象(如果未设置跟踪参数,则存在非常快的空值记录器)。生成的输出要么作为HTML注释转储到请求页面,要么写入一个段中的日志文件。
答案 4 :(得分:0)
在Java5(及更高版本)中,您可以调用
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
检查堆栈跟踪到您想要的任何深度并相应地记录。
在Java 1.4中,您可以使用
获得相同的信息StackTraceElement[] stackTrace = new Exception().getStackTrace();
答案 5 :(得分:0)
您希望将记录器对象与我认为的线程相关联。为每个线程保存log4j记录器实例的ThreadLocal变量可能会有所帮助:
http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html
答案 6 :(得分:0)
您需要将一些结构传递给标识当前“活动”的数据访问层。您可能已经有一个“Activity”类 - 有意义,您可以将Logger实例用作Sunny suggested,或者您可以使用第三个结构来跟踪活动上下文。
在任何情况下,由于您的“活动”是跨多个线程处理的,因此您无法使用线程本地存储来跟踪当前的“活动”,就像大多数其他当前答案所示。您需要明确传递它。
我建议在log4j之上创建一个小外观,用
等方法扩展界面void debug(Activity activity, String message);
并将活动上下文从数据访问层传递给它。
您需要对数据访问层进行一些修改,以允许您将当前活动传递给它,但最好的方法取决于当前界面。 如果使用Workspace模式,则可能只需要在Workspace类上添加setActivity()方法,但是其他接口模式可能需要您向所有方法添加Activity参数。
如果由于某种原因无法或不愿意更改数据访问层,您当然可以在调用数据访问层之前将活动上下文存储在线程本地存储中,并在生成子线程之前检索它或者在数据访问层中对作业进行排队。这是一个可行的解决方案,但以这种方式传递信息有点危险。