在多线程应用程序中记录活动

时间:2020-03-05 18:58:51  来源:igfitidea点击:

我在Java中有一个分层的应用程序,它具有一个从不同点调用的多线程数据访问层。对该层的一次调用可能会产生多个线程以并行化对DB的请求。

我正在寻找的是一个日志记录工具,它将允许我定义由各种线程组成的"活动"。因此,数据访问层中的相同方法应根据其调用者记录不同的输出。对不同的输出进行分组以汇总操作总成本的能力也很重要。

尽管该应用程序是Java语言,但语言不是限制。我需要的是设计准则,以便最终实现它。我们目前正在使用log4j,但无法从中获得此行为。

解决方案

回答

在log4j中,我们可以使用"%t"模式记录线程名称。请参见log4j模式布局。

回答

在Java5(及更高版本)中,我们可以调用

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

检查堆栈跟踪到所需的深度,并进行相应记录。

在Java 1.4中,我们可以使用

StackTraceElement[] stackTrace = new Exception().getStackTrace();

回答

我们想将记录器对象与我认为的线程相关联。为每个线程保存一个log4j记录器实例的ThreadLocal变量可能会有所帮助:

http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html

回答

我们还应该查看log4j的嵌套诊断上下文功能。为不同的调用者将不同的上下文推送到记录器可能会解决问题。

回答

我们应该能够传递记录器,因此我们可以基于任务数据(例如用户名等)的"通用"来创建记录器,然后将此记录器作为参数传递给所需的所有方法。这样,我们将能够在log4j配置文件中设置不同的过滤器和/或者规则。或者根据记录器名称刮取输出文件。

编辑:还检查log4j中的MDC和NDC类。我们可以在此处添加上下文数据。

回答

我们将需要将一些结构传递给标识当前"活动"的数据访问层。我们可能已经有了一个有意义的"活动"类,可以按照Sunny的建议使用Logger实例,或者可以使用第三个结构来跟踪活动上下文。

无论如何,由于"活动"是在多个线程中处理的,因此我们不能像其他大多数当前答案一样使用线程本地存储来跟踪当前的"活动"。我们将需要显式传递它。

我建议在log4j的顶部制作一个小的外观,以使用以下方法扩展接口

void debug(Activity activity, String message);

并将活动上下文从数据访问层传递到其中。

我们将需要对数据访问层进行一些修改,以允许我们将当前活动传递给它,但是如何做到最好取决于当前接口。
如果使用Workspace模式,则可能只需要在Workspace类上添加setActivity()方法,但是其他接口模式可能需要我们向所有方法添加Activity参数。

如果我们由于某种原因无法或者不愿更改数据访问层,那么我们当然可以在调用数据访问层之前将活动上下文存储在线程本地存储中,并在生成子线程或者将其放入队列之前对其进行检索。数据访问层中的作业。这是一个可行的解决方案,但是以这种方式传递信息有点危险。

回答

在我的一个(Web)应用程序中,我使用了一个ThreadLocal记录器,该记录器将记录信息捕获到StringBuilder中。如果设置了跟踪参数(如果未设置,则有一个非常快速的空记录器),该记录器对象在HttpServlet#service方法中初始化。结果输出或者作为HTML注释转储到请求页面中,或者在一个段中写入日志文件。