文本结构 API

edit

您可以使用以下API来查找文本结构:

查找字段结构 API

edit

查找Elasticsearch索引中字段的结构。

请求

edit

GET _text_structure/find_field_structure

先决条件

edit
  • 如果启用了Elasticsearch安全功能,您必须拥有monitor_text_structuremonitor集群权限才能使用此API。请参阅 安全权限

描述

edit

此API为从已摄取到Elasticsearch的日志消息中提取更多信息提供了一个起点。例如,如果您已经将数据摄取到一个非常简单的索引中,该索引仅包含@timestampmessage字段,您可以使用此API查看message字段中存在的常见结构。

API的响应包含:

  • 示例消息。
  • 揭示文本中检测到的所有字段的最常见值的统计数据,以及数值字段的基本数值统计数据。
  • 关于文本结构的详细信息,这在您编写摄取配置以索引它或类似格式的文本时非常有用。
  • 适用于Elasticsearch索引的适当映射,您可以使用它来摄取文本。

所有这些信息都可以在没有指导的情况下由结构查找器计算出来。 然而,您可以选择通过指定一个或多个查询参数来覆盖关于文本结构的一些决定。

输出细节可以在示例中查看。

如果结构查找器产生意外结果, 请指定explain查询参数,响应中将出现explanation。它有助于确定为何选择了返回的结构。

查询参数

edit
index
(必需, 字符串) 包含字段的索引名称。
field
(必需,字符串) 被分析的字段的名称。
column_names
(可选, 字符串) 如果你已将 format 设置为 delimited,你可以指定以逗号分隔的列名列表。如果未指定此参数,结构查找器将使用文本的标题行中的列名。如果文本没有标题行,列将被命名为 "column1", "column2", "column3" 等。
delimiter
(可选,字符串) 如果你已将 format 设置为 delimited,你可以指定用于分隔每行中值的字符。仅支持单个字符;分隔符不能包含多个字符。默认情况下,API 会考虑以下可能性:逗号、制表符、分号和竖线 (|)。在这种默认情况下,所有行必须具有相同数量的字段,才能检测到分隔格式。如果你指定了一个分隔符,最多可以有 10% 的行与第一行的列数不同。
documents_to_sample
(可选,无符号整数) 用于结构分析的文档数量。最小值为 2;默认值为 1000。
explain
(可选,布尔值) 如果为true,响应中将包含一个名为explanation的字段,该字段是一个字符串数组,指示结构查找器如何生成其结果。默认值为false
format
(可选,字符串) 文本的高级结构。有效值为 ndjsonxmldelimitedsemi_structured_text。默认情况下,API 会选择格式。在这种默认情况下,所有行必须具有相同数量的字段,才能检测到分隔格式。如果将 format 设置为 delimited 并且未设置 delimiter,则 API 允许最多 5% 的行与第一行的列数不同。
grok_pattern
(可选,字符串) 如果你已将 format 设置为 semi_structured_text,你可以 指定一个 Grok 模式,用于从文本中的每条消息中提取字段。Grok 模式中的时间戳字段的名称必须与 timestamp_field 参数中指定的名称匹配。如果未指定该参数,Grok 模式中的时间戳字段的名称必须匹配 "timestamp"。如果未指定 grok_pattern,结构查找器将创建一个 Grok 模式。
ecs_compatibility
(可选,字符串) 与符合 ECS 的 Grok 模式兼容的模式。 使用此参数指定在结构查找器创建 Grok 模式时是否使用 ECS Grok 模式而不是传统模式。有效值为 disabledv1。默认值为 disabled。此设置主要在输入匹配整个消息 Grok 模式(如 %{CATALINALOG})时产生影响。如果结构查找器识别出常见结构但不知道其含义,则在 grok_pattern 输出中使用通用字段名称,如 pathipaddressfield1field2,目的是让了解含义的用户在使用前重命名这些字段。
quote
(可选,字符串) 如果你已将 format 设置为 delimited,你可以指定用于引用每行中值的字符,如果它们包含换行符或分隔符字符。仅支持单个字符。如果未指定此参数,默认值是双引号 (")。如果你的分隔文本格式不使用引用,一种解决方法是将此参数设置为一个在样本中不出现的字符。
should_trim_fields
(可选, 布尔值) 如果你已将 format 设置为 delimited,你可以指定 分隔符之间的值是否应去除空白。如果 未指定此参数且分隔符为管道 (|),默认 值为 true。否则,默认值为 false
timeout
(可选,时间单位) 设置结构分析可能花费的最大时间。如果分析在超时到期时仍在运行,则它将被停止。默认值为25秒。
timestamp_field

(可选,字符串) 包含文本中每个记录的主时间戳的字段名称。特别是,如果将文本导入索引, 这将是要用于填充 @timestamp 字段的字段。

如果formatsemi_structured_text,此字段必须与grok_pattern中的适当提取名称匹配。因此,对于半结构化文本,最好不要指定此参数,除非也指定了grok_pattern

对于结构化文本,如果您指定此参数,该字段必须存在于文本中。

如果未指定此参数,结构查找器将决定哪个字段(如果有)是主时间戳字段。对于结构化文本,文本中不一定需要有时间戳。

timestamp_format

(可选, 字符串) 文本中时间戳字段的Java时间格式。

仅支持部分Java时间格式字母组:

  • a
  • d
  • dd
  • EEE
  • EEEE
  • H
  • HH
  • h
  • M
  • MM
  • MMM
  • MMMM
  • mm
  • ss
  • XX
  • XXX
  • yy
  • yyyy
  • zzz

此外,支持长度为一到九的 S 字母组(小数秒),前提是它们出现在 ss 之后,并且与 ss 之间用 .,: 分隔。除了 ?、换行符和回车符外,还允许使用空格和标点符号,以及用单引号括起来的文字文本。例如,MM/dd HH.mm.ss,SSSSSS 'in' yyyy 是一个有效的覆盖格式。

这个参数的一个有价值的用例是当格式是半结构化文本时,文本中有多个时间戳格式,并且你知道哪个格式对应于主要时间戳,但你不想指定完整的grok_pattern。另一个用例是当时间戳格式是结构查找器默认不考虑的格式时。

如果未指定此参数,结构查找器将从内置集合中选择最佳格式。

如果指定了特殊值 null,结构查找器将不会在文本中查找主时间戳。当格式为半结构化文本时,这将导致结构查找器将文本视为单行消息。

下表提供了一些示例时间戳的适当timeformat值:

时间格式 展示

yyyy-MM-dd HH:mm:ssZ

2019-04-20 13:15:22+0000

星期三, d 月 yyyy HH:mm:ss Z

2019年4月20日 星期六 13:15:22 +0000

dd.MM.yy HH:mm:ss.SSS

2020年4月19日 13:15:22.285

请参考 Java 日期/时间格式文档 以获取更多关于日期和时间格式语法的信息。

示例

edit
分析 Elasticsearch 日志文件
edit

假设你有一个包含Elasticsearch日志消息的索引。 你可以使用find_field_structure端点来分析它们,如下所示:

POST _bulk?refresh=true
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:36,256][INFO ][o.a.l.u.VectorUtilPanamaProvider] [laptop] Java vector incubator API enabled; uses preferredBitSize=128"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,038][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-url]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,042][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [rest-root]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-core]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-redact]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [ingest-user-agent]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-monitoring]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-s3]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-analytics]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-ent-search]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-autoscaling]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [lang-painless]]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,059][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [lang-expression]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:41,059][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-eql]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:43,291][INFO ][o.e.e.NodeEnvironment    ] [laptop] heap size [16gb], compressed ordinary object pointers [true]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:46,098][INFO ][o.e.x.s.Security         ] [laptop] Security is enabled"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:47,227][INFO ][o.e.x.p.ProfilingPlugin  ] [laptop] Profiling is enabled"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:47,259][INFO ][o.e.x.p.ProfilingPlugin  ] [laptop] profiling index templates will not be installed or reinstalled"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:47,755][INFO ][o.e.i.r.RecoverySettings ] [laptop] using rate limit [40mb] with [default=40mb, read=0b, write=0b, max=0b]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:47,787][INFO ][o.e.d.DiscoveryModule    ] [laptop] using discovery type [multi-node] and seed hosts providers [settings]"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:49,188][INFO ][o.e.n.Node               ] [laptop] initialized"}
{"index":{"_index":"test-logs"}}
{"message":"[2024-03-05T10:52:49,199][INFO ][o.e.n.Node               ] [laptop] starting ..."}

GET _text_structure/find_field_structure?index=test-logs&field=message

如果请求没有遇到错误,您将收到以下结果:

