解析和组织日志

编辑

如果您的日志数据是非结构化或半结构化的,您可以对其进行解析并将其分解为有意义的字段。您可以使用这些字段来探索和分析您的数据。例如,您可以查找特定时间范围内的日志,或按日志级别过滤日志以关注潜在问题。

解析后,您可以使用结构化字段通过配置重路由处理器将特定日志发送到不同的目标数据流,从而进一步组织您的日志。

有关解析和组织日志数据的更多信息,请参阅以下部分

提取结构化字段

编辑

通过从非结构化日志数据中提取结构化字段,使您的日志更有用。提取结构化字段可以更轻松地搜索、分析和过滤您的日志数据。

按照以下步骤查看默认情况下如何索引以下非结构化日志数据

2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.

首先将文档存储在 logs-example-default 数据流中

  1. 要打开 控制台,请在 全局搜索字段 中找到 Dev Tools
  2. 控制台 选项卡中,使用以下命令将示例日志添加到 Elasticsearch

    POST logs-example-default/_doc
    {
      "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%."
    }
  3. 然后,您可以使用以下搜索检索文档

    GET /logs-example-default/_search

结果应如下所示

{
  ...
  "hits": {
    ...
    "hits": [
      {
        "_index": ".ds-logs-example-default-2023.08.09-000001",
        ...
        "_source": {
          "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.",
          "@timestamp": "2023-08-09T17:19:27.73312243Z"
        }
      }
    ]
  }
}

Elasticsearch 默认情况下会索引 message 字段并添加 @timestamp 字段。由于没有设置时间戳,因此将其设置为 now。此时,您可以搜索 message 字段中的短语,例如 WARNDisk usage exceeds。例如,使用以下命令在日志的 message 字段中搜索短语 WARN

GET logs-example-default/_search
{
  "query": {
    "match": {
      "message": {
        "query": "WARN"
      }
    }
  }
}

虽然您可以在 message 字段中搜索短语,但您无法使用此字段来过滤日志数据。但是,您的消息包含所有以下潜在字段,您可以提取这些字段并将其用于过滤和聚合日志数据

  • @timestamp (2023-08-08T13:45:12.123Z):提取此字段可让您按日期和时间对日志进行排序。当您想按发生的顺序查看日志或确定问题发生时间时,这很有帮助。
  • log.level (WARN):提取此字段可让您按严重性过滤日志。如果您想关注高严重性的 WARN 或 ERROR 级别的日志,并通过过滤掉低严重性的 INFO 级别的日志来减少噪音,这很有帮助。
  • host.ip (192.168.1.101):提取此字段可让您按主机 IP 地址过滤日志。如果您想关注遇到问题的特定主机,或者想查找主机之间的差异,这很有帮助。
  • message (Disk usage exceeds 90%.):您可以在消息字段中搜索短语或单词。

这些字段是 Elastic 通用架构 (ECS) 的一部分。ECS 定义了一组可在存储数据(包括日志和指标数据)时跨 Elasticsearch 使用的通用字段。

提取 @timestamp 字段

编辑

在上一节中将日志添加到 Elasticsearch 时,@timestamp 字段显示了添加日志的时间。显示日志实际发生时间的的时间戳位于非结构化的 message 字段中

        ...
        "_source": {
          "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.",
          "@timestamp": "2023-08-09T17:19:27.73312243Z"
        }
        ...

message 字段中的时间戳显示日志发生的时间。

@timestamp 字段中的时间戳显示日志添加到 Elasticsearch 的时间。

在调查问题时,您希望按问题发生的时间而不是日志添加到项目的时段过滤日志。为此,请通过完成以下操作将时间戳从非结构化的 message 字段提取到结构化的 @timestamp 字段中

使用摄取管道提取 @timestamp 字段
编辑

摄取管道由一系列处理器组成,这些处理器在索引传入文档之前对其执行常见的转换。要从示例日志中提取 @timestamp 字段,请使用带有 dissect 处理器的摄取管道。 dissect 处理器 根据您设置的模式从非结构化日志消息中提取结构化字段。

