使用Restlet时如何在日志中跟踪请求?

时间:2013-02-02 16:23:02

标签: java logging restlet slf4j

在Restlet servlet的日志文件中跟踪特定请求的最佳方法是什么?

如果同时有多个请求,我希望能够在日志文件中跟踪单个请求。

由于我使用slf4j Restlet扩展,我考虑使用slf4j.MDC并向其添加源-IP +端口+时间戳的哈希。或者随着每个请求而增加的数字。

但也许还有另一种更简单的方法?

1 个答案:

答案 0 :(得分:2)

可能更容易使用线程ID,并确保记录每个请求的开始和结束。无需任何额外编码(或CPU周期)即可为您提供所需的功能。

<强>更新

如果您为每个线程运行多个请求,那么您应该只生成一个随机ID并将其用于跟踪。类似的东西:

import java.security.SecureRandom;

public class StringUtils
{
  private static final SecureRandom RANDOMSOURCE;
  private static String CANDIDATES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  static
  {
    RANDOMSOURCE = new SecureRandom();
  }

 /**
  * Generate a random string of alphanumeric characters.
  * <p>
  * The string returned will contain characters randomly
  * selected from upper- and lower-case a through z as
  * well as the digits 0 through 9.
  * @param length the length of the string to generate
  * @return a string of random alphanumeric characters of the requested length
  */
  public static String generateRandomString(int length)
  {
    final StringBuffer sb = new StringBuffer(length);
    for (int i = 0; i < length; i++)
    {
      sb.append(CANDIDATES.charAt(RANDOMSOURCE.nextInt(62)));
    }
    return sb.toString();
  }
}

然后,正如您所说,您可以使用MDC为每个请求创建请求ID,并在过滤器中记录详细信息(这是一个泽西过滤器,但对于Restlet看起来应该类似):

  ...
  private static final String REQUESTHIDEADER = "Request-ID";
  private static final String REQUESTID = "REQUESTID";
  private static final String REQUESTSTARTTIME = "RSTARTTIME";

  @Override
  public ContainerRequest filter(final ContainerRequest request)
  {
    final String requestid = Long.toHexString(Double.doubleToLongBits(Math.random()));
    MDC.put(REQUESTID, requestid);
    MDC.put(REQUESTSTARTTIME, String.valueOf(System.currentTimeMillis()));
    if (LOGGER.isInfoEnabled())
    {
      LOGGER.info("Started: {} {} ({})", request.getMethod(), request.getPath(), requestid);
    }

    return request;
  }

  @Override
  public ContainerResponse filter(final ContainerRequest request, final ContainerResponse response)
  {
    try
    {
      final Long startTime = Long.parseLong(MDC.get(REQUESTSTARTTIME));
      final String rid = MDC.get(REQUESTID);
      final long duration = System.currentTimeMillis() - startTime;
      response.getHttpHeaders().add(REQUESTHIDEADER, rid);
      LOGGER.info("Finished: {} {} ({} ms)", request.getMethod(), request.getPath(), String.valueOf(duration));
    }
    catch (Exception e)
    {
      LOGGER.warn("Finished {} {}", request.getMethod(), request.getPath());
    }
    return response;
  }

作为奖励,这也会将请求ID传递回请求者,以便在出现问题时进行跟踪。