【问题标题】:Issue with Kibana log entry using Spring Boot & MDC Filter使用 Spring Boot 和 MDC 过滤器的 Kibana 日志条目问题
【发布时间】:2020-11-23 16:02:17
【问题描述】:

我在 elastic.co 上玩 ELK 堆栈,现在我已经敲了 5 个小时的头(尽管阅读了文档和文档)。

所以我有一个 Spring Boot API,它写入一个 JSON 日志文件。该日志文件由 filebeat 获取并发送到 Elastic.co ELK 堆栈,在那里我可以在 Kibana 中查看数据。

在我的 API 中,我有一个过滤器类,它向日志中添加了一些值,例如响应代码等(如下所示),但是我看到的是,在 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 中看到的图像

【问题讨论】:

  • 这可能是关于设置 ELK 堆栈以将您的消息视为 JSON - 现在似乎没有意识到它们是 JSON 并将它们作为纯字符串行处理的事实。但是您的服务产生的输出似乎很好。不过,不确定这是如何在 ELK 上完成的。
  • 我想你可能正在做点什么。现在可能是我需要应用注入管道。任何人都知道如何使用 Filebeat 来做到这一点(我没有使用 logstash)。谢谢你的回复顺便说一句!!
  • 好的,感谢 Jan 的帮助。所以基本上你是对的!我必须设置一个摄取管道来解析 JSON。再次感谢您

标签: spring spring-boot kibana elastic-stack


【解决方案1】:

好的,我将补充一下 Jan Mares 在评论中提到的内容。

因此,当您使用 filebeat 从 Spring 获取日志并将它们直接发送到 ELK 时,您需要创建一个摄取管道并告诉它您要解析的字段。

现在,完成后转到您的索引模式并单击它。有一个用于编辑设置的选项卡,您需要在其中将以下内容添加到 JSON 设置:

"index.default_pipeline": "在此处插入您的摄取设置"

在那之后......一切都应该向前解析。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 2015-02-08
    • 2018-10-15
    • 2019-02-24
    • 1970-01-01
    • 2018-06-05
    • 2019-01-31
    • 2022-09-24
    相关资源
    最近更新 更多