Elasticsearch 可以将格式为 yyyy-MM-dd'T'HH:mm:ss.SSSZyyyy-MM-dd 的字符串时间戳解析为日期字段。由于日志示例的时间戳采用其中一种格式,因此您不需要其他处理器。更复杂或非标准的时间戳需要 日期处理器 将时间戳解析为日期字段。

使用以下命令将时间戳从 message 字段提取到 @timestamp 字段

PUT _ingest/pipeline/logs-example-default
{
  "description": "Extracts the timestamp",
  "processors": [
    {
      "dissect": {
        "field": "message",
        "pattern": "%{@timestamp} %{message}"
      }
    }
  ]
}

管道的名称 logs-example-default 必须与您的数据流的名称匹配。您将在下一节中设置您的数据流。有关更多信息,请参阅 数据流命名方案

您从中提取数据的字段,在本例中为 message

日志数据中元素的模式。 %{@timestamp} %{message} 模式将时间戳 2023-08-08T13:45:12.123Z 提取到 @timestamp 字段,而消息的其余部分 WARN 192.168.1.101 Disk usage exceeds 90%. 则保留在 message 字段中。dissect 处理器将空格作为模式定义的分隔符进行查找。

使用模拟管道 API 测试管道
编辑

模拟管道 API 运行摄取管道而不存储任何文档。这使您可以使用多个文档验证您的管道是否正常工作。运行以下命令以使用模拟管道 API 测试您的摄取管道。

POST _ingest/pipeline/logs-example-default/_simulate
{
  "docs": [
    {
      "_source": {
        "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%."
      }
    }
  ]
}

结果应显示从 message 字段提取的 @timestamp 字段

{
  "docs": [
    {
      "doc": {
        "_index": "_index",
        "_id": "_id",
        "_version": "-3",
        "_source": {
          "message": "WARN 192.168.1.101 Disk usage exceeds 90%.",
          "@timestamp": "2023-08-08T13:45:12.123Z"
        },
        ...
      }
    }
  ]
}

在使用模拟管道 API 之前,请确保已使用上一节中的 PUT 命令创建了摄取管道。

使用索引模板配置数据流
编辑

创建摄取管道后,运行以下命令以创建索引模板来配置数据流的备份索引

PUT _index_template/logs-example-default-template
{
  "index_patterns": [ "logs-example-*" ],
  "data_stream": { },
  "priority": 500,
  "template": {
    "settings": {
      "index.default_pipeline":"logs-example-default"
    }
  },
  "composed_of": [
    "logs@mappings",
    "logs@settings",
    "logs@custom",
    "ecs@mappings"
  ],
  "ignore_missing_component_templates": ["logs@custom"]
}

index_pattern:需要与您的日志数据流匹配。数据流的命名约定为 <type>-<dataset>-<namespace>。在本例中,您的日志数据流名为 logs-example-*。与该模式匹配的数据将通过您的管道。

data_stream:启用数据流。

priority:设置索引模板的优先级。优先级较高的索引模板优先于优先级较低的索引模板。如果数据流与多个索引模板匹配,则 Elasticsearch 将使用优先级较高的模板。内置模板的优先级为 200,因此对于自定义模板,请使用高于 200 的优先级。

index.default_pipeline:您的摄取管道的名称。在本例中为 logs-example-default

composed_of:在这里您可以设置组件模板。组件模板是构建索引模板的构建块,用于指定索引映射、设置和别名。Elastic 有几个内置模板,可以在摄取日志数据时提供帮助。

上面的示例索引模板设置了以下组件模板

  • logs@mappings:日志数据流的通用映射,包括禁用来自 string 字段的自动日期检测以及指定 data_stream ECS 字段 的映射。
  • logs@settings:日志数据流的通用设置,包括以下内容

    • 当主分片达到 50 GB 或 30 天后,默认的生命周期策略将进行滚动。
    • 如果未指定 @timestamp,则默认管道将使用摄取时间戳,并为 logs@custom 管道设置一个挂钩。如果安装了 logs@custom 管道,则将其应用于摄取到此数据流中的日志。
    • ignore_malformed 标志设置为 true。在摄取大量日志数据时,单个格式错误的字段(如 IP 地址)会导致整个批处理失败。当设置为 true 时,仍然会处理具有支持此标志的映射类型的格式错误的字段。
  • logs@custom:默认情况下未安装的预定义组件模板。使用此名称安装自定义组件模板以覆盖或扩展任何默认映射或设置。
  • ecs@mappings:动态模板,可自动确保您的数据流映射符合 Elastic 通用架构 (ECS)
