简体   繁体   English

您将如何细分并记录应用程序不同部分的执行时间?

[英]How would you break down and log the execution times of different parts of your application?

We have built a web application that accepts SOAP messages, does some processing, calls out to another web service, massages the response and sendd it back to the original caller. 我们已经构建了一个Web应用程序,该应用程序接受SOAP消息,进行一些处理,调出另一个Web服务,整理响应并将其发送回原始调用方。

We'd like to log, in a single line, the different execution times for these different steps. 我们想在一行中记录这些不同步骤的不同执行时间。 We use log4j with the JBossWS stack. 我们在JBossWS堆栈中使用log4j。 In other words, we'd like the log output to look something like: 换句话说,我们希望日志输出看起来像:

2009-06-10T16:19:31.487 3336/2449/861

where 3336ms is the total time spent serving the request, 2449ms is the time spent waiting for the web service's response, and 861ms is the time spent internally massaging the data. 其中3336毫秒是服务请求的总时间,2449毫秒是等待Web服务的响应所花费的时间,861毫秒是内部按摩数据所花费的时间。

These different computations happen in different places in our code and we cannot just time each one of them and make a call to the logger at the end of a single method. 这些不同的计算发生在我们代码中的不同位置,我们不能只对每个时间进行计时并在单个方法结束时调用记录器。 One of us has suggested using log4j's MDC for this as a poor man's set of global variables to track the different executions times. 我们中的一个人建议为此使用log4j的MDC作为穷人的全局变量集,以跟踪不同的执行时间。

So my questions are the following: 所以我的问题如下:

  1. Is this a horrible abuse of the MDC's primary intent? 这是对MDC主要意图的可怕滥用吗?
  2. If yes, how would you do this otherwise? 如果是,否则您将如何做?

Please have a look at SLF4J profiler . 请看看SLF4J分析器 Interestingly enough. 有趣的是。 tt was developed to answer the exact same need, that is to measure and improve the performance of SOAP calls. 开发tt是为了满足完全相同的需求,即测量和提高SOAP调用的性能。

听起来像Perf4J的工作。

I'd do the following: 我将执行以下操作:

  1. create a PerformanceTimer class, which exposes: 创建一个PerformanceTimer类,该类公开:
    • recordWaitedForWebServerReponse(operationId, time); recordWaitedForWebServerReponse(operationId,time);
    • recordMassagedData(operationId, time); recordMassagedData(operationId,time);
    • other methods, if needed 其他方法(如果需要)
  2. inject that class where it's needed; 在需要的地方注入该类;
  3. have the PerformanceTimer maintain a concurrent map of OperationId -> OperationTimingData; 让PerformanceTimer维护OperationId-> OperationTimingData的并发映射;
  4. on the method call known to be the last, invoke Log4j with the output you desired. 在已知为最后一个方法调用上,使用所需的输出调用Log4j。

While it would certainly work, I cringe at the thought, too. 虽然肯定会奏效,但我也很想念这个想法。 My suggestion would be to create a timing class just for that purpose which uses ThreadLocal to create a variable per request. 我的建议是为此创建一个计时类,该计时类使用ThreadLocal为每个请求创建一个变量。

When the request comes in, you create the variable (a long with the start time). 当请求到来时,您将创建变量(开始时间long )。 When the variable already exists, you leave it alone. 当变量已经存在时,请不要理会它。 When the result gets sent back to the client, you calculate the duration and log that. 将结果发送回客户端后,您可以计算持续时间并将其记录下来。

I'd use Spring and aspect-oriented programming to do it. 我会使用Spring和面向方面的编程来做到这一点。 The nice thing is that I'd write the logic once and apply it declaratively everywhere I needed it. 令人高兴的是,我只需编写一次逻辑并将其声明性地应用于我需要的任何地方。

One Simple way is to use System.currentTimeMillis() which returns time in milli seconds. 一种简单的方法是使用System.currentTimeMillis() ,该方法以毫秒为单位返回时间。 The difference between the millisec at the start of the method and the milli seconds at the end of the method will give the milli sec's taken for executing that particular method. 方法开始时的毫秒与方法结束时的毫秒之间的差将给出执行该特定方法所用的毫秒数。 Hope System.currentTimeMillis() will help you. 希望System.currentTimeMillis()将为您提供帮助。

We just use this in our first request filter: 我们只在第一个请求过滤器中使用它:

logger.trace("Init");
long start = System.currentTimeMillis();

//do stuff here 

long stop = System.currentTimeMillis();
String time = Util.getTimeDifferenceInSec(start, stop);
logger.trace("Complete in " + time + " sec");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM