使用 Spring 引导和 MDC 过滤器的 Kibana 日志条目问题
Issue with Kibana log entry using Spring Boot & MDC Filter
我正在 elastic.co 上玩 ELK 堆栈,现在我已经花了 5 个小时的时间研究一些东西(尽管阅读了 doc 和 doc)。
所以我有一个 spring 引导程序 API,它会写入一个 JSON 日志文件。该日志文件由 filebeat 获取并传送到 Elastic.co ELK 堆栈,在那里我可以在 Kibana 中看到数据。
在我的 API 中,我有一个过滤器 class,它将一些值(例如响应代码等)添加到日志中(如下所示),但是我看到的是,在 Kibana 中,这些 MDC 值是实际上在消息中而不是独立字段中。
对吗?或者我需要做一个 Grok 过滤器吗?如果 Grok 是可行的方法,我一直在尝试并未能从消息中提取所有内容。
任何人都可以在我真正失去理智之前帮助/阐明一些问题 :D
@Order(1)
@Component
public class MDCFilter implements Filter {
private final Logger LOGGER = LoggerFactory.getLogger(MDCFilter.class);
private final String X_REQUEST_ID = "X-Request-ID";
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
try {
addXRequestId(req);
LOGGER.info("path: {}, method: {}, query {}",
req.getRequestURI(), req.getMethod(), req.getQueryString());
res.setHeader(X_REQUEST_ID, MDC.get(X_REQUEST_ID));
chain.doFilter(request, response);
} finally {
MDC.put("api.version", req.getContextPath());
MDC.put("Server.IP", req.getServerName());
MDC.put("API.Controller", req.getServletPath());
MDC.put("Response.code", String.valueOf(res.getStatus()));
MDC.put("Request.Method.Type", req.getMethod());
LOGGER.info("statusCode {}, path: {}, method: {}, query {}, context {}, serverName {}, RequestURI {}, RemoteHost {}, Cookies {}",
res.getStatus(), req.getRequestURI(), req.getMethod(), req.getQueryString(), req.getContextPath(),
req.getServerName(), req.getRequestURI(), request.getRemoteAddr(),
req.getCookies());
MDC.clear();
}
}
private void addXRequestId(HttpServletRequest request) {
String xRequestId = request.getHeader(X_REQUEST_ID);
if (xRequestId == null) {
MDC.put(X_REQUEST_ID, UUID.randomUUID().toString());
} else {
MDC.put(X_REQUEST_ID, xRequestId);
}
}
}
我的日志输出如下:
{"@timestamp":"2020-11-23T10:31:09.010Z", "log.level": "INFO", "message":"statusCode 200, path: /test/service/feed/, method: GET, query null, context /api/v1, serverName localhost, RequestURI /test/service/feed/, RemoteHost 0:0:0:0:0:0:0:1, Cookies null", "service.name":"test-spring-project","event.dataset":"test-service.log","process.thread.name":"http-nio-8080-exec-8","log.logger":"com.example.filter.MDCFilter","api.version":"/api/v1","API.Controller":"/test/service/feed/","Request.Method.Type":"GET","Response.code":"200","Server.IP":"localhost"}
下面是我在ELK中看到的图片
好的,我将补充 Jan Mares 在评论中提到的内容。
因此,当您使用 filebeat 从 Spring 获取日志并将它们直接发送到 ELK 时,您需要创建一个摄取管道并告诉它您要解析的字段。
现在,完成后转到您的索引模式并单击它。有一个用于编辑设置的选项卡,然后您需要将以下内容添加到 JSON 设置:
"index.default_pipeline": "在此处插入您的摄取设置"
在那之后......一切都应该继续解析。
我正在 elastic.co 上玩 ELK 堆栈,现在我已经花了 5 个小时的时间研究一些东西(尽管阅读了 doc 和 doc)。
所以我有一个 spring 引导程序 API,它会写入一个 JSON 日志文件。该日志文件由 filebeat 获取并传送到 Elastic.co ELK 堆栈,在那里我可以在 Kibana 中看到数据。
在我的 API 中,我有一个过滤器 class,它将一些值(例如响应代码等)添加到日志中(如下所示),但是我看到的是,在 Kibana 中,这些 MDC 值是实际上在消息中而不是独立字段中。
对吗?或者我需要做一个 Grok 过滤器吗?如果 Grok 是可行的方法,我一直在尝试并未能从消息中提取所有内容。
任何人都可以在我真正失去理智之前帮助/阐明一些问题 :D
@Order(1)
@Component
public class MDCFilter implements Filter {
private final Logger LOGGER = LoggerFactory.getLogger(MDCFilter.class);
private final String X_REQUEST_ID = "X-Request-ID";
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
try {
addXRequestId(req);
LOGGER.info("path: {}, method: {}, query {}",
req.getRequestURI(), req.getMethod(), req.getQueryString());
res.setHeader(X_REQUEST_ID, MDC.get(X_REQUEST_ID));
chain.doFilter(request, response);
} finally {
MDC.put("api.version", req.getContextPath());
MDC.put("Server.IP", req.getServerName());
MDC.put("API.Controller", req.getServletPath());
MDC.put("Response.code", String.valueOf(res.getStatus()));
MDC.put("Request.Method.Type", req.getMethod());
LOGGER.info("statusCode {}, path: {}, method: {}, query {}, context {}, serverName {}, RequestURI {}, RemoteHost {}, Cookies {}",
res.getStatus(), req.getRequestURI(), req.getMethod(), req.getQueryString(), req.getContextPath(),
req.getServerName(), req.getRequestURI(), request.getRemoteAddr(),
req.getCookies());
MDC.clear();
}
}
private void addXRequestId(HttpServletRequest request) {
String xRequestId = request.getHeader(X_REQUEST_ID);
if (xRequestId == null) {
MDC.put(X_REQUEST_ID, UUID.randomUUID().toString());
} else {
MDC.put(X_REQUEST_ID, xRequestId);
}
}
}
我的日志输出如下:
{"@timestamp":"2020-11-23T10:31:09.010Z", "log.level": "INFO", "message":"statusCode 200, path: /test/service/feed/, method: GET, query null, context /api/v1, serverName localhost, RequestURI /test/service/feed/, RemoteHost 0:0:0:0:0:0:0:1, Cookies null", "service.name":"test-spring-project","event.dataset":"test-service.log","process.thread.name":"http-nio-8080-exec-8","log.logger":"com.example.filter.MDCFilter","api.version":"/api/v1","API.Controller":"/test/service/feed/","Request.Method.Type":"GET","Response.code":"200","Server.IP":"localhost"}
下面是我在ELK中看到的图片
好的,我将补充 Jan Mares 在评论中提到的内容。
因此,当您使用 filebeat 从 Spring 获取日志并将它们直接发送到 ELK 时,您需要创建一个摄取管道并告诉它您要解析的字段。
现在,完成后转到您的索引模式并单击它。有一个用于编辑设置的选项卡,然后您需要将以下内容添加到 JSON 设置:
"index.default_pipeline": "在此处插入您的摄取设置"
在那之后......一切都应该继续解析。