创建数据流
编辑

使用 数据流命名方案 创建您的数据流。将数据流命名为与您的摄取管道名称匹配,在本例中为 logs-example-default。使用此命令将示例日志发布到您的数据流

POST logs-example-default/_doc
{
  "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%."
}

使用此命令查看您的文档

GET /logs-example-default/_search

您应该看到管道已提取 @timestamp 字段

{
...
{
  ...
  "hits": {
    ...
    "hits": [
      {
        "_index": ".ds-logs-example-default-2023.08.09-000001",
        "_id": "RsWy3IkB8yCtA5VGOKLf",
        "_score": 1,
        "_source": {
          "message": "WARN 192.168.1.101 Disk usage exceeds 90%.",
          "@timestamp": "2023-08-08T13:45:12.123Z"
        }
      }
    ]
  }
}

提取的 @timestamp 字段。

您现在可以使用 @timestamp 字段按日志发生的日期和时间对日志进行排序。

@timestamp 字段故障排除
编辑

检查以下时间戳的常见问题和解决方案

  • 时间戳失败:如果您的数据具有不一致的日期格式,请为您的日期处理器将 ignore_failure 设置为 true。这将处理格式正确的日期的日志,并忽略存在问题的时间戳。
  • 时区错误:使用 日期处理器上的 timezone 选项设置您的时区。
  • 时间戳格式错误:您的时间戳可以是 Java 时间模式或以下格式之一:ISO8601、UNIX、UNIX_MS 或 TAI64N。有关时间戳格式的更多信息,请参阅 映射日期格式

提取 log.level 字段

编辑

提取 log.level 字段允许您按严重性进行筛选,并关注关键问题。本节将向您展示如何从以下示例日志中提取 log.level 字段

2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.

要提取和使用 log.level 字段

log.level 添加到您的摄取管道
编辑

使用以下命令,将 %{log.level} 选项添加到您在 提取 @timestamp 字段 部分中创建的摄取管道中的 dissect 处理器模式中

PUT _ingest/pipeline/logs-example-default
{
  "description": "Extracts the timestamp and log level",
  "processors": [
    {
      "dissect": {
        "field": "message",
        "pattern": "%{@timestamp} %{log.level} %{message}"
      }
    }
  ]
}

现在您的管道将提取以下字段

  • @timestamp 字段:2023-08-08T13:45:12.123Z
  • log.level 字段:WARN
  • message 字段:192.168.1.101 Disk usage exceeds 90%.

除了设置摄取管道外,您还需要设置索引模板。您可以使用在 提取 @timestamp 字段 部分中创建的索引模板。

使用模拟 API 测试管道
编辑

使用 模拟管道 API 测试您的摄取管道是否按预期工作

POST _ingest/pipeline/logs-example-default/_simulate
{
  "docs": [
    {
      "_source": {
        "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%."
      }
    }
  ]
}

结果应显示从 message 字段提取的 @timestamplog.level 字段

{
  "docs": [
    {
      "doc": {
        "_index": "_index",
        "_id": "_id",
        "_version": "-3",
        "_source": {
          "message": "192.168.1.101 Disk usage exceeds 90%.",
          "log": {
            "level": "WARN"
          },
          "@timestamp": "2023-8-08T13:45:12.123Z",
        },
        ...
      }
    }
  ]
}
基于 log.level 查询日志
编辑

提取 log.level 字段后,您可以查询诸如 WARNERROR 之类的高严重性日志(可能需要立即关注),并过滤掉不太关键的 INFODEBUG 日志。

假设您有以下具有不同严重性的日志

2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.
2023-08-08T13:45:14.003Z ERROR 192.168.1.103 Database connection failed.
2023-08-08T13:45:15.004Z DEBUG 192.168.1.104 Debugging connection issue.
2023-08-08T13:45:16.005Z INFO 192.168.1.102 User changed profile picture.

使用以下命令将它们添加到您的数据流中

POST logs-example-default/_bulk
{ "create": {} }
{ "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%." }
{ "create": {} }
{ "message": "2023-08-08T13:45:14.003Z ERROR 192.168.1.103 Database connection failed." }
{ "create": {} }
{ "message": "2023-08-08T13:45:15.004Z DEBUG 192.168.1.104 Debugging connection issue." }
{ "create": {} }
{ "message": "2023-08-08T13:45:16.005Z INFO 192.168.1.102 User changed profile picture." }

然后,使用以下命令查询日志级别为 WARNERROR 的文档

GET logs-example-default/_search
{
  "query": {
    "terms": {
      "log.level": ["WARN", "ERROR"]
    }
  }
}

结果应仅显示高严重性日志

{
...
  },
  "hits": {
  ...
    "hits": [
      {
        "_index": ".ds-logs-example-default-2023.08.14-000001",
        "_id": "3TcZ-4kB3FafvEVY4yKx",
        "_score": 1,
        "_source": {
          "message": "192.168.1.101 Disk usage exceeds 90%.",
          "log": {
            "level": "WARN"
          },
          "@timestamp": "2023-08-08T13:45:12.123Z"
        }
      },
      {
        "_index": ".ds-logs-example-default-2023.08.14-000001",
        "_id": "3jcZ-4kB3FafvEVY4yKx",
        "_score": 1,
        "_source": {
          "message": "192.168.1.103 Database connection failed.",
          "log": {
            "level": "ERROR"
          },
          "@timestamp": "2023-08-08T13:45:14.003Z"
        }
      }
    ]
  }
}

提取 host.ip 字段

编辑

提取 host.ip 字段允许您按主机 IP 地址过滤日志,从而使您能够专注于遇到问题的特定主机或查找主机之间的差异。

host.ip 字段是 Elastic Common Schema (ECS) 的一部分。通过 ECS,host.ip 字段被映射为 ip 字段类型ip 字段类型允许范围查询,因此您可以查找特定范围内的 IP 地址的日志。您还可以使用无类别域间路由 (CIDR) 表示法查询 ip 字段类型,以查找来自特定网络或子网的日志。

本节将向您展示如何从以下示例日志中提取 host.ip 字段并基于提取的字段进行查询

2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.
2023-08-08T13:45:14.003Z ERROR 192.168.1.103 Database connection failed.
2023-08-08T13:45:15.004Z DEBUG 192.168.1.104 Debugging connection issue.
2023-08-08T13:45:16.005Z INFO 192.168.1.102 User changed profile picture.

要提取和使用 host.ip 字段

host.ip 添加到您的摄取管道
编辑

%{host.ip} 选项添加到您在 提取 @timestamp 字段 部分中创建的摄取管道中的 dissect 处理器模式中

PUT _ingest/pipeline/logs-example-default
{
  "description": "Extracts the timestamp log level and host ip",
  "processors": [
    {
      "dissect": {
        "field": "message",
        "pattern": "%{@timestamp} %{log.level} %{host.ip} %{message}"
      }
    }
  ]
}

您的管道将提取以下字段

  • @timestamp 字段:2023-08-08T13:45:12.123Z
  • log.level 字段:WARN
  • host.ip 字段:192.168.1.101
  • message 字段:Disk usage exceeds 90%.

除了设置摄取管道外,您还需要设置索引模板。您可以使用在 提取 @timestamp 字段 部分中创建的索引模板。

使用模拟 API 测试管道
编辑

使用 模拟管道 API 测试您的摄取管道是否按预期工作

POST _ingest/pipeline/logs-example-default/_simulate
{
  "docs": [
    {
      "_source": {
        "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%."
      }
    }
  ]
}

结果应显示从 message 字段提取的 host.ip@timestamplog.level 字段

{
  "docs": [
    {
      "doc": {
        ...
        "_source": {
          "host": {
            "ip": "192.168.1.101"
          },
          "@timestamp": "2023-08-08T13:45:12.123Z",
          "message": "Disk usage exceeds 90%.",
          "log": {
            "level": "WARN"
          }
        },
        ...
      }
    }
  ]
}
基于 host.ip 查询日志
编辑

您可以通过多种方式基于 host.ip 字段查询日志,包括使用 CIDR 表示法和范围查询。

