如何使用 log4j2 将 JSON 结构作为源而不是消息记录到弹性搜索中

How to record a JSON structure as source instead of message into elastic search using log4j2

我的log4j2.xml如下,

<Configuration status="info">
  <Properties>
    <Property name="basePath">./</Property>
  </Properties>

  <Appenders>

    <Console name="console" target="SYSTEM_OUT">
      <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/>
    </Console>

    <Http name="ES" url="http://localhost:9200/test/log4j/">
      <JSONLayout complete="false" compact="true" eventEol="true" objectMessageAsJsonObject="true" />
    </Http>
  </Appenders>

  <Loggers>
    <Logger name="io.github.sylllys" level="info" additivity="true">
      <appender-ref ref="ES" level="info"/>
    </Logger>
    <Root level="info" additivity="false">
      <appender-ref ref="console"/>
    </Root>
  </Loggers>
</Configuration>

当我记录一些 json 负载时,它存储在消息元组下,当我尝试使用 API 获取弹性结果时,我得到以下响应,查看元组:hits.hits[0]._source.message,那是我从 java 程序中登录的 json,

  "took": 87,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 54,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "test",
        "_type": "log4j",
        "_id": "2KYwiXwBpgzgsgok5uIw",
        "_score": 1.0,
        "_source": {
          "instant": {
            "epochSecond": 1634389248,
            "nanoOfSecond": 549000000
          },
          "thread": "main",
          "level": "INFO",
          "loggerName": "io.github.sylllys.test.suite.stepDefinitions.Log4JStepDefinitions",
          "message": {
             "test_exec_id": "smoke3",
             "test_suite_id": "suite1",
             "test_case_id": "case1",
             "test_object": "xyz request",
             "assertion_objective": "validation for xyz1 format",
             "assertion_status": "false"
          },
          "endOfBatch": false,
          "loggerFqcn": "org.apache.logging.log4j.spi.AbstractLogger",
          "threadId": 1,
          "threadPriority": 5
        }
      }
    ]
  }
}

我只想让元组 hits.hits[0]._source 只包含我已记录的信息,

示例:

{
  "took": 104,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 6,
      "relation": "eq"
    },
    "max_score": 3.2219477,
    "hits": [
      {
        "_index": "test-records",
        "_type": "_doc",
        "_id": "qDkdenwBHlfFxA75kZ_Q",
        "_score": 3.2219477,
        "_source": {
          "assertion_objective": "validation for xyz1 format",
          "assertion_status": "false",
          "test_case_id": "case1",
          "test_suite_id": "suite1",
          "test_object": "xyz request",
          "test_exec_id": "smoke1"
        }
      }
    ]
  }
}

这里还有我用来记录消息的 Java 代码,

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ObjectMessage;

    Logger logger = LogManager.getLogger(Log4JStepDefinitions.class);
    TestReportDetails testReportDetails = new TestReportDetails();
    //code to set details into testReportDetails
    logger.info(new ObjectMessage(testReportDetails));

我通过将 log4j2 的 HTTP appender 指向我的自定义服务器解决了这个问题,我在其中编写了代码以按照我想要的方式重新格式化 JSON,然后使用弹性 api 来保存他们。