{
  "num_lines_analyzed" : 22,
  "num_messages_analyzed" : 22,
  "sample_start" : "[2024-03-05T10:52:36,256][INFO ][o.a.l.u.VectorUtilPanamaProvider] [laptop] Java vector incubator API enabled; uses preferredBitSize=128\n[2024-03-05T10:52:41,038][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-url]\n", 
  "charset" : "UTF-8",
  "format" : "semi_structured_text",
  "multiline_start_pattern" : "^\\[\\b\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}",
  "grok_pattern" : "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel} \\]\\[.*",
  "ecs_compatibility" : "disabled",
  "timestamp_field" : "timestamp",
  "joda_timestamp_formats" : [
    "ISO8601"
  ],
  "java_timestamp_formats" : [
    "ISO8601"
  ],
  "need_client_timezone" : true,
  "mappings" : {
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "loglevel" : {
        "type" : "keyword"
      },
      "message" : {
        "type" : "text"
      }
    }
  },
  "ingest_pipeline" : {
    "description" : "Ingest pipeline created by text structure finder",
    "processors" : [
      {
        "grok" : {
          "field" : "message",
          "patterns" : [
            "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel} \\]\\[.*"
          ],
          "ecs_compatibility" : "disabled"
        }
      },
      {
        "date" : {
          "field" : "timestamp",
          "timezone" : "{{ event.timezone }}",
          "formats" : [
            "ISO8601"
          ]
        }
      },
      {
        "remove" : {
          "field" : "timestamp"
        }
      }
    ]
  },
  "field_stats" : {
    "loglevel" : {
      "count" : 22,
      "cardinality" : 1,
      "top_hits" : [
        {
          "value" : "INFO",
          "count" : 22
        }
      ]
    },
    "message" : {
      "count" : 22,
      "cardinality" : 22,
      "top_hits" : [
        {
          "value" : "[2024-03-05T10:52:36,256][INFO ][o.a.l.u.VectorUtilPanamaProvider] [laptop] Java vector incubator API enabled; uses preferredBitSize=128",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,038][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-url]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,042][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [rest-root]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [ingest-user-agent]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-core]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-redact]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [lang-painless]]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-s3]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-analytics]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-autoscaling]",
          "count" : 1
        }
      ]
    },
    "timestamp" : {
      "count" : 22,
      "cardinality" : 14,
      "earliest" : "2024-03-05T10:52:36,256",
      "latest" : "2024-03-05T10:52:49,199",
      "top_hits" : [
        {
          "value" : "2024-03-05T10:52:41,044",
          "count" : 6
        },
        {
          "value" : "2024-03-05T10:52:41,043",
          "count" : 3
        },
        {
          "value" : "2024-03-05T10:52:41,059",
          "count" : 2
        },
        {
          "value" : "2024-03-05T10:52:36,256",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:41,038",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:41,042",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:43,291",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:46,098",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:47,227",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:47,259",
          "count" : 1
        }
      ]
    }
  }
}

有关响应格式的详细描述,或关于摄取定界文本(如CSV)或换行符分隔的JSON的更多示例,请参阅查找文本结构端点的示例

查找消息结构 API

edit

查找一组文本消息的结构。

请求

edit

GET _text_structure/find_message_structure
POST _text_structure/find_message_structure

先决条件

edit
  • 如果启用了Elasticsearch安全功能,您必须拥有monitor_text_structuremonitor集群权限才能使用此API。请参阅 安全权限

描述

edit

此API提供了一个将数据以适合与其他Elastic Stack功能后续使用的格式导入Elasticsearch的起点。当您的输入文本已经通过其他过程分割成单独的消息时,请优先使用此API,而不是find_structure

API的响应包含:

  • 示例消息。
  • 揭示文本中检测到的所有字段的最常见值的统计数据,以及数值字段的基本数值统计数据。
  • 关于文本结构的详细信息,这在您编写摄取配置以索引它或类似格式的文本时非常有用。
  • 适用于Elasticsearch索引的适当映射,您可以使用它来摄取文本。

所有这些信息都可以在没有指导的情况下由结构查找器计算出来。 然而,您可以选择通过指定一个或多个查询参数来覆盖关于文本结构的一些决定。

输出详情可以在示例中查看。

如果结构查找器产生意外结果, 请指定explain查询参数,响应中将出现explanation。它有助于确定为何选择了返回的结构。

查询参数

edit
column_names
(可选, 字符串) 如果你已将 format 设置为 delimited,你可以指定以逗号分隔的列名列表。如果未指定此参数,结构查找器将使用文本的标题行中的列名。如果文本没有标题行,列将被命名为 "column1", "column2", "column3" 等。
delimiter
(可选,字符串) 如果你已将 format 设置为 delimited,你可以指定用于分隔每行中值的字符。仅支持单个字符;分隔符不能包含多个字符。默认情况下,API 会考虑以下可能性:逗号、制表符、分号和竖线 (|)。在这种默认情况下,所有行必须具有相同数量的字段,才能检测到分隔格式。如果你指定了一个分隔符,最多可以有 10% 的行与第一行的列数不同。
explain
(可选,布尔值) 如果 true,响应中会包含一个名为 explanation 的字段,该字段是一个字符串数组,指示结构查找器如何生成其结果。默认值为 false
format
(可选,字符串) 文本的高级结构。有效值为 ndjsonxmldelimitedsemi_structured_text。默认情况下,API 会选择格式。在这种默认情况下,所有行必须具有相同数量的字段,才能检测到分隔格式。如果将 format 设置为 delimited 并且未设置 delimiter,则 API 允许最多 5% 的行与第一行的列数不同。
grok_pattern
(可选, 字符串) 如果你已将 format 设置为 semi_structured_text,你可以 指定一个 Grok 模式,用于从文本中的每条消息中提取字段。Grok 模式中的时间戳字段的名称必须与 timestamp_field 参数中指定的名称匹配。如果未指定该参数,Grok 模式中的时间戳字段的名称必须匹配 "timestamp"。如果未指定 grok_pattern,结构查找器将创建一个 Grok 模式。
ecs_compatibility
(可选,字符串) 与符合 ECS 的 Grok 模式兼容的模式。 使用此参数指定在结构查找器创建 Grok 模式时是否使用 ECS Grok 模式而不是传统模式。有效值为 disabledv1。默认值为 disabled。此设置主要在输入匹配整个消息 Grok 模式(如 %{CATALINALOG})时产生影响。如果结构查找器识别出常见结构但不知道其含义,则在 grok_pattern 输出中使用通用字段名称,如 pathipaddressfield1field2,目的是让了解含义的用户在使用前重命名这些字段。
quote
(可选,字符串) 如果你已将 format 设置为 delimited,你可以指定用于引用每行中值的字符,如果它们包含换行符或分隔符字符。仅支持单个字符。如果未指定此参数,默认值是双引号 (")。如果你的分隔文本格式不使用引用,一种解决方法是将此参数设置为一个在样本中不出现的字符。
should_trim_fields
(可选,布尔值) 如果你已将 format 设置为 delimited,你可以指定 分隔符之间的值是否应去除空白。如果 未指定此参数且分隔符为管道符 (|),默认 值为 true。否则,默认值为 false
timeout
(可选,时间单位) 设置结构分析可能花费的最大时间。如果分析在超时到期时仍在运行,则它将被停止。默认值为25秒。
timestamp_field

(可选,字符串) 包含文本中每个记录的主时间戳的字段名称。特别是,如果将文本导入索引, 这将是要用于填充 @timestamp 字段的字段。

如果formatsemi_structured_text,此字段必须与grok_pattern中的适当提取名称匹配。因此,对于半结构化文本,最好不要指定此参数,除非也指定了grok_pattern

对于结构化文本,如果您指定此参数,该字段必须存在于文本中。

如果未指定此参数,结构查找器将决定哪个字段(如果有)是主时间戳字段。对于结构化文本,文本中不一定需要有时间戳。

timestamp_format

(可选, 字符串) 文本中时间戳字段的Java时间格式。

仅支持部分Java时间格式字母组:

  • a
  • d
  • dd
  • EEE
  • EEEE
  • H
  • HH
  • h
  • M
  • MM
  • MMM
  • MMMM
  • mm
  • ss
  • XX
  • XXX
  • yy
  • yyyy
  • zzz

此外,支持长度为一到九的S字母组(小数秒),前提是它们出现在ss之后,并且与ss之间用.,:分隔。除了?、换行符和回车符外,还允许使用空格和标点符号,以及用单引号括起来的文字。例如,MM/dd HH.mm.ss,SSSSSS 'in' yyyy是一个有效的覆盖格式。

这个参数的一个有价值的用例是当格式是半结构化文本时,文本中有多个时间戳格式,并且你知道哪个格式对应于主要时间戳,但你不想指定完整的grok_pattern。另一个用例是当时间戳格式是结构查找器默认不考虑的格式时。

如果未指定此参数,结构查找器将从内置集合中选择最佳格式。

如果指定了特殊值 null,结构查找器将不会在文本中查找主时间戳。当格式为半结构化文本时,这将导致结构查找器将文本视为单行消息。

下表提供了一些示例时间戳的适当timeformat值:

时间格式 展示

yyyy-MM-dd HH:mm:ssZ

2019-04-20 13:15:22+0000

星期三, d 月 yyyy HH:mm:ss Z

2019年4月20日 星期六 13:15:22 +0000

dd.MM.yy HH:mm:ss.SSS

2020年4月19日 13:15:22.285

请参考 Java 日期/时间格式文档 以获取更多关于日期和时间格式语法的信息。

请求体

edit
messages
(必需,字符串数组) 您要分析的消息列表。

示例

edit
分析 Elasticsearch 日志文件
edit

假设你有一组Elasticsearch日志消息。 你可以将其发送到find_message_structure端点,如下所示:

POST _text_structure/find_message_structure
{
  "messages": [
    "[2024-03-05T10:52:36,256][INFO ][o.a.l.u.VectorUtilPanamaProvider] [laptop] Java vector incubator API enabled; uses preferredBitSize=128",
    "[2024-03-05T10:52:41,038][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-url]",
    "[2024-03-05T10:52:41,042][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [rest-root]",
    "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-core]",
    "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-redact]",
    "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [ingest-user-agent]",
    "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-monitoring]",
    "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-s3]",
    "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-analytics]",
    "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-ent-search]",
    "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-autoscaling]",
    "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [lang-painless]]",
    "[2024-03-05T10:52:41,059][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [lang-expression]",
    "[2024-03-05T10:52:41,059][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-eql]",
    "[2024-03-05T10:52:43,291][INFO ][o.e.e.NodeEnvironment    ] [laptop] heap size [16gb], compressed ordinary object pointers [true]",
    "[2024-03-05T10:52:46,098][INFO ][o.e.x.s.Security         ] [laptop] Security is enabled",
    "[2024-03-05T10:52:47,227][INFO ][o.e.x.p.ProfilingPlugin  ] [laptop] Profiling is enabled",
    "[2024-03-05T10:52:47,259][INFO ][o.e.x.p.ProfilingPlugin  ] [laptop] profiling index templates will not be installed or reinstalled",
    "[2024-03-05T10:52:47,755][INFO ][o.e.i.r.RecoverySettings ] [laptop] using rate limit [40mb] with [default=40mb, read=0b, write=0b, max=0b]",
    "[2024-03-05T10:52:47,787][INFO ][o.e.d.DiscoveryModule    ] [laptop] using discovery type [multi-node] and seed hosts providers [settings]",
    "[2024-03-05T10:52:49,188][INFO ][o.e.n.Node               ] [laptop] initialized",
    "[2024-03-05T10:52:49,199][INFO ][o.e.n.Node               ] [laptop] starting ..."
  ]
}

如果请求没有遇到错误,您将收到以下结果:

{
  "num_lines_analyzed" : 22,
  "num_messages_analyzed" : 22,
  "sample_start" : "[2024-03-05T10:52:36,256][INFO ][o.a.l.u.VectorUtilPanamaProvider] [laptop] Java vector incubator API enabled; uses preferredBitSize=128\n[2024-03-05T10:52:41,038][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-url]\n", 
  "charset" : "UTF-8",
  "format" : "semi_structured_text",
  "multiline_start_pattern" : "^\\[\\b\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}",
  "grok_pattern" : "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel} \\]\\[.*",
  "ecs_compatibility" : "disabled",
  "timestamp_field" : "timestamp",
  "joda_timestamp_formats" : [
    "ISO8601"
  ],
  "java_timestamp_formats" : [
    "ISO8601"
  ],
  "need_client_timezone" : true,
  "mappings" : {
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "loglevel" : {
        "type" : "keyword"
      },
      "message" : {
        "type" : "text"
      }
    }
  },
  "ingest_pipeline" : {
    "description" : "Ingest pipeline created by text structure finder",
    "processors" : [
      {
        "grok" : {
          "field" : "message",
          "patterns" : [
            "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel} \\]\\[.*"
          ],
          "ecs_compatibility" : "disabled"
        }
      },
      {
        "date" : {
          "field" : "timestamp",
          "timezone" : "{{ event.timezone }}",
          "formats" : [
            "ISO8601"
          ]
        }
      },
      {
        "remove" : {
          "field" : "timestamp"
        }
      }
    ]
  },
  "field_stats" : {
    "loglevel" : {
      "count" : 22,
      "cardinality" : 1,
      "top_hits" : [
        {
          "value" : "INFO",
          "count" : 22
        }
      ]
    },
    "message" : {
      "count" : 22,
      "cardinality" : 22,
      "top_hits" : [
        {
          "value" : "[2024-03-05T10:52:36,256][INFO ][o.a.l.u.VectorUtilPanamaProvider] [laptop] Java vector incubator API enabled; uses preferredBitSize=128",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,038][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-url]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,042][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [rest-root]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [ingest-user-agent]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-core]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,043][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-redact]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [lang-painless]]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [repository-s3]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-analytics]",
          "count" : 1
        },
        {
          "value" : "[2024-03-05T10:52:41,044][INFO ][o.e.p.PluginsService     ] [laptop] loaded module [x-pack-autoscaling]",
          "count" : 1
        }
      ]
    },
    "timestamp" : {
      "count" : 22,
      "cardinality" : 14,
      "earliest" : "2024-03-05T10:52:36,256",
      "latest" : "2024-03-05T10:52:49,199",
      "top_hits" : [
        {
          "value" : "2024-03-05T10:52:41,044",
          "count" : 6
        },
        {
          "value" : "2024-03-05T10:52:41,043",
          "count" : 3
        },
        {
          "value" : "2024-03-05T10:52:41,059",
          "count" : 2
        },
        {
          "value" : "2024-03-05T10:52:36,256",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:41,038",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:41,042",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:43,291",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:46,098",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:47,227",
          "count" : 1
        },
        {
          "value" : "2024-03-05T10:52:47,259",
          "count" : 1
        }
      ]
    }
  }
}

有关响应格式的详细描述,或关于摄取定界文本(如CSV)或换行符分隔的JSON的更多示例,请参阅查找文本结构端点的示例

查找文本结构 API

edit

查找文本的结构。文本必须包含适合被摄取到Elastic Stack中的数据。

请求

edit

POST _text_structure/find_structure

先决条件

edit
  • 如果启用了Elasticsearch安全功能,您必须拥有monitor_text_structuremonitor集群权限才能使用此API。请参阅 安全权限

描述

edit

此API提供了一个将数据导入Elasticsearch的起点,其格式适合后续与其他Elastic Stack功能一起使用。

与其他 Elasticsearch 端点不同,发布到此端点的数据不需要是 UTF-8 编码并以 JSON 格式。然而,它必须是文本;目前不支持二进制文本格式。

API的响应包含:

  • 文本开头的一些消息。
  • 揭示文本中检测到的所有字段的最常见值的统计数据,以及数值字段的基本数值统计数据。
  • 关于文本结构的详细信息,这在您编写摄取配置以索引它或类似格式的文本时非常有用。
  • 适用于Elasticsearch索引的适当映射,您可以使用它来摄取文本。

所有这些信息都可以在没有指导的情况下由结构查找器计算出来。 然而,您可以选择通过指定一个或多个查询参数来覆盖关于文本结构的一些决定。

输出细节可以在示例中查看。

如果结构查找器对某些文本产生意外结果,请指定explain查询参数。它会在响应中生成一个explanation,这将有助于确定为何选择了返回的结构。

查询参数

edit
charset
(可选,字符串) 文本的字符集。它必须是 Elasticsearch 使用的 JVM 支持的字符集。例如,UTF-8UTF-16LEwindows-1252EUC-JP。如果未指定此参数,结构查找器将选择适当的字符集。
column_names
(可选, 字符串) 如果你已将 format 设置为 delimited,你可以指定以逗号分隔的列名列表。如果未指定此参数,结构查找器将使用文本的标题行中的列名。如果文本没有标题行,列将被命名为 "column1", "column2", "column3" 等。
delimiter
(可选,字符串) 如果你已将 format 设置为 delimited,你可以指定用于分隔每行中值的字符。仅支持单个字符;分隔符不能包含多个字符。默认情况下,API 会考虑以下可能性:逗号、制表符、分号和竖线 (|)。在这种默认情况下,所有行必须具有相同数量的字段,才能检测到分隔格式。如果你指定了一个分隔符,最多可以有 10% 的行与第一行的列数不同。
explain
(可选,布尔值) 如果为true,响应中将包含一个名为explanation的字段,该字段是一个字符串数组,指示结构查找器如何生成其结果。默认值为false
format
(可选,字符串) 文本的高级结构。有效值为 ndjsonxmldelimitedsemi_structured_text。默认情况下,API 会选择格式。在这种默认情况下,所有行必须具有相同数量的字段,才能检测到分隔格式。如果将 format 设置为 delimited 并且未设置 delimiter,然而,API 允许最多 5% 的行与第一行的列数不同。
grok_pattern
(可选,字符串) 如果你已将 format 设置为 semi_structured_text,你可以 指定一个 Grok 模式,用于从文本中的每条消息中提取字段。Grok 模式中的时间戳字段的名称必须与 timestamp_field 参数中指定的名称匹配。如果未指定该参数,Grok 模式中的时间戳字段的名称必须匹配 "timestamp"。如果未指定 grok_pattern,结构查找器将创建一个 Grok 模式。
ecs_compatibility
(可选,字符串) 与符合 ECS 的 Grok 模式的兼容性模式。 使用此参数指定在结构查找器创建 Grok 模式时是否使用 ECS Grok 模式而不是传统模式。有效值为 disabledv1。默认值为 disabled。此设置主要在输入匹配整个消息 Grok 模式(如 %{CATALINALOG})时产生影响。如果结构查找器识别出常见结构但不知道其含义,则在 grok_pattern 输出中使用通用字段名称,如 pathipaddressfield1field2,目的是让了解含义的用户在使用前重命名这些字段。
has_header_row
(可选,布尔值) 如果你已将 format 设置为 delimited,你可以使用此参数来指示列名是否在文本的第一行。 如果未指定此参数,结构查找器将根据文本的第一行与其他行的相似性进行猜测。
line_merge_size_limit
(可选,无符号整数) 在分析半结构化文本时,合并行以形成消息时消息中的最大字符数。默认值为 10000。如果您有非常长的消息,可能需要增加此值,但请注意,如果错误地检测到将行分组为消息的方式,可能会导致非常长的处理时间。
lines_to_sample

(可选,无符号整数) 从文本开头开始包含在结构分析中的行数。最小值为 2;默认值为 1000。如果此参数的值大于文本中的行数,只要文本中至少有两行,分析将继续进行所有行。

行数和行的变化会影响分析的速度。例如,如果您上传的文本前1000行都是同一消息的变体,分析将发现更多的共性,而不是在大样本中看到的。然而,如果可能的话,上传前1000行有更多变化的样本文本比请求分析100000行以实现一些变化更为高效。

quote
(可选,字符串) 如果你已将 format 设置为 delimited,你可以指定用于引用每行中值的字符,如果它们包含换行符或分隔符字符。仅支持单个字符。如果未指定此参数,默认值是双引号 (")。如果你的分隔文本格式不使用引用,一种解决方法是将此参数设置为一个在样本中不出现的字符。
should_trim_fields
(可选, 布尔值) 如果你已将 format 设置为 delimited,你可以指定 分隔符之间的值是否应去除空白。如果 未指定此参数且分隔符为管道 (|),默认 值为 true。否则,默认值为 false
timeout
(可选,时间单位) 设置结构分析可能花费的最大时间。如果分析在超时到期时仍在运行,则它将被停止。默认值为25秒。
timestamp_field

(可选,字符串) 包含文本中每个记录的主时间戳的字段名称。特别是,如果将文本导入索引, 这将是要用于填充 @timestamp 字段的字段。

如果formatsemi_structured_text,此字段必须与grok_pattern中的适当提取名称匹配。因此,对于半结构化文本,最好不要指定此参数,除非也指定了grok_pattern

对于结构化文本,如果您指定此参数,该字段必须存在于文本中。

如果未指定此参数,结构查找器将决定哪个字段(如果有)是主时间戳字段。对于结构化文本,文本中不一定需要有时间戳。

timestamp_format

(可选, 字符串) 文本中时间戳字段的Java时间格式。

仅支持部分Java时间格式字母组:

  • a
  • d
  • dd
  • EEE
  • EEEE
  • H
  • HH
  • h
  • M
  • MM
  • MMM
  • MMMM
  • mm
  • ss
  • XX
  • XXX
  • yy
  • yyyy
  • zzz

此外,支持长度为一到九的 S 字母组(小数秒),前提是它们出现在 ss 之后,并且与 ss 之间用 .,: 分隔。除了 ?、换行符和回车符外,还允许使用空格和标点符号,以及用单引号括起来的文字文本。例如,MM/dd HH.mm.ss,SSSSSS 'in' yyyy 是一个有效的覆盖格式。

这个参数的一个有价值的用例是当格式是半结构化文本时,文本中有多个时间戳格式,并且你知道哪个格式对应于主要时间戳,但你不想指定完整的grok_pattern。另一个用例是当时间戳格式是结构查找器默认不考虑的格式时。

如果未指定此参数,结构查找器将从内置集合中选择最佳格式。

如果指定了特殊值 null,结构查找器将不会在文本中查找主时间戳。当格式为半结构化文本时,这将导致结构查找器将文本视为单行消息。

下表提供了一些示例时间戳的适当timeformat值:

时间格式 展示

yyyy-MM-dd HH:mm:ssZ

2019-04-20 13:15:22+0000

星期三, d 月 yyyy HH:mm:ss Z

2019年4月20日 星期六 13:15:22 +0000

dd.MM.yy HH:mm:ss.SSS

2020年4月19日 13:15:22.285

请参考 Java 日期/时间格式文档 以获取更多关于日期和时间格式语法的信息。

请求体

edit

您想要分析的文本。它必须包含适合被摄取到 Elasticsearch 中的数据。它不需要是 JSON 格式,也不需要是 UTF-8 编码。大小限制为 Elasticsearch HTTP 接收缓冲区大小,默认值为 100 Mb。

示例

edit
摄取换行符分隔的JSON
edit

假设你有一个包含一些书籍信息的换行符分隔的JSON文本。你可以将内容发送到find_structure端点:

POST _text_structure/find_structure
{"name": "Leviathan Wakes", "author": "James S.A. Corey", "release_date": "2011-06-02", "page_count": 561}
{"name": "Hyperion", "author": "Dan Simmons", "release_date": "1989-05-26", "page_count": 482}
{"name": "Dune", "author": "Frank Herbert", "release_date": "1965-06-01", "page_count": 604}
{"name": "Dune Messiah", "author": "Frank Herbert", "release_date": "1969-10-15", "page_count": 331}
{"name": "Children of Dune", "author": "Frank Herbert", "release_date": "1976-04-21", "page_count": 408}
{"name": "God Emperor of Dune", "author": "Frank Herbert", "release_date": "1981-05-28", "page_count": 454}
{"name": "Consider Phlebas", "author": "Iain M. Banks", "release_date": "1987-04-23", "page_count": 471}
{"name": "Pandora's Star", "author": "Peter F. Hamilton", "release_date": "2004-03-02", "page_count": 768}
{"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585}
{"name": "A Fire Upon the Deep", "author": "Vernor Vinge", "release_date": "1992-06-01", "page_count": 613}
{"name": "Ender's Game", "author": "Orson Scott Card", "release_date": "1985-06-01", "page_count": 324}
{"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328}
{"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227}
{"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268}
{"name": "Foundation", "author": "Isaac Asimov", "release_date": "1951-06-01", "page_count": 224}
{"name": "The Giver", "author": "Lois Lowry", "release_date": "1993-04-26", "page_count": 208}
{"name": "Slaughterhouse-Five", "author": "Kurt Vonnegut", "release_date": "1969-06-01", "page_count": 275}
{"name": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "release_date": "1979-10-12", "page_count": 180}
{"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470}
{"name": "Neuromancer", "author": "William Gibson", "release_date": "1984-07-01", "page_count": 271}
{"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311}
{"name": "Starship Troopers", "author": "Robert A. Heinlein", "release_date": "1959-12-01", "page_count": 335}
{"name": "The Left Hand of Darkness", "author": "Ursula K. Le Guin", "release_date": "1969-06-01", "page_count": 304}
{"name": "The Moon is a Harsh Mistress", "author": "Robert A. Heinlein", "release_date": "1966-04-01", "page_count": 288}

如果请求没有遇到错误,您将收到以下结果:

{
  "num_lines_analyzed" : 24, 
  "num_messages_analyzed" : 24, 
  "sample_start" : "{\"name\": \"Leviathan Wakes\", \"author\": \"James S.A. Corey\", \"release_date\": \"2011-06-02\", \"page_count\": 561}\n{\"name\": \"Hyperion\", \"author\": \"Dan Simmons\", \"release_date\": \"1989-05-26\", \"page_count\": 482}\n", 
  "charset" : "UTF-8", 
  "has_byte_order_marker" : false, 
  "format" : "ndjson", 
  "ecs_compatibility" : "disabled", 
  "timestamp_field" : "release_date", 
  "joda_timestamp_formats" : [ 
    "ISO8601"
  ],
  "java_timestamp_formats" : [ 
    "ISO8601"
  ],
  "need_client_timezone" : true, 
  "mappings" : { 
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "author" : {
        "type" : "keyword"
      },
      "name" : {
        "type" : "keyword"
      },
      "page_count" : {
        "type" : "long"
      },
      "release_date" : {
        "type" : "date",
        "format" : "iso8601"
      }
    }
  },
  "ingest_pipeline" : {
    "description" : "Ingest pipeline created by text structure finder",
    "processors" : [
      {
        "date" : {
          "field" : "release_date",
          "timezone" : "{{ event.timezone }}",
          "formats" : [
            "ISO8601"
          ]
        }
      }
    ]
  },
  "field_stats" : { 
    "author" : {
      "count" : 24,
      "cardinality" : 20,
      "top_hits" : [
        {
          "value" : "Frank Herbert",
          "count" : 4
        },
        {
          "value" : "Robert A. Heinlein",
          "count" : 2
        },
        {
          "value" : "Alastair Reynolds",
          "count" : 1
        },
        {
          "value" : "Aldous Huxley",
          "count" : 1
        },
        {
          "value" : "Dan Simmons",
          "count" : 1
        },
        {
          "value" : "Douglas Adams",
          "count" : 1
        },
        {
          "value" : "George Orwell",
          "count" : 1
        },
        {
          "value" : "Iain M. Banks",
          "count" : 1
        },
        {
          "value" : "Isaac Asimov",
          "count" : 1
        },
        {
          "value" : "James S.A. Corey",
          "count" : 1
        }
      ]
    },
    "name" : {
      "count" : 24,
      "cardinality" : 24,
      "top_hits" : [
        {
          "value" : "1984",
          "count" : 1
        },
        {
          "value" : "A Fire Upon the Deep",
          "count" : 1
        },
        {
          "value" : "Brave New World",
          "count" : 1
        },
        {
          "value" : "Children of Dune",
          "count" : 1
        },
        {
          "value" : "Consider Phlebas",
          "count" : 1
        },
        {
          "value" : "Dune",
          "count" : 1
        },
        {
          "value" : "Dune Messiah",
          "count" : 1
        },
        {
          "value" : "Ender's Game",
          "count" : 1
        },
        {
          "value" : "Fahrenheit 451",
          "count" : 1
        },
        {
          "value" : "Foundation",
          "count" : 1
        }
      ]
    },
    "page_count" : {
      "count" : 24,
      "cardinality" : 24,
      "min_value" : 180,
      "max_value" : 768,
      "mean_value" : 387.0833333333333,
      "median_value" : 329.5,
      "top_hits" : [
        {
          "value" : 180,
          "count" : 1
        },
        {
          "value" : 208,
          "count" : 1
        },
        {
          "value" : 224,
          "count" : 1
        },
        {
          "value" : 227,
          "count" : 1
        },
        {
          "value" : 268,
          "count" : 1
        },
        {
          "value" : 271,
          "count" : 1
        },
        {
          "value" : 275,
          "count" : 1
        },
        {
          "value" : 288,
          "count" : 1
        },
        {
          "value" : 304,
          "count" : 1
        },
        {
          "value" : 311,
          "count" : 1
        }
      ]
    },
    "release_date" : {
      "count" : 24,
      "cardinality" : 20,
      "earliest" : "1932-06-01",
      "latest" : "2011-06-02",
      "top_hits" : [
        {
          "value" : "1985-06-01",
          "count" : 3
        },
        {
          "value" : "1969-06-01",
          "count" : 2
        },
        {
          "value" : "1992-06-01",
          "count" : 2
        },
        {
          "value" : "1932-06-01",
          "count" : 1
        },
        {
          "value" : "1951-06-01",
          "count" : 1
        },
        {
          "value" : "1953-10-15",
          "count" : 1
        },
        {
          "value" : "1959-12-01",
          "count" : 1
        },
        {
          "value" : "1965-06-01",
          "count" : 1
        },
        {
          "value" : "1966-04-01",
          "count" : 1
        },
        {
          "value" : "1969-10-15",
          "count" : 1
        }
      ]
    }
  }
}

num_lines_analyzed 表示分析了多少行文本。

num_messages_analyzed 表示行中包含了多少个不同的消息。对于NDJSON,此值与num_lines_analyzed相同。对于其他文本格式,消息可以跨越几行。

sample_start 逐字重现文本中的前两条消息。这可能有助于诊断解析错误或意外上传了错误的文本。

charset 表示用于解析文本的字符编码。

对于UTF字符编码,has_byte_order_marker 指示文本是否以字节顺序标记开头。

formatndjsonxmldelimitedsemi_structured_text 之一。

ecs_compatibility 可以是 disabledv1,默认为 disabled

The timestamp_field 命名了被认为最可能是每个文档主时间戳的字段。

joda_timestamp_formats 用于告诉 Logstash 如何解析时间戳。

java_timestamp_formats 是时间字段中识别的 Java 时间格式。Elasticsearch 映射和摄取管道使用此格式。

如果检测到的时间戳格式不包含时区,need_client_timezone 将为 true。因此,解析文本的服务器必须由客户端告知正确的时区。

mappings 包含了一些适合将数据导入索引的映射。在这种情况下,release_date 字段被赋予了 keyword 类型,因为它被认为不够具体,无法转换为 date 类型。

field_stats 包含每个字段的最常见值,以及数字字段 page_count 的基本数值统计信息。这些信息可能提供线索,表明在使用其他 Elastic Stack 功能之前,数据需要进行清理或转换。

查找纽约市黄色出租车示例数据的结构
edit

下一个示例展示了如何找到一些纽约市黄色出租车行程数据的结构。第一个 curl 命令下载数据,前 20000 行随后通过管道传输到 find_structure 端点。端点的 lines_to_sample 查询参数设置为 20000,以匹配 head 命令中指定的内容。

curl -s "s3.amazonaws.com/nyc-tlc/trip+data/yellow_tripdata_2018-06.csv" | head -20000 | curl -s -H "Content-Type: application/json" -XPOST "localhost:9200/_text_structure/find_structure?pretty&lines_to_sample=20000" -T -

即使在这种情况下数据不是JSON,也必须设置Content-Type: application/json头。(或者可以将Content-Type设置为Elasticsearch支持的任何其他类型,但它必须设置。)

如果请求没有遇到错误,您将收到以下结果:

{
  "num_lines_analyzed" : 20000,
  "num_messages_analyzed" : 19998, 
  "sample_start" : "VendorID,tpep_pickup_datetime,tpep_dropoff_datetime,passenger_count,trip_distance,RatecodeID,store_and_fwd_flag,PULocationID,DOLocationID,payment_type,fare_amount,extra,mta_tax,tip_amount,tolls_amount,improvement_surcharge,total_amount\n\n1,2018-06-01 00:15:40,2018-06-01 00:16:46,1,.00,1,N,145,145,2,3,0.5,0.5,0,0,0.3,4.3\n",
  "charset" : "UTF-8",
  "has_byte_order_marker" : false,
  "format" : "delimited", 
  "multiline_start_pattern" : "^.*?,\"?\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}",
  "exclude_lines_pattern" : "^\"?VendorID\"?,\"?tpep_pickup_datetime\"?,\"?tpep_dropoff_datetime\"?,\"?passenger_count\"?,\"?trip_distance\"?,\"?RatecodeID\"?,\"?store_and_fwd_flag\"?,\"?PULocationID\"?,\"?DOLocationID\"?,\"?payment_type\"?,\"?fare_amount\"?,\"?extra\"?,\"?mta_tax\"?,\"?tip_amount\"?,\"?tolls_amount\"?,\"?improvement_surcharge\"?,\"?total_amount\"?",
  "column_names" : [ 
    "VendorID",
    "tpep_pickup_datetime",
    "tpep_dropoff_datetime",
    "passenger_count",
    "trip_distance",
    "RatecodeID",
    "store_and_fwd_flag",
    "PULocationID",
    "DOLocationID",
    "payment_type",
    "fare_amount",
    "extra",
    "mta_tax",
    "tip_amount",
    "tolls_amount",
    "improvement_surcharge",
    "total_amount"
  ],
  "has_header_row" : true, 
  "delimiter" : ",", 
  "quote" : "\"", 
  "timestamp_field" : "tpep_pickup_datetime", 
  "joda_timestamp_formats" : [ 
    "YYYY-MM-dd HH:mm:ss"
  ],
  "java_timestamp_formats" : [ 
    "yyyy-MM-dd HH:mm:ss"
  ],
  "need_client_timezone" : true, 
  "mappings" : {
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "DOLocationID" : {
        "type" : "long"
      },
      "PULocationID" : {
        "type" : "long"
      },
      "RatecodeID" : {
        "type" : "long"
      },
      "VendorID" : {
        "type" : "long"
      },
      "extra" : {
        "type" : "double"
      },
      "fare_amount" : {
        "type" : "double"
      },
      "improvement_surcharge" : {
        "type" : "double"
      },
      "mta_tax" : {
        "type" : "double"
      },
      "passenger_count" : {
        "type" : "long"
      },
      "payment_type" : {
        "type" : "long"
      },
      "store_and_fwd_flag" : {
        "type" : "keyword"
      },
      "tip_amount" : {
        "type" : "double"
      },
      "tolls_amount" : {
        "type" : "double"
      },
      "total_amount" : {
        "type" : "double"
      },
      "tpep_dropoff_datetime" : {
        "type" : "date",
        "format" : "yyyy-MM-dd HH:mm:ss"
      },
      "tpep_pickup_datetime" : {
        "type" : "date",
        "format" : "yyyy-MM-dd HH:mm:ss"
      },
      "trip_distance" : {
        "type" : "double"
      }
    }
  },
  "ingest_pipeline" : {
    "description" : "Ingest pipeline created by text structure finder",
    "processors" : [
      {
        "csv" : {
          "field" : "message",
          "target_fields" : [
            "VendorID",
            "tpep_pickup_datetime",
            "tpep_dropoff_datetime",
            "passenger_count",
            "trip_distance",
            "RatecodeID",
            "store_and_fwd_flag",
            "PULocationID",
            "DOLocationID",
            "payment_type",
            "fare_amount",
            "extra",
            "mta_tax",
            "tip_amount",
            "tolls_amount",
            "improvement_surcharge",
            "total_amount"
          ]
        }
      },
      {
        "date" : {
          "field" : "tpep_pickup_datetime",
          "timezone" : "{{ event.timezone }}",
          "formats" : [
            "yyyy-MM-dd HH:mm:ss"
          ]
        }
      },
      {
        "convert" : {
          "field" : "DOLocationID",
          "type" : "long"
        }
      },
      {
        "convert" : {
          "field" : "PULocationID",
          "type" : "long"
        }
      },
      {
        "convert" : {
          "field" : "RatecodeID",
          "type" : "long"
        }
      },
      {
        "convert" : {
          "field" : "VendorID",
          "type" : "long"
        }
      },
      {
        "convert" : {
          "field" : "extra",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "fare_amount",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "improvement_surcharge",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "mta_tax",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "passenger_count",
          "type" : "long"
        }
      },
      {
        "convert" : {
          "field" : "payment_type",
          "type" : "long"
        }
      },
      {
        "convert" : {
          "field" : "tip_amount",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "tolls_amount",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "total_amount",
          "type" : "double"
        }
      },
      {
        "convert" : {
          "field" : "trip_distance",
          "type" : "double"
        }
      },
      {
        "remove" : {
          "field" : "message"
        }
      }
    ]
  },
  "field_stats" : {
    "DOLocationID" : {
      "count" : 19998,
      "cardinality" : 240,
      "min_value" : 1,
      "max_value" : 265,
      "mean_value" : 150.26532653265312,
      "median_value" : 148,
      "top_hits" : [
        {
          "value" : 79,
          "count" : 760
        },
        {
          "value" : 48,
          "count" : 683
        },
        {
          "value" : 68,
          "count" : 529
        },
        {
          "value" : 170,
          "count" : 506
        },
        {
          "value" : 107,
          "count" : 468
        },
        {
          "value" : 249,
          "count" : 457
        },
        {
          "value" : 230,
          "count" : 441
        },
        {
          "value" : 186,
          "count" : 432
        },
        {
          "value" : 141,
          "count" : 409
        },
        {
          "value" : 263,
          "count" : 386
        }
      ]
    },
    "PULocationID" : {
      "count" : 19998,
      "cardinality" : 154,
      "min_value" : 1,
      "max_value" : 265,
      "mean_value" : 153.4042404240424,
      "median_value" : 148,
      "top_hits" : [
        {
          "value" : 79,
          "count" : 1067
        },
        {
          "value" : 230,
          "count" : 949
        },
        {
          "value" : 148,
          "count" : 940
        },
        {
          "value" : 132,
          "count" : 897
        },
        {
          "value" : 48,
          "count" : 853
        },
        {
          "value" : 161,
          "count" : 820
        },
        {
          "value" : 234,
          "count" : 750
        },
        {
          "value" : 249,
          "count" : 722
        },
        {
          "value" : 164,
          "count" : 663
        },
        {
          "value" : 114,
          "count" : 646
        }
      ]
    },
    "RatecodeID" : {
      "count" : 19998,
      "cardinality" : 5,
      "min_value" : 1,
      "max_value" : 5,
      "mean_value" : 1.0656565656565653,
      "median_value" : 1,
      "top_hits" : [
        {
          "value" : 1,
          "count" : 19311
        },
        {
          "value" : 2,
          "count" : 468
        },
        {
          "value" : 5,
          "count" : 195
        },
        {
          "value" : 4,
          "count" : 17
        },
        {
          "value" : 3,
          "count" : 7
        }
      ]
    },
    "VendorID" : {
      "count" : 19998,
      "cardinality" : 2,
      "min_value" : 1,
      "max_value" : 2,
      "mean_value" : 1.59005900590059,
      "median_value" : 2,
      "top_hits" : [
        {
          "value" : 2,
          "count" : 11800
        },
        {
          "value" : 1,
          "count" : 8198
        }
      ]
    },
    "extra" : {
      "count" : 19998,
      "cardinality" : 3,
      "min_value" : -0.5,
      "max_value" : 0.5,
      "mean_value" : 0.4815981598159816,
      "median_value" : 0.5,
      "top_hits" : [
        {
          "value" : 0.5,
          "count" : 19281
        },
        {
          "value" : 0,
          "count" : 698
        },
        {
          "value" : -0.5,
          "count" : 19
        }
      ]
    },
    "fare_amount" : {
      "count" : 19998,
      "cardinality" : 208,
      "min_value" : -100,
      "max_value" : 300,
      "mean_value" : 13.937719771977209,
      "median_value" : 9.5,
      "top_hits" : [
        {
          "value" : 6,
          "count" : 1004
        },
        {
          "value" : 6.5,
          "count" : 935
        },
        {
          "value" : 5.5,
          "count" : 909
        },
        {
          "value" : 7,
          "count" : 903
        },
        {
          "value" : 5,
          "count" : 889
        },
        {
          "value" : 7.5,
          "count" : 854
        },
        {
          "value" : 4.5,
          "count" : 802
        },
        {
          "value" : 8.5,
          "count" : 790
        },
        {
          "value" : 8,
          "count" : 789
        },
        {
          "value" : 9,
          "count" : 711
        }
      ]
    },
    "improvement_surcharge" : {
      "count" : 19998,
      "cardinality" : 3,
      "min_value" : -0.3,
      "max_value" : 0.3,
      "mean_value" : 0.29915991599159913,
      "median_value" : 0.3,
      "top_hits" : [
        {
          "value" : 0.3,
          "count" : 19964
        },
        {
          "value" : -0.3,
          "count" : 22
        },
        {
          "value" : 0,
          "count" : 12
        }
      ]
    },
    "mta_tax" : {
      "count" : 19998,
      "cardinality" : 3,
      "min_value" : -0.5,
      "max_value" : 0.5,
      "mean_value" : 0.4962246224622462,
      "median_value" : 0.5,
      "top_hits" : [
        {
          "value" : 0.5,
          "count" : 19868
        },
        {
          "value" : 0,
          "count" : 109
        },
        {
          "value" : -0.5,
          "count" : 21
        }
      ]
    },
    "passenger_count" : {
      "count" : 19998,
      "cardinality" : 7,
      "min_value" : 0,
      "max_value" : 6,
      "mean_value" : 1.6201620162016201,
      "median_value" : 1,
      "top_hits" : [
        {
          "value" : 1,
          "count" : 14219
        },
        {
          "value" : 2,
          "count" : 2886
        },
        {
          "value" : 5,
          "count" : 1047
        },
        {
          "value" : 3,
          "count" : 804
        },
        {
          "value" : 6,
          "count" : 523
        },
        {
          "value" : 4,
          "count" : 406
        },
        {
          "value" : 0,
          "count" : 113
        }
      ]
    },
    "payment_type" : {
      "count" : 19998,
      "cardinality" : 4,
      "min_value" : 1,
      "max_value" : 4,
      "mean_value" : 1.315631563156316,
      "median_value" : 1,
      "top_hits" : [
        {
          "value" : 1,
          "count" : 13936
        },
        {
          "value" : 2,
          "count" : 5857
        },
        {
          "value" : 3,
          "count" : 160
        },
        {
          "value" : 4,
          "count" : 45
        }
      ]
    },
    "store_and_fwd_flag" : {
      "count" : 19998,
      "cardinality" : 2,
      "top_hits" : [
        {
          "value" : "N",
          "count" : 19910
        },
        {
          "value" : "Y",
          "count" : 88
        }
      ]
    },
    "tip_amount" : {
      "count" : 19998,
      "cardinality" : 717,
      "min_value" : 0,
      "max_value" : 128,
      "mean_value" : 2.010959095909593,
      "median_value" : 1.45,
      "top_hits" : [
        {
          "value" : 0,
          "count" : 6917
        },
        {
          "value" : 1,
          "count" : 1178
        },
        {
          "value" : 2,
          "count" : 624
        },
        {
          "value" : 3,
          "count" : 248
        },
        {
          "value" : 1.56,
          "count" : 206
        },
        {
          "value" : 1.46,
          "count" : 205
        },
        {
          "value" : 1.76,
          "count" : 196
        },
        {
          "value" : 1.45,
          "count" : 195
        },
        {
          "value" : 1.36,
          "count" : 191
        },
        {
          "value" : 1.5,
          "count" : 187
        }
      ]
    },
    "tolls_amount" : {
      "count" : 19998,
      "cardinality" : 26,
      "min_value" : 0,
      "max_value" : 35,
      "mean_value" : 0.2729697969796978,
      "median_value" : 0,
      "top_hits" : [
        {
          "value" : 0,
          "count" : 19107
        },
        {
          "value" : 5.76,
          "count" : 791
        },
        {
          "value" : 10.5,
          "count" : 36
        },
        {
          "value" : 2.64,
          "count" : 21
        },
        {
          "value" : 11.52,
          "count" : 8
        },
        {
          "value" : 5.54,
          "count" : 4
        },
        {
          "value" : 8.5,
          "count" : 4
        },
        {
          "value" : 17.28,
          "count" : 4
        },
        {
          "value" : 2,
          "count" : 2
        },
        {
          "value" : 2.16,
          "count" : 2
        }
      ]
    },
    "total_amount" : {
      "count" : 19998,
      "cardinality" : 1267,
      "min_value" : -100.3,
      "max_value" : 389.12,
      "mean_value" : 17.499898989898995,
      "median_value" : 12.35,
      "top_hits" : [
        {
          "value" : 7.3,
          "count" : 478
        },
        {
          "value" : 8.3,
          "count" : 443
        },
        {
          "value" : 8.8,
          "count" : 420
        },
        {
          "value" : 6.8,
          "count" : 406
        },
        {
          "value" : 7.8,
          "count" : 405
        },
        {
          "value" : 6.3,
          "count" : 371
        },
        {
          "value" : 9.8,
          "count" : 368
        },
        {
          "value" : 5.8,
          "count" : 362
        },
        {
          "value" : 9.3,
          "count" : 332
        },
        {
          "value" : 10.3,
          "count" : 332
        }
      ]
    },
    "tpep_dropoff_datetime" : {
      "count" : 19998,
      "cardinality" : 9066,
      "earliest" : "2018-05-31 06:18:15",
      "latest" : "2018-06-02 02:25:44",
      "top_hits" : [
        {
          "value" : "2018-06-01 01:12:12",
          "count" : 10
        },
        {
          "value" : "2018-06-01 00:32:15",
          "count" : 9
        },
        {
          "value" : "2018-06-01 00:44:27",
          "count" : 9
        },
        {
          "value" : "2018-06-01 00:46:42",
          "count" : 9
        },
        {
          "value" : "2018-06-01 01:03:22",
          "count" : 9
        },
        {
          "value" : "2018-06-01 01:05:13",
          "count" : 9
        },
        {
          "value" : "2018-06-01 00:11:20",
          "count" : 8
        },
        {
          "value" : "2018-06-01 00:16:03",
          "count" : 8
        },
        {
          "value" : "2018-06-01 00:19:47",
          "count" : 8
        },
        {
          "value" : "2018-06-01 00:25:17",
          "count" : 8
        }
      ]
    },
    "tpep_pickup_datetime" : {
      "count" : 19998,
      "cardinality" : 8760,
      "earliest" : "2018-05-31 06:08:31",
      "latest" : "2018-06-02 01:21:21",
      "top_hits" : [
        {
          "value" : "2018-06-01 00:01:23",
          "count" : 12
        },
        {
          "value" : "2018-06-01 00:04:31",
          "count" : 10
        },
        {
          "value" : "2018-06-01 00:05:38",
          "count" : 10
        },
        {
          "value" : "2018-06-01 00:09:50",
          "count" : 10
        },
        {
          "value" : "2018-06-01 00:12:01",
          "count" : 10
        },
        {
          "value" : "2018-06-01 00:14:17",
          "count" : 10
        },
        {
          "value" : "2018-06-01 00:00:34",
          "count" : 9
        },
        {
          "value" : "2018-06-01 00:00:40",
          "count" : 9
        },
        {
          "value" : "2018-06-01 00:02:53",
          "count" : 9
        },
        {
          "value" : "2018-06-01 00:05:40",
          "count" : 9
        }
      ]
    },
    "trip_distance" : {
      "count" : 19998,
      "cardinality" : 1687,
      "min_value" : 0,
      "max_value" : 64.63,
      "mean_value" : 3.6521062106210715,
      "median_value" : 2.16,
      "top_hits" : [
        {
          "value" : 0.9,
          "count" : 335
        },
        {
          "value" : 0.8,
          "count" : 320
        },
        {
          "value" : 1.1,
          "count" : 316
        },
        {
          "value" : 0.7,
          "count" : 304
        },
        {
          "value" : 1.2,
          "count" : 303
        },
        {
          "value" : 1,
          "count" : 296
        },
        {
          "value" : 1.3,
          "count" : 280
        },
        {
          "value" : 1.5,
          "count" : 268
        },
        {
          "value" : 1.6,
          "count" : 268
        },
        {
          "value" : 0.6,
          "count" : 256
        }
      ]
    }
  }
}

num_messages_analyzednum_lines_analyzed 少2,因为只有数据记录才算作消息。第一行包含列名,在这个样本中,第二行是空白的。

与第一个示例不同,在这种情况下,format 已被识别为 delimited

因为formatdelimited,输出中的column_names字段列出了样本中列名的顺序。

has_header_row 表示对于这个样本,列名在样本的第一行中。(如果它们不在第一行,那么在 column_names 查询参数中指定它们会是一个好主意。)

此示例的分隔符是逗号,因为它是CSV格式的文本。

字符是默认的双引号。(结构查找器不会尝试推断其他引号字符,因此如果您有使用其他字符引用的定界文本,则必须使用查询参数指定它。)

已选择 timestamp_fieldtpep_pickup_datetimetpep_dropoff_datetime 同样适用,但选择 tpep_pickup_datetime 是因为它在列顺序中排在前面。如果你更喜欢 tpep_dropoff_datetime,则可以使用 timestamp_field 查询参数强制选择它。

joda_timestamp_formats 用于告诉 Logstash 如何解析时间戳。

java_timestamp_formats 是时间字段中识别的 Java 时间格式。Elasticsearch 映射和摄取管道使用此格式。

此示例中的时间戳格式未指定时区,因此为了准确地将它们转换为UTC时间戳并存储在Elasticsearch中,需要提供它们所关联的时区。need_client_timezone 对于包含时区的时间戳格式将为 false

设置超时参数
edit

如果你尝试分析大量数据,那么分析将花费很长时间。如果你想限制你的Elasticsearch集群为一个请求执行的处理量,可以使用timeout查询参数。当超时到期时,分析将被中止并返回一个错误。例如,你可以将前一个例子中的20000行替换为200000行,并在分析上设置1秒的超时:

curl -s "s3.amazonaws.com/nyc-tlc/trip+data/yellow_tripdata_2018-06.csv" | head -200000 | curl -s -H "Content-Type: application/json" -XPOST "localhost:9200/_text_structure/find_structure?pretty&lines_to_sample=200000&timeout=1s" -T -

除非你使用的是一台非常快的计算机,否则你会收到一个超时错误:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "timeout_exception",
        "reason" : "Aborting structure analysis during [delimited record parsing] as it has taken longer than the timeout of [1s]"
      }
    ],
    "type" : "timeout_exception",
    "reason" : "Aborting structure analysis during [delimited record parsing] as it has taken longer than the timeout of [1s]"
  },
  "status" : 500
}

如果你自己尝试上面的例子,你会注意到curl命令的总运行时间远远超过1秒。这是因为从互联网下载200000行CSV需要一些时间,而超时是从这个端点开始处理数据的时间开始计算的。

分析Elasticsearch日志文件
edit

这是一个分析Elasticsearch日志文件的示例:

curl -s -H "Content-Type: application/json" -XPOST
"localhost:9200/_text_structure/find_structure?pretty&ecs_compatibility=disabled" -T "$ES_HOME/logs/elasticsearch.log"

如果请求没有遇到错误,结果将看起来像这样:

{
  "num_lines_analyzed" : 53,
  "num_messages_analyzed" : 53,
  "sample_start" : "[2018-09-27T14:39:28,518][INFO ][o.e.e.NodeEnvironment    ] [node-0] using [1] data paths, mounts [[/ (/dev/disk1)]], net usable_space [165.4gb], net total_space [464.7gb], types [hfs]\n[2018-09-27T14:39:28,521][INFO ][o.e.e.NodeEnvironment    ] [node-0] heap size [494.9mb], compressed ordinary object pointers [true]\n",
  "charset" : "UTF-8",
  "has_byte_order_marker" : false,
  "format" : "semi_structured_text", 
  "multiline_start_pattern" : "^\\[\\b\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}", 
  "grok_pattern" : "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel}.*", 
  "ecs_compatibility" : "disabled", 
  "timestamp_field" : "timestamp",
  "joda_timestamp_formats" : [
    "ISO8601"
  ],
  "java_timestamp_formats" : [
    "ISO8601"
  ],
  "need_client_timezone" : true,
  "mappings" : {
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "loglevel" : {
        "type" : "keyword"
      },
      "message" : {
        "type" : "text"
      }
    }
  },
  "ingest_pipeline" : {
    "description" : "Ingest pipeline created by text structure finder",
    "processors" : [
      {
        "grok" : {
          "field" : "message",
          "patterns" : [
            "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel}.*"
          ]
        }
      },
      {
        "date" : {
          "field" : "timestamp",
          "timezone" : "{{ event.timezone }}",
          "formats" : [
            "ISO8601"
          ]
        }
      },
      {
        "remove" : {
          "field" : "timestamp"
        }
      }
    ]
  },
  "field_stats" : {
    "loglevel" : {
      "count" : 53,
      "cardinality" : 3,
      "top_hits" : [
        {
          "value" : "INFO",
          "count" : 51
        },
        {
          "value" : "DEBUG",
          "count" : 1
        },
        {
          "value" : "WARN",
          "count" : 1
        }
      ]
    },
    "timestamp" : {
      "count" : 53,
      "cardinality" : 28,
      "earliest" : "2018-09-27T14:39:28,518",
      "latest" : "2018-09-27T14:39:37,012",
      "top_hits" : [
        {
          "value" : "2018-09-27T14:39:29,859",
          "count" : 10
        },
        {
          "value" : "2018-09-27T14:39:29,860",
          "count" : 9
        },
        {
          "value" : "2018-09-27T14:39:29,858",
          "count" : 6
        },
        {
          "value" : "2018-09-27T14:39:28,523",
          "count" : 3
        },
        {
          "value" : "2018-09-27T14:39:34,234",
          "count" : 2
        },
        {
          "value" : "2018-09-27T14:39:28,518",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:28,521",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:28,522",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:29,861",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:32,786",
          "count" : 1
        }
      ]
    }
  }
}

这次 format 被识别为 semi_structured_text

基于时间戳出现在每个多行日志消息的第一行,设置了multiline_start_pattern

已创建一个非常简单的 grok_pattern,它提取时间戳和每个分析消息中出现的可识别字段。在这种情况下,除了时间戳之外,唯一被识别的字段是日志级别。

使用的ECS Grok模式兼容性模式,可以是disabled(如果请求中未指定,则为默认值)或v1

指定 grok_pattern 作为查询参数
edit

如果你识别出的字段比结构查找器单独生成的简单 grok_pattern 更多,那么你可以重新提交请求,指定一个更高级的 grok_pattern 作为查询参数,结构查找器将为你额外的字段计算 field_stats

在Elasticsearch日志的情况下,一个更完整的Grok模式是 \[%{TIMESTAMP_ISO8601:timestamp}\]\[%{LOGLEVEL:loglevel} *\]\[%{JAVACLASS:class} *\] \[%{HOSTNAME:node}\] %{JAVALOGMESSAGE:message}。 你可以再次分析相同的文本,提交这个grok_pattern作为一个 查询参数(适当地进行URL转义):

curl -s -H "Content-Type: application/json" -XPOST "localhost:9200/_text_structure/find_structure?pretty&format=semi_structured_text&grok_pattern=%5C%5B%25%7BTIMESTAMP_ISO8601:timestamp%7D%5C%5D%5C%5B%25%7BLOGLEVEL:loglevel%7D%20*%5C%5D%5C%5B%25%7BJAVACLASS:class%7D%20*%5C%5D%20%5C%5B%25%7BHOSTNAME:node%7D%5C%5D%20%25%7BJAVALOGMESSAGE:message%7D" -T "$ES_HOME/logs/elasticsearch.log"