在查询日志之前,请使用以下命令将它们添加到您的数据流中

POST logs-example-default/_bulk
{ "create": {} }
{ "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%." }
{ "create": {} }
{ "message": "2023-08-08T13:45:14.003Z ERROR 192.168.1.103 Database connection failed." }
{ "create": {} }
{ "message": "2023-08-08T13:45:15.004Z DEBUG 192.168.1.104 Debugging connection issue." }
{ "create": {} }
{ "message": "2023-08-08T13:45:16.005Z INFO 192.168.1.102 User changed profile picture." }
CIDR 表示法
编辑

您可以使用 CIDR 表示法 使用属于特定网络段的 IP 地址块查询您的日志数据。CIDR 表示法使用 [IP 地址]/[前缀长度] 的格式。以下命令查询 192.168.1.0/24 子网中的 IP 地址,这意味着从 192.168.1.0192.168.1.255 的 IP 地址。

GET logs-example-default/_search
{
  "query": {
    "term": {
      "host.ip": "192.168.1.0/24"
    }
  }
}

因为所有示例日志都在此范围内,所以您将获得以下结果

{
  ...
  },
  "hits": {
    ...
      {
        "_index": ".ds-logs-example-default-2023.08.16-000001",
        "_id": "ak4oAIoBl7fe5ItIixuB",
        "_score": 1,
        "_source": {
          "host": {
            "ip": "192.168.1.101"
          },
          "@timestamp": "2023-08-08T13:45:12.123Z",
          "message": "Disk usage exceeds 90%.",
          "log": {
            "level": "WARN"
          }
        }
      },
      {
        "_index": ".ds-logs-example-default-2023.08.16-000001",
        "_id": "a04oAIoBl7fe5ItIixuC",
        "_score": 1,
        "_source": {
          "host": {
            "ip": "192.168.1.103"
          },
          "@timestamp": "2023-08-08T13:45:14.003Z",
          "message": "Database connection failed.",
          "log": {
            "level": "ERROR"
          }
        }
      },
      {
        "_index": ".ds-logs-example-default-2023.08.16-000001",
        "_id": "bE4oAIoBl7fe5ItIixuC",
        "_score": 1,
        "_source": {
          "host": {
            "ip": "192.168.1.104"
          },
          "@timestamp": "2023-08-08T13:45:15.004Z",
          "message": "Debugging connection issue.",
          "log": {
            "level": "DEBUG"
          }
        }
      },
      {
        "_index": ".ds-logs-example-default-2023.08.16-000001",
        "_id": "bU4oAIoBl7fe5ItIixuC",
        "_score": 1,
        "_source": {
          "host": {
            "ip": "192.168.1.102"
          },
          "@timestamp": "2023-08-08T13:45:16.005Z",
          "message": "User changed profile picture.",
          "log": {
            "level": "INFO"
          }
        }
      }
    ]
  }
}
范围查询
编辑

使用 范围查询 查询特定范围内的日志。

以下命令搜索大于或等于 192.168.1.100 且小于或等于 192.168.1.102 的 IP 地址。

GET logs-example-default/_search
{
  "query": {
    "range": {
      "host.ip": {
        "gte": "192.168.1.100",
        "lte": "192.168.1.102"
      }
    }
  }
}

大于或等于 192.168.1.100

小于或等于 192.168.1.102

您将获得以下结果,仅显示您设置范围内的日志

{
  ...
  },
  "hits": {
    ...
      {
        "_index": ".ds-logs-example-default-2023.08.16-000001",
        "_id": "ak4oAIoBl7fe5ItIixuB",
        "_score": 1,
        "_source": {
          "host": {
            "ip": "192.168.1.101"
          },
          "@timestamp": "2023-08-08T13:45:12.123Z",
          "message": "Disk usage exceeds 90%.",
          "log": {
            "level": "WARN"
          }
        }
      },
      {
        "_index": ".ds-logs-example-default-2023.08.16-000001",
        "_id": "bU4oAIoBl7fe5ItIixuC",
        "_score": 1,
        "_source": {
          "host": {
            "ip": "192.168.1.102"
          },
          "@timestamp": "2023-08-08T13:45:16.005Z",
          "message": "User changed profile picture.",
          "log": {
            "level": "INFO"
          }
        }
      }
    ]
  }
}

