在 Restlet servlet 的日志文件中跟踪特定请求的最佳方法是什么?
如果同时有多个请求,我希望能够在日志文件中跟踪单个请求。
由于我使用的是 slf4j Restlet 扩展,所以我考虑使用 slf4j.MDC 并向其添加源 IP+端口+时间戳的哈希。或者随着每次请求而增加的数字。
但也许还有另一种更简单的方法?
可能更容易使用线程 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,并将详细信息记录在过滤器中(这是一个 Jersey 过滤器,但对于 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 传递回请求者,以便在出现问题时进行跟踪。