如果请求没有遇到错误,结果将看起来像这样:

{
  "num_lines_analyzed" : 53,
  "num_messages_analyzed" : 53,
  "sample_start" : "[2018-09-27T14:39:28,518][INFO ][o.e.e.NodeEnvironment    ] [node-0] using [1] data paths, mounts [[/ (/dev/disk1)]], net usable_space [165.4gb], net total_space [464.7gb], types [hfs]\n[2018-09-27T14:39:28,521][INFO ][o.e.e.NodeEnvironment    ] [node-0] heap size [494.9mb], compressed ordinary object pointers [true]\n",
  "charset" : "UTF-8",
  "has_byte_order_marker" : false,
  "format" : "semi_structured_text",
  "multiline_start_pattern" : "^\\[\\b\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}",
  "grok_pattern" : "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel} *\\]\\[%{JAVACLASS:class} *\\] \\[%{HOSTNAME:node}\\] %{JAVALOGMESSAGE:message}", 
  "ecs_compatibility" : "disabled", 
  "timestamp_field" : "timestamp",
  "joda_timestamp_formats" : [
    "ISO8601"
  ],
  "java_timestamp_formats" : [
    "ISO8601"
  ],
  "need_client_timezone" : true,
  "mappings" : {
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "class" : {
        "type" : "keyword"
      },
      "loglevel" : {
        "type" : "keyword"
      },
      "message" : {
        "type" : "text"
      },
      "node" : {
        "type" : "keyword"
      }
    }
  },
  "ingest_pipeline" : {
    "description" : "Ingest pipeline created by text structure finder",
    "processors" : [
      {
        "grok" : {
          "field" : "message",
          "patterns" : [
            "\\[%{TIMESTAMP_ISO8601:timestamp}\\]\\[%{LOGLEVEL:loglevel} *\\]\\[%{JAVACLASS:class} *\\] \\[%{HOSTNAME:node}\\] %{JAVALOGMESSAGE:message}"
          ]
        }
      },
      {
        "date" : {
          "field" : "timestamp",
          "timezone" : "{{ event.timezone }}",
          "formats" : [
            "ISO8601"
          ]
        }
      },
      {
        "remove" : {
          "field" : "timestamp"
        }
      }
    ]
  },
  "field_stats" : { 
    "class" : {
      "count" : 53,
      "cardinality" : 14,
      "top_hits" : [
        {
          "value" : "o.e.p.PluginsService",
          "count" : 26
        },
        {
          "value" : "o.e.c.m.MetadataIndexTemplateService",
          "count" : 8
        },
        {
          "value" : "o.e.n.Node",
          "count" : 7
        },
        {
          "value" : "o.e.e.NodeEnvironment",
          "count" : 2
        },
        {
          "value" : "o.e.a.ActionModule",
          "count" : 1
        },
        {
          "value" : "o.e.c.s.ClusterApplierService",
          "count" : 1
        },
        {
          "value" : "o.e.c.s.MasterService",
          "count" : 1
        },
        {
          "value" : "o.e.d.DiscoveryModule",
          "count" : 1
        },
        {
          "value" : "o.e.g.GatewayService",
          "count" : 1
        },
        {
          "value" : "o.e.l.LicenseService",
          "count" : 1
        }
      ]
    },
    "loglevel" : {
      "count" : 53,
      "cardinality" : 3,
      "top_hits" : [
        {
          "value" : "INFO",
          "count" : 51
        },
        {
          "value" : "DEBUG",
          "count" : 1
        },
        {
          "value" : "WARN",
          "count" : 1
        }
      ]
    },
    "message" : {
      "count" : 53,
      "cardinality" : 53,
      "top_hits" : [
        {
          "value" : "Using REST wrapper from plugin org.elasticsearch.xpack.security.Security",
          "count" : 1
        },
        {
          "value" : "adding template [.monitoring-alerts] for index patterns [.monitoring-alerts-6]",
          "count" : 1
        },
        {
          "value" : "adding template [.monitoring-beats] for index patterns [.monitoring-beats-6-*]",
          "count" : 1
        },
        {
          "value" : "adding template [.monitoring-es] for index patterns [.monitoring-es-6-*]",
          "count" : 1
        },
        {
          "value" : "adding template [.monitoring-kibana] for index patterns [.monitoring-kibana-6-*]",
          "count" : 1
        },
        {
          "value" : "adding template [.monitoring-logstash] for index patterns [.monitoring-logstash-6-*]",
          "count" : 1
        },
        {
          "value" : "adding template [.triggered_watches] for index patterns [.triggered_watches*]",
          "count" : 1
        },
        {
          "value" : "adding template [.watch-history-9] for index patterns [.watcher-history-9*]",
          "count" : 1
        },
        {
          "value" : "adding template [.watches] for index patterns [.watches*]",
          "count" : 1
        },
        {
          "value" : "starting ...",
          "count" : 1
        }
      ]
    },
    "node" : {
      "count" : 53,
      "cardinality" : 1,
      "top_hits" : [
        {
          "value" : "node-0",
          "count" : 53
        }
      ]
    },
    "timestamp" : {
      "count" : 53,
      "cardinality" : 28,
      "earliest" : "2018-09-27T14:39:28,518",
      "latest" : "2018-09-27T14:39:37,012",
      "top_hits" : [
        {
          "value" : "2018-09-27T14:39:29,859",
          "count" : 10
        },
        {
          "value" : "2018-09-27T14:39:29,860",
          "count" : 9
        },
        {
          "value" : "2018-09-27T14:39:29,858",
          "count" : 6
        },
        {
          "value" : "2018-09-27T14:39:28,523",
          "count" : 3
        },
        {
          "value" : "2018-09-27T14:39:34,234",
          "count" : 2
        },
        {
          "value" : "2018-09-27T14:39:28,518",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:28,521",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:28,522",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:29,861",
          "count" : 1
        },
        {
          "value" : "2018-09-27T14:39:32,786",
          "count" : 1
        }
      ]
    }
  }
}