将日志数据重新路由到特定数据流

编辑

默认情况下,摄取管道会将您的日志数据发送到单个数据流。为了简化日志数据管理,请使用 重新路由处理器 将数据从通用数据流路由到目标数据流。例如,您可能希望将高严重性日志发送到特定数据流以帮助进行分类。

本节将向您展示如何使用重新路由处理器将以下示例日志中的高严重性日志(WARNERROR)发送到特定数据流,并将常规日志(DEBUGINFO)保留在默认数据流中

2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%.
2023-08-08T13:45:14.003Z ERROR 192.168.1.103 Database connection failed.
2023-08-08T13:45:15.004Z DEBUG 192.168.1.104 Debugging connection issue.
2023-08-08T13:45:16.005Z INFO 192.168.1.102 User changed profile picture.

将数据路由到不同的数据流时,我们建议选择一个具有有限数量的不同值的字段,以防止数据流数量过分增加。有关更多详细信息,请参阅 调整分片大小 文档。

要使用重新路由处理器

将重新路由处理器添加到摄取管道

编辑

使用以下命令将重新路由处理器添加到您的摄取管道

PUT _ingest/pipeline/logs-example-default
{
  "description": "Extracts fields and reroutes WARN",
  "processors": [
    {
      "dissect": {
        "field": "message",
        "pattern": "%{@timestamp} %{log.level} %{host.ip} %{message}"
      },
      "reroute": {
        "tag": "high_severity_logs",
        "if" : "ctx.log?.level == 'WARN' || ctx.log?.level == 'ERROR'",
        "dataset": "critical"
      }
    }
  ]
}

tag:处理器的标识符,可用于调试和指标。在本例中,标签设置为 high_severity_logs

if:有条件地运行处理器。在本例中,"ctx.log?.level == 'WARN' || ctx.log?.level == 'ERROR'", 表示当 log.level 字段为 WARNERROR 时运行处理器。

dataset:如果上一个条件为 true,则将文档路由到的数据流数据集。在本例中,日志级别为 WARNERROR 的日志将路由到 logs-critical-default 数据流。

除了设置摄取管道外,您还需要设置索引模板。您可以使用在 提取 @timestamp 字段 部分中创建的索引模板。

将日志添加到数据流

编辑

使用以下命令将示例日志添加到您的数据流

POST logs-example-default/_bulk
{ "create": {} }
{ "message": "2023-08-08T13:45:12.123Z WARN 192.168.1.101 Disk usage exceeds 90%." }
{ "create": {} }
{ "message": "2023-08-08T13:45:14.003Z ERROR 192.168.1.103 Database connection failed." }
{ "create": {} }
{ "message": "2023-08-08T13:45:15.004Z DEBUG 192.168.1.104 Debugging connection issue." }
{ "create": {} }
{ "message": "2023-08-08T13:45:16.005Z INFO 192.168.1.102 User changed profile picture." }

验证重新路由处理器是否有效

编辑

重新路由处理器应将任何日志级别为 WARNERROR 的日志路由到 logs-critical-default 数据流。使用以下命令查询数据流以验证日志数据是否按预期路由

GET logs-critical-default/_search

您应该会看到类似以下的结果,显示高严重性日志现在位于 critical 数据集中

{
  ...
  "hits": {
    ...
    "hits": [
        ...
        "_source": {
          "host": {
            "ip": "192.168.1.101"
          },
          "@timestamp": "2023-08-08T13:45:12.123Z",
          "message": "Disk usage exceeds 90%.",
          "log": {
            "level": "WARN"
          },
          "data_stream": {
            "namespace": "default",
            "type": "logs",
            "dataset": "critical"
          },
          {
        ...
        "_source": {
          "host": {
            "ip": "192.168.1.103"
           },
          "@timestamp": "2023-08-08T13:45:14.003Z",
          "message": "Database connection failed.",
          "log": {
            "level": "ERROR"
          },
          "data_stream": {
            "namespace": "default",
            "type": "logs",
            "dataset": "critical"
          }
        }
      }
    ]
  }
}