输出中的 grok_pattern 现在是查询参数中提供的被覆盖的那个。

使用的ECS Grok模式兼容模式,可以是disabled(如果请求中未指定,则为默认值)或v1

返回的 field_stats 包括来自被覆盖的 grok_pattern 的字段条目。

URL 转义很复杂,所以如果你是交互式工作,最好使用 UI!

测试 Grok 模式 API

edit

在文本行上测试Grok模式,另请参阅Grokking grok

请求

edit

GET _text_structure/test_grok_pattern

POST _text_structure/test_grok_pattern

描述

edit

测试 Grok 模式 API 允许您对一行或多行文本执行 Grok 模式。它返回这些行是否与模式匹配,以及匹配子字符串的偏移量和长度。

查询参数

edit
ecs_compatibility
(可选, 字符串) 与符合ECS标准的Grok模式的兼容性模式。 使用此参数来指定当结构查找器创建Grok模式时,是否使用ECS Grok模式而不是传统的模式。有效值为disabledv1。默认值为disabled

请求体

edit
grok_pattern
(必需,字符串) 要在线文本上运行的 Grok 模式。
text
(必需,字符串数组) 要运行 Grok 模式的文本行。

示例

edit
GET _text_structure/test_grok_pattern
{
  "grok_pattern": "Hello %{WORD:first_name} %{WORD:last_name}",
  "text": [
    "Hello John Doe",
    "this does not match"
  ]
}

API返回以下响应:

{
  "matches": [
    {
      "matched": true,
      "fields": {
        "first_name": [
          {
            "match": "John",
            "offset": 6,
            "length": 4
          }
        ],
        "last_name": [
          {
            "match": "Doe",
            "offset": 11,
            "length": 3
          }
        ]
      }
    },
    {
      "matched": false
    }
  ]
}