loki.process
loki.process
接收来自其他 loki 组件的日志条目,应用一个或多个处理阶段,并将结果转发到组件参数中的接收器列表。
阶段是一种多用途工具,可以在日志条目传递到下游组件之前对其进行解析、转换和过滤。这些阶段按照它们在配置文件中出现的顺序应用于每个日志条目。loki.process
块内的所有阶段都可以访问日志条目的标签集、日志行、日志时间戳以及“提取”值的共享映射,以便一个阶段的结果可以在后续阶段中使用。
您可以通过为多个 loki.process
组件提供不同的标签来指定它们。
用法
loki.process "<LABEL>" {
forward_to = <RECEIVER_LIST>
stage.<STAGENAME> {
...
}
...
}
参数
您可以将以下参数与 loki.process
一起使用
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
forward_to | list(LogsReceiver) | 处理后将日志条目转发到何处。 | 是 |
块
您可以将以下块与 loki.process
一起使用
块 | 描述 | 必需 |
---|---|---|
stage.cri | 配置预定义的 CRI 格式管道。 | 否 |
stage.decolorize | 从日志行中去除 ANSI 颜色代码。 | 否 |
stage.docker | 配置预定义的 Docker 日志格式管道。 | 否 |
stage.drop | 配置 drop 处理阶段。 | 否 |
stage.eventlogmessage | 从 Windows 事件日志中的消息字段提取数据。 | 否 |
stage.geoip | 配置 geoip 处理阶段。 | 否 |
stage.json | 配置 JSON 处理阶段。 | 否 |
stage.label_drop | 配置 label_drop 处理阶段。 | 否 |
stage.label_keep | 配置 label_keep 处理阶段。 | 否 |
stage.labels | 配置 labels 处理阶段。 | 否 |
stage.limit | 配置 limit 处理阶段。 | 否 |
stage.logfmt | 配置 logfmt 处理阶段。 | 否 |
stage.luhn | 配置 luhn 处理阶段。 | 否 |
stage.match | 配置 match 处理阶段。 | 否 |
stage.metrics | 配置 metrics 阶段。 | 否 |
stage.multiline | 配置 multiline 处理阶段。 | 否 |
stage.output | 配置 output 处理阶段。 | 否 |
stage.pack | 配置 pack 处理阶段。 | 否 |
stage.regex | 配置 regex 处理阶段。 | 否 |
stage.replace | 配置 replace 处理阶段。 | 否 |
stage.sampling | 以给定的速率采样日志。 | 否 |
stage.static_labels | 配置 static_labels 处理阶段。 | 否 |
stage.structured_metadata | 配置结构化元数据处理阶段。 | 否 |
stage.template | 配置 template 处理阶段。 | 否 |
stage.tenant | 配置 tenant 处理阶段。 | 否 |
stage.timestamp | 配置 timestamp 处理阶段。 | 否 |
您可以提供任意数量的这些 stage 块,嵌套在 loki.process
内部。这些块按照在配置文件中出现的顺序运行。
stage.cri
stage.cri
内部块启用预定义的管道,该管道使用 CRI 日志记录格式读取日志行。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
max_partial_line_size_truncate | bool | 截断长度超过 max_partial_line_size 的部分行。 | false | 否 |
max_partial_line_size | number | 部分行可以具有的最大字符数。 | 0 | 否 |
max_partial_lines | number | 内存中要保留的最大部分行数。 | 100 | 否 |
只有当 max_partial_line_size_truncate
设置为 true
时,才会考虑 max_partial_line_size
。
stage.cri {}
CRI 将日志行指定为以空格分隔的单个值,包含以下组件
time
:日志的时间戳字符串。stream
:stdout
或stderr
。flags
:CRI 标志,包括F
或P
。log
:日志行的内容。
给定以下日志行,将在提取数据的共享映射中创建后续的键值对
"2019-04-30T02:12:41.8443515Z stdout F message"
content: message
stream: stdout
timestamp: 2019-04-30T02:12:41.8443515
stage.decolorize
stage.decolorize
从日志行中去除 ANSI 颜色代码,使其更易于解析日志。
stage.decolorize
块不支持任何参数或内部块,因此它始终为空。
stage.decolorize {}
stage.decolorize
将每个具有颜色代码的行转换为非彩色行。例如
[2022-11-04 22:17:57.811] \033[0;32http\033[0m: GET /_health (0 ms) 204
被转换为
[2022-11-04 22:17:57.811] http: GET /_health (0 ms) 204
stage.docker
stage.docker
内部块启用预定义的管道,该管道以 Docker 日志文件的标准格式读取日志行。
stage.docker
块不支持任何参数或内部块,因此它始终为空。
stage.docker {}
Docker 日志条目格式化为 JSON,包含以下键
log
:日志行的内容。stream
:stdout
或stderr
。time
:日志行的时间戳字符串。
给定以下日志行,将在提取数据的共享映射中创建后续的键值对
{"log":"log message\n","stream":"stderr","time":"2019-04-30T02:12:41.8443515Z"}
output: log message\n
stream: stderr
timestamp: 2019-04-30T02:12:41.8443515
stage.drop
stage.drop
内部块配置一个过滤阶段,该阶段根据多个选项删除日志条目。如果提供了多个选项,则它们被视为 AND 子句,并且所有选项都必须为 true,日志条目才会被删除。要使用 OR 子句删除条目,请按顺序指定多个 drop
块。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
drop_counter_reason | string | 报告已删除行的自定义原因。 | "drop_stage" | 否 |
expression | string | 有效的 RE2 正则表达式。 | "" | 否 |
longer_than | string | 如果指定,则该阶段会删除大小超过配置值的行。 | "" | 否 |
older_than | duration | 如果指定,则该阶段会删除时间戳早于当前时间减去此持续时间的行。 | "" | 否 |
separator | string | 当 source 是以逗号分隔的名称列表时,此分隔符放置在连接的提取数据值之间。 | ";" | 否 |
source | string | 要匹配的提取数据中的名称或以逗号分隔的名称列表。如果为空或未定义,则使用日志消息。 | "" | 否 |
value | string | 如果同时指定了 source 和 value ,则该阶段会删除 value 与源内容完全匹配的行。 | "" | 否 |
expression
字段必须是 RE2 正则表达式字符串。
- 如果
source
为空或未提供,则正则表达式尝试匹配日志行本身。 - 如果
source
是单个名称,则正则表达式尝试匹配提取映射中的相应值。 - 如果
source
是以逗号分隔的名称列表,则使用separator
连接提取映射中的相应值,并且正则表达式尝试匹配连接的字符串。
value
字段只能与提取映射中的值一起使用,并且必须与 source
一起指定。
- 如果
source
是单个名称,则当提取映射中的相应值与value
完全匹配时,条目将被删除。 - 如果
source
是以逗号分隔的名称列表,则当value
匹配使用separator
连接的提取数据中的source
值时,条目将被删除。
每当删除条目时,指标 loki_process_dropped_lines_total
就会递增。默认情况下,原因标签为 "drop_stage"
,但您可以使用 drop_counter_reason
参数提供自定义标签。
以下阶段删除包含单词 debug
且长度超过 1KB 的日志条目。
stage.drop {
expression = ".*debug.*"
longer_than = "1KB"
}
以下示例定义了多个 drop
块,因此 loki.process
会删除 24 小时或更旧的条目、长度超过 8KB 的条目,或者 app
的提取值等于 example
的条目。
stage.drop {
older_than = "24h"
drop_counter_reason = "too old"
}
stage.drop {
longer_than = "8KB"
drop_counter_reason = "too long"
}
stage.drop {
source = "app"
value = "example"
}
stage.eventlogmessage
eventlogmessage
阶段从 Windows 事件日志中出现的消息字符串中提取数据。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
drop_invalid_labels | bool | 是否删除不是有效标签名称的字段。 | false | 否 |
overwrite_existing | bool | 是否覆盖现有的提取数据字段。 | false | 否 |
source | string | source | message | 否 |
当 drop_invalid_labels
设置为 true
时,该阶段会删除不是有效标签名称的字段。如果设置为 false
,则该阶段会自动将它们转换为有效标签,并将无效字符替换为下划线。
当 overwrite_existing
设置为 true
时,该阶段会覆盖具有相同名称的现有提取数据字段。如果设置为 false
,则 _extracted
后缀将附加到现有字段名称。
eventlogmessage
阶段仅提取具有 key:value 格式的行。键中的所有非字母字符都将替换为下划线。例如,\tSecurity ID
被提取为 _Security_ID
。
与 stage.json
结合使用的示例
stage.json {
expressions = {
message = "",
Overwritten = "",
}
}
stage.eventlogmessage {
source = "message"
overwrite_existing = true
}
给定以下日志行
{"event_id": 1, "Overwritten": "old", "message": "Message type:\r\nOverwritten: new\r\nImage: C:\\Users\\User\\alloy.exe"}
第一个阶段将在提取数据集中创建以下键值对
message
:Message type:\r\nOverwritten: new\r\nImage: C:\Users\User\alloy.exe
Overwritten
:old
第二个阶段解析提取数据中 message
的值,并将以下键值对附加或覆盖到提取数据集中
Image
:C:\\Users\\User\\alloy.exe
Message_type
: (空字符串)Overwritten
:new
stage.geoip
stage.geoip
内部块配置一个处理阶段,该阶段读取 IP 地址并使用 geoip
字段填充共享映射。Maxmind GeoIP2 数据库用于查找。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
db | string | Maxmind DB 文件的路径。 | 是 | |
source | string | source | 是 | |
custom_lookups | map(string) | JMESPath 表达式的键值对。 | 否 | |
db_type | string | Maxmind DB 类型。允许的值为 "city" 、"asn" 、"country" 。 | 否 |
使用 City 数据库的 GeoIP 示例
{"log":"log message","client_ip":"34.120.177.193"}
loki.process "example" {
stage.json {
expressions = {ip = "client_ip"}
}
stage.geoip {
source = "ip"
db = "/path/to/db/GeoLite2-City.mmdb"
db_type = "city"
}
stage.labels {
values = {
geoip_city_name = "",
geoip_country_name = "",
geoip_country_code = "",
geoip_continent_name = "",
geoip_continent_code = "",
geoip_location_latitude = "",
geoip_location_longitude = "",
geoip_postal_code = "",
geoip_timezone = "",
geoip_subdivision_name = "",
geoip_subdivision_code = "",
}
}
}
json
阶段从日志行中的 client_ip
键中提取 IP 地址。然后,将提取的 ip
值作为源提供给 geoip
阶段。geoip
阶段对 IP 执行查找,并在共享映射中填充以下字段,这些字段使用 labels
阶段添加为标签。
此示例中使用的 IP 的提取数据
geoip_city_name: Kansas City
geoip_country_name: United States
geoip_country_code: US
geoip_continent_name: North America
geoip_continent_code: NA
geoip_location_latitude: 39.1027
geoip_location_longitude: -94.5778
geoip_postal_code: 64184
geoip_timezone: America/Chicago
geoip_subdivision_name: Missouri
geoip_subdivision_code: MO
使用 ASN(自治系统号)数据库的 GeoIP 示例
loki.process "example" {
stage.json {
expressions = {ip = "client_ip"}
}
stage.geoip {
source = "ip"
db = "/path/to/db/GeoIP2-ASN.mmdb"
db_type = "asn"
}
stage.labels {
values = {
geoip_autonomous_system_number = "",
geoip_autonomous_system_organization = "",
}
}
}
json
阶段从日志行中的 client_ip
键中提取 IP 地址。然后,将提取的 ip
值作为源提供给 geoip
阶段。geoip
阶段对 IP 执行查找,并填充共享映射。
此示例中使用的 IP 的提取数据
geoip_autonomous_system_number: 396982
geoip_autonomous_system_organization: GOOGLE-CLOUD-PLATFORM
使用 Country 数据库的 GeoIP 示例
{"log":"log message","client_ip":"34.120.177.193"}
loki.process "example" {
stage.json {
expressions = {ip = "client_ip"}
}
stage.geoip {
source = "ip"
db = "/path/to/db/GeoLite2-Country.mmdb"
db_type = "country"
}
stage.labels {
values = {
geoip_country_name = "",
geoip_country_code = "",
geoip_continent_name = "",
geoip_continent_code = "",
}
}
}
json
阶段从日志行中的 client_ip
键中提取 IP 地址。然后,将提取的 ip
值作为源提供给 geoip
阶段。geoip
阶段对 IP 执行查找,并在共享映射中填充以下字段,这些字段使用 labels
阶段添加为标签。
此示例中使用的 IP 的提取数据
geoip_country_name: United States
geoip_country_code: US
geoip_continent_name: North America
geoip_continent_code: NA
使用自定义字段的 GeoIP 示例
如果使用的 MMDB 文件使用自定义数据进行了丰富,例如,Maxmind 博客文章中解释的私有 IP 地址,则可以使用 custom_lookups
属性从记录中提取它。
loki.process "example" {
stage.json {
expressions = {ip = "client_ip"}
}
stage.geoip {
source = "ip"
db = "/path/to/db/GeoIP2-Enriched.mmdb"
db_type = "city"
custom_lookups = {
"department" = "MyCompany.DeptName",
"parent_vnet" = "MyCompany.ParentVNet",
"subnet" = "MyCompany.Subnet",
}
}
stage.labels {
values = {
department = "",
parent_vnet = "",
subnet = "",
}
}
}
json
阶段从日志行中的 client_ip
键中提取 IP 地址。然后,将提取的 ip
值作为源提供给 geoip
阶段。geoip
阶段对 IP 执行查找,并在共享映射中填充城市数据库结果中的数据以及自定义查找。最后,共享映射中的自定义查找字段将添加为标签。
stage.json
stage.json
内部块配置一个 JSON 处理阶段,该阶段将传入的日志行或先前提取的值解析为 JSON,并使用 JMESPath 表达式从中提取新值。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
expressions | map(string) | JMESPath 表达式的键值对。 | 是 | |
drop_malformed | bool | 删除输入无法解析为有效 JSON 的行。 | false | 否 |
source | string | source | "" | 否 |
expressions
字段是要运行的 JMESPath 表达式的键值对集合。映射键定义提取数据的名称,而映射值是用于填充值的表达式。
配置 JSON 阶段时,source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是先前提取的值。
以下示例显示了给定的日志行和两个 JSON 阶段。
{"log":"log message\n","extra":"{\"user\":\"alloy\"}"}
loki.process "username" {
stage.json {
expressions = {output = "log", extra = ""}
}
stage.json {
source = "extra"
expressions = {username = "user"}
}
}
在此示例中,第一个阶段使用日志行作为源,并在共享映射中填充这些值。空表达式表示使用与键相同的值,例如 extra="extra"
。
output: log message\n
extra: {"user": "alloy"}
第二个阶段使用 extra
中的值作为输入,并将以下键值对附加到提取数据集中。
username: alloy
注意
由于上游
jmespath
库的限制,您必须将任何包含连字符-
的字符串用引号括起来,以使其不被视为数值表达式。如果您不使用引号来括住包含连字符的字符串,您将收到如下错误:
Unexpected token at the end of the expression: tNumber
您可以使用以下两种选项之一来规避此问题
- 转义的双引号。例如:
http_user_agent = "\"request_User-Agent\""
- 反引号。例如:
http_user_agent = `"request_User-Agent"`
stage.label_drop
stage.label_drop
内部块配置一个处理阶段,该阶段从传入的日志条目中删除标签。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
values | list(string) | 配置 label_drop 处理阶段。 | {} | 否 |
stage.label_drop {
values = [ "kubernetes_node_name", "kubernetes_namespace" ]
}
stage.label_keep
stage.label_keep
内部块配置一个处理阶段,该阶段将传入日志条目的标签集过滤为子集。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
values | list(string) | 配置 label_keep 处理阶段。 | {} | 否 |
stage.label_keep {
values = [ "kubernetes_pod_name", "kubernetes_pod_container_name" ]
}
stage.labels
stage.labels
内部块配置一个标签处理阶段,该阶段可以从提取的值映射中读取数据,并在传入的日志条目上设置新标签。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
values | map(string) | 配置 labels 处理阶段。 | {} | 否 |
在 labels 阶段中,映射的键定义要设置的标签,值是如何查找它们。如果值为空,则推断为与键相同。
stage.labels {
values = {
env = "", // Sets up an 'env' label, based on the 'env' extracted value.
user = "username", // Sets up a 'user' label, based on the 'username' extracted value.
}
}
stage.limit
stage.limit
内部块配置一个速率限制阶段,该阶段根据多个选项限制日志的速率。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
burst | number | 该阶段转发的最大突发行数。 | 是 | |
rate | number | 该阶段每秒转发的最大行数速率。 | 是 | |
by_label_name | string | 在按标签名称进行速率限制时要使用的标签。 | "" | 否 |
drop | bool | 是丢弃还是背压超过速率限制的行。 | false | 否 |
max_distinct_labels | number | 在按 by_label_name 进行速率限制时要跟踪的唯一值数量。 | 10000 | 否 |
速率限制是大小为 burst
的“令牌桶”。它最初是满的,并以每秒 rate
个令牌的速度重新填充。每个收到的日志条目消耗桶中的一个令牌。当 drop
设置为 true 时,超过速率限制的传入条目将被删除,否则它们将被排队,直到有更多令牌可用。
stage.limit {
rate = 5
burst = 10
}
如果设置了 by_label_name
,则 drop
必须设置为 true
。这使该阶段能够按标签数量而不是行数进行速率限制。
以下示例独立地对每个唯一 namespace
值中的条目进行速率限制。任何没有 namespace
标签的条目都不会受到速率限制。该阶段最多跟踪 max_distinct_labels
个唯一值,默认为 10000。
stage.limit {
rate = 10
burst = 10
drop = true
by_label_name = "namespace"
}
stage.logfmt
stage.logfmt
内部块配置一个处理阶段,该阶段将传入的日志行读取为 logfmt 并从中提取值。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
mapping | map(string) | 要提取的 logmft 字段的键值对。 | 是 | |
source | string | source | "" | 否 |
source
字段定义要解析为 logfmt
的数据源。当 source
缺失或为空时,该阶段将解析日志行本身,但它也可以用于解析先前提取的值。
此阶段使用 go-logfmt unmarshaler,以便将数字或布尔类型解组为其正确的形式。该阶段不执行任何其他类型转换。如果提取的值是复杂类型,则将其视为字符串。
以下日志行和阶段演示了其工作原理。
time=2012-11-01T22:08:41+00:00 app=loki level=WARN duration=125 message="this is a log line" extra="user=example_name"
stage.logfmt {
mapping = { "extra" = "" }
}
stage.logfmt {
mapping = { "username" = "user" }
source = "extra"
}
第一个阶段解析日志行本身,并在提取数据集中插入 extra
键,其值为 user=example_name
。
第二个阶段解析 extra
的内容,并将 username: example_name
键值对附加到提取数据集中。
stage.luhn
stage.luhn
内部块配置一个处理阶段,该阶段读取传入的日志行并编辑与 Luhn 算法匹配的字符串。
Luhn 算法 是一种简单的校验和公式,用于验证各种识别号码,例如信用卡号、IMEI 号、美国国家提供商标识号码和加拿大社会保险号码。许多支付卡行业环境要求编辑这些号码。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
min_length | int | 要考虑的最小位数长度 | 13 | 否 |
replacement | string | 用于替换匹配模式的字符串 | "**已编辑**" | 否 |
source | string | source | "" | 否 |
source
字段定义要搜索的数据源。当 source
缺失或为空时,该阶段将解析日志行本身,但它也可以用于解析先前提取的值。
以下示例日志行包含已批准的信用卡号。
time=2012-11-01T22:08:41+00:00 app=loki level=WARN duration=125 message="credit card approved 4032032513548443" extra="user=example_name"
stage.luhn {
replacement = "**DELETED**"
}
该阶段解析日志行,编辑信用卡号,并生成以下更新的日志行
time=2012-11-01T22:08:41+00:00 app=loki level=INFO duration=125 message="credit card approved **DELETED**" extra="user=example_name"
stage.match
stage.match
内部块配置一个过滤阶段,当日志条目与可配置的 LogQL 流选择器和过滤器表达式匹配时,该阶段可以有条件地应用一组嵌套的处理阶段或删除条目。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
selector | string | 要使用的 LogQL 流选择器和行过滤器表达式。 | 是 | |
action | string | 当选择器与日志行匹配时要采取的操作。支持的值为 "keep" 和 "drop" | "keep" | 否 |
drop_counter_reason | string | 报告已删除行的自定义原因。 | drop_counter_reason | 否 |
pipeline_name | string | 用于嵌套管道的自定义名称。 | "" | 否 |
注意
过滤器不包括标签过滤器表达式,例如
| label == "examplelabel"
。
stage.match
块支持许多 stage.*
内部块,就像顶级块一样。这些用于构建一组嵌套阶段,以便在选择器与日志条目的标签和内容匹配时运行。它支持与 loki.process
组件的顶级相同的 stage.NAME
块。
如果指定的操作是 "drop"
,则每删除一行,指标 loki_process_dropped_lines_total
就会递增。默认情况下,原因标签为 "match_stage"
,但可以使用 drop_counter_reason
参数提供自定义原因。
以下示例日志行和阶段显示了其工作原理。
{ "time":"2023-01-18T17:08:41+00:00", "app":"example1", "component": ["parser","type"], "level" : "WARN", "message" : "app1 log line" }
{ "time":"2023-01-18T17:08:42+00:00", "app":"example2", "component": ["parser","type"], "level" : "ERROR", "message" : "example noisy error" }
stage.json {
expressions = { "appname" = "app" }
}
stage.labels {
values = { "applbl" = "appname" }
}
stage.match {
selector = "{applbl=\"examplelabel\"}"
stage.json {
expressions = { "msg" = "message" }
}
}
stage.match {
selector = "{applbl=\"qux\"}"
stage.json {
expressions = { "msg" = "msg" }
}
}
stage.match {
selector = "{applbl=\"bar\"} |~ \".*noisy error.*\""
action = "drop"
drop_counter_reason = "discard_noisy_errors"
}
stage.output {
source = "msg"
}
前两个阶段将日志行解析为 JSON,将 app
值解码到共享提取映射中作为 appname
,并将其值用作 applbl
标签。
第三个阶段使用 LogQL 选择器仅在 applbl="examplelabel"
的行上执行嵌套阶段。因此,对于第一行,嵌套的 JSON 阶段将 msg="app1 log line"
添加到提取映射中。
第四个阶段使用 LogQL 选择器仅在 applbl="qux"
的行上执行。这意味着它不会匹配任何输入,并且嵌套的 JSON 阶段不会运行。
第五个阶段从 applbl
设置为“example2”且行内容与正则表达式 .*noisy error.*
匹配的行中删除条目。它还会使用标签 drop_counter_reason="discard_noisy_errors"
递增 loki_process_dropped_lines_total
指标。
最终输出阶段将日志行的内容更改为提取映射中 msg
的值。在这种情况下,第一个日志条目的内容更改为 app1 log line
。
stage.metrics
stage.metrics
内部块配置阶段,该阶段允许您根据共享提取映射中的值定义和更新指标。创建的指标在 Alloy 根目录 /metrics
端点处可用。
stage.metrics
块不支持任何参数,仅通过多个嵌套的内部 metric.*
块进行配置,每个块对应一个应生成的指标。
stage.metrics
的定义内支持以下块
块 | 描述 | 必需 |
---|---|---|
metric.counter | 定义 counter 指标。 | 否 |
metric.gauge | 定义 gauge 指标。 | 否 |
metric.histogram | 定义 histogram 指标。 | 否 |
注意
如果您重新加载 Alloy 配置文件,指标将被重置。
metric.counter
定义一个值只会增加的指标。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
action | string | action | 是 | |
name | string | 指标名称。 | 是 | |
count_entry_bytes | bool | 如果设置为 true,则计算所有日志行字节数。 | false | 否 |
description | string | 指标的描述和帮助文本。 | "" | 否 |
match_all | bool | 如果设置为 true,则计算所有日志行,而不尝试将 source 与提取映射匹配。 | false | 否 |
max_idle_duration | duration | 等待指标标记为“过时”并删除的最大时间量。 | "5m" | 否 |
prefix | string | 指标名称的前缀。 | "loki_process_custom_" | 否 |
source | string | source | "" | 否 |
value | string | value | "" | 否 |
计数器不能将 match_all
设置为 true 并且设置 value
。计数器不能在未同时设置 match_all=true
或 action=add
的情况下设置 count_entry_bytes
。有效的 action
值为 inc
和 add
。inc
操作使指标值对于每个通过过滤器的日志行增加 1。add
操作将提取的值转换为正浮点数并将其添加到指标。
metric.gauge
定义一个值可以上升或下降的 gauge 指标。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
action | string | action | 是 | |
name | string | 指标名称。 | 是 | |
description | string | 指标的描述和帮助文本。 | "" | 否 |
max_idle_duration | duration | 等待指标标记为“过时”并删除的最大时间量。 | "5m" | 否 |
prefix | string | 指标名称的前缀。 | "loki_process_custom_" | 否 |
source | string | source | "" | 否 |
value | string | value | "" | 否 |
有效的 action
值为 inc
、dec
、set
、add
或 sub
。inc
和 dec
分别将指标的值增加和减少 1。如果选择 set
、add
或 sub
,则提取的值必须可转换为正浮点数,并且设置为、添加到或从指标的值中减去。
metric.histogram
定义一个直方图指标,其值记录在预定义的存储桶中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
buckets | list(float) | 预定义的存储桶 | 是 | |
name | string | 指标名称。 | 是 | |
description | string | 指标的描述和帮助文本。 | "" | 否 |
max_idle_duration | duration | 等待指标标记为“过时”并删除的最大时间量。 | "5m" | 否 |
prefix | string | 指标名称的前缀。 | "loki_process_custom_" | 否 |
source | string | source | "" | 否 |
value | string | value | "" | 否 |
metrics
行为
如果 value
不存在,则所有传入的日志条目都匹配。
在创建的指标上的标签值可以是动态的,这可能会导致导出的指标在基数上爆炸或变得过时,例如,当流停止接收新日志时。为了防止 /metrics
端点无限增长,任何在 max_idle_duration
内未更新的指标都将被删除。max_idle_duration
必须大于或等于 "1s"
,并且默认为 "5m"
。
从日志数据中提取的指标值在内部转换为浮点数。支持的值如下
- 整数
- 浮点数
- 字符串 - 支持两种类型的字符串格式
- 表示浮点数的字符串,例如,“0.804”转换为 0.804。
- 持续时间格式字符串。有效的时间单位为
"ns"
、"us"
、"ms"
、"s"
、"m"
、"h"
。此格式的值将转换为浮点秒数,例如,"0.5ms"
转换为0.0005
。
- 布尔值
true
转换为1
。false
转换为0
。
以下pipeline创建了一个计数器,每次收到任何日志行时,该计数器都会递增,通过使用 match_all
参数。该pipeline创建了第二个计数器,通过使用 count_entry_bytes
参数来添加这些日志行的字节大小。
如果24小时内没有收到新的条目,这两个指标将消失,以避免累积不再有任何用途的指标。这两个指标是跟踪日志流的卷(包括条目数量和字节大小)的良好起点,以识别高容量或高基数数据的来源。
stage.metrics {
metric.counter {
name = "log_lines_total"
description = "total number of log lines"
prefix = "my_custom_tracking_"
match_all = true
action = "inc"
max_idle_duration = "24h"
}
}
stage.metrics {
metric.counter {
name = "log_bytes_total"
description = "total bytes of log lines"
prefix = "my_custom_tracking_"
match_all = true
count_entry_bytes = true
action = "add"
max_idle_duration = "24h"
}
}
在这里,第一阶段使用正则表达式来提取日志行中格式为 order_status=<string>
的文本。第二阶段定义了一个计数器,根据先前提取的值,递增 successful_orders_total
和 failed_orders_total
。
stage.regex {
expression = "^.* order_status=(?P<order_status>.*?) .*$"
}
stage.metrics {
metric.counter {
name = "successful_orders_total"
description = "successful orders"
source = "order_status"
value = "success"
action = "inc"
}
}
stage.metrics {
metric.counter {
name = "failed_orders_total"
description = "failed orders"
source = "order_status"
value = "fail"
action = "inc"
}
}
在本示例中,第一阶段从日志行中提取格式为 retries=<value>
的文本。第二阶段创建了一个仪表盘,其当前指标值会根据从 retries 字段提取的数字而增加。
stage.regex {
expression = "^.* retries=(?P<retries>\\d+) .*$"
}
stage.metrics {
metric.gauge {
name = "retries_total"
description = "total_retries"
source = "retries"
action = "add"
}
}
以下示例展示了一个直方图,该直方图从提取的映射中读取 response_time
,并将其放入存储桶中,同时增加存储桶的计数和该特定存储桶的总和。
stage.metrics {
metric.histogram {
name = "http_response_time_seconds"
description = "recorded response times"
source = "response_time"
buckets = [0.001,0.0025,0.005,0.010,0.025,0.050]
}
}
stage.multiline
stage.multiline
内部块将多行合并成一个块,然后再将其传递到pipeline中的下一个阶段。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
firstline | string | 从提取的数据中获取用于日志条目的名称。 | 是 | |
max_lines | number | 一个块可以拥有的最大行数。 | 128 | 否 |
max_wait_time | duration | 等待多行块的最长时间。 | "3秒" | 否 |
通过在 firstline
中传递的 RE2 正则表达式来识别新块。
任何与该表达式不匹配的行都被认为是前一个匹配块的一部分。如果在 max_wait_time
内没有新的日志到达,则会发送该块。max_lines
字段定义了一个块可以拥有的最大行数。如果超过此限制,则会启动一个新块。
以下示例阶段和来自 Flask Web 服务的日志条目流展示了其工作原理。
stage.multiline {
firstline = "^\\[\\d{4}-\\d{2}-\\d{2} \\d{1,2}:\\d{2}:\\d{2}\\]"
max_wait_time = "10s"
}
[2023-01-18 17:41:21] "GET /hello HTTP/1.1" 200 -
[2023-01-18 17:41:25] ERROR in app: Exception on /error [GET]
Traceback (most recent call last):
File "/home/pallets/.pyenv/versions/3.8.5/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/pallets/.pyenv/versions/3.8.5/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/pallets/.pyenv/versions/3.8.5/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/pallets/.pyenv/versions/3.8.5/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/pallets/.pyenv/versions/3.8.5/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/pallets/.pyenv/versions/3.8.5/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/pallets/src/deployment_tools/hello.py", line 10, in error
raise Exception("Sorry, this route always breaks")
Exception: Sorry, this route always breaks
[2023-01-18 17:42:24] "GET /error HTTP/1.1" 500 -
[2023-01-18 17:42:29] "GET /hello HTTP/1.1" 200 -
构成单独 Web 请求的日志条目的所有“块”都以方括号中的时间戳开头。该阶段使用 firstline
中的正则表达式检测到这一点,以将回溯的所有行折叠成单个块,从而形成单个 Loki 日志条目。
stage.output
stage.output
内部块配置一个处理阶段,该阶段从提取的映射中读取数据,并更改转发到下一个组件的日志条目的内容。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
source | string | 从提取的数据中获取用于日志条目的名称。 | 是 |
以下示例日志行和三阶段pipeline展示了其工作原理。
{"user": "John Doe", "message": "hello, world!"}
stage.json {
expressions = { "user" = "user", "message" = "message" }
}
stage.labels {
values = { "user" = "user" }
}
stage.output {
source = "message"
}
第一阶段将以下键值对提取到共享映射中
user: John Doe
message: hello, world!
然后,第二阶段将 user="John Doe"
添加到日志条目的标签集中,最后一个输出阶段将日志行从原始 JSON 更改为 hello, world!
。
stage.pack
stage.pack
内部块配置一个转换阶段,该阶段用 JSON 对象替换日志条目,该 JSON 对象嵌入了提取的值和标签。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
labels | list(string) | 要与日志条目一起打包的提取数据和标签中的值。 | 是 | |
ingest_timestamp | bool | 是否将日志条目时间戳替换为 pack 阶段运行的时间。 | true | 否 |
此阶段允许您将提取的值和标签与日志行一起嵌入,方法是将它们打包到 JSON 对象中。原始消息存储在 _entry
键下,所有其他键都保留其值。这在您确实想要保留某个标签或元数据的情况下很有用,但由于高基数,您不希望将其索引为标签。
Loki 的查询功能使您可以轻松访问这些数据,以便在查询时对其进行过滤和聚合。
例如,考虑以下日志条目
log_line: "something went wrong"
labels: { "level" = "error", "env" = "dev", "user_id" = "f8fas0r" }
和此处理阶段
stage.pack {
labels = ["env", "user_id"]
}
该阶段将日志条目转换为以下 JSON 对象,其中从原始日志条目中删除了两个嵌入式标签
{
"_entry": "something went wrong",
"env": "dev",
"user_id": "f8fas0r"
}
在查询时,Loki unpack
解析器 可用于访问这些嵌入式标签,并将日志行自动替换为存储在 _entry
字段中的原始日志行。
当组合多个日志流以与 pack
阶段一起使用时,您可以将 ingest_timestamp
设置为 true,以避免交错的时间戳和乱序摄取问题。
stage.regex
stage.regex
内部块配置一个处理阶段,该阶段使用正则表达式解析日志行,并使用命名捕获组将数据添加到共享的提取值映射中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
expression | string | 有效的 RE2 正则表达式。每个捕获组都必须命名。 | 是 | |
source | string | 要解析的提取数据中的名称。如果为空,则使用日志消息。 | "" | 否 |
expression
字段需要是 RE2 正则表达式字符串。每个匹配的捕获组都会添加到提取的映射中,因此必须像这样命名:(?P<name>re)
。捕获组的名称随后用作提取映射中匹配值的键。
由于 Alloy 语法字符串的工作方式,expression
中的任何反斜杠都必须使用双反斜杠进行转义,例如,"\\w"
或 "\\S+"
。
如果 source
为空或缺失,则该阶段将解析日志行本身。如果已设置,则该阶段将解析先前提取的具有相同名称的值。
给定以下日志行和正则表达式阶段,提取的值如下所示
2019-01-01T01:00:00.000000001Z stderr P i'm a log message!
stage.regex {
expression = "^(?s)(?P<time>\\S+?) (?P<stream>stdout|stderr) (?P<flags>\\S+?) (?P<content>.*)$"
}
time: 2019-01-01T01:00:00.000000001Z,
stream: stderr,
flags: P,
content: i'm a log message
另一方面,如果设置了 source
值,则正则表达式将应用于存储在共享映射中该名称下的值。
以下日志行将通过此两阶段pipeline
{"timestamp":"2022-01-01T01:00:00.000000001Z"}
stage.json {
expressions = { time = "timestamp" }
}
stage.regex {
expression = "^(?P<year>\\d+)"
source = "time"
}
第一阶段将以下键值对添加到提取的映射中
time: 2022-01-01T01:00:00.000000001Z
然后,正则表达式阶段从共享值中解析 time 的值,并将后续的键值对添加回提取的值映射中
year: 2022
stage.replace
stage.replace
内部块配置一个阶段,该阶段使用正则表达式解析日志行并替换日志行内容。正则表达式中的命名捕获组也支持将数据添加到共享的提取映射中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
expression | string | 包含捕获组的 RE2 正则表达式。 | 是 | |
replace | string | 由捕获组替换的值。 | 否 | |
source | string | 要解析的数据源。如果为空,则使用日志消息。 | 否 |
expression
中的每个捕获组和命名捕获组都将替换为 replace
中给定的值。
expression
必须包含有效的 RE2 正则表达式捕获组。您还可以使用诸如 (?P<name>re)
之类的语法来命名某些组。如果任何捕获组被命名,则它们的值将设置到共享的提取映射中,名称为正则表达式组的名称。
source
字段定义了使用 expression
解析的数据源。当 source
缺失或为空时,该阶段将解析日志行本身,但它也可以用于解析先前提取的值。替换后的值将重新分配给 source
键。
由于 Alloy 语法如何处理双引号字符串中的反斜杠,因此正则表达式中的所有反斜杠都必须像 "\\w*"
这样转义。
以下日志行和阶段展示了其工作原理。由于省略了 source
,因此替换发生在日志行本身上。
2023-01-01T01:00:00.000000001Z stderr P i'm a log message who has sensitive information with password xyz!
stage.replace {
expression = "password (\\S+)"
replace = "*****"
}
日志行被转换为
2023-01-01T01:00:00.000000001Z stderr P i'm a log message who has sensitive information with password *****!
如果 replace
为空,则会省略捕获的值。
在以下示例中,定义了 source
。
{"time":"2023-01-01T01:00:00.000000001Z", "level": "info", "msg":"11.11.11.11 - \"POST /loki/api/push/ HTTP/1.1\" 200 932 \"-\" \"Mozilla/5.0\"}
stage.json {
expressions = { "level" = "", "msg" = "" }
}
stage.replace {
expression = "\\S+ - \"POST (\\S+) .*"
source = "msg"
replace = "redacted_url"
}
JSON 阶段将以下键值对添加到提取的映射中
time: 2023-01-01T01:00:00.000000001Z
level: info
msg: "11.11.11.11 - "POST /loki/api/push/ HTTP/1.1" 200 932 "-" "Mozilla/5.0"
replace
阶段作用于 msg
值。捕获组与 /loki/api/push
匹配,并被 redacted_url
替换。
msg
值最终转换为
msg: "11.11.11.11 - "POST redacted_url HTTP/1.1" 200 932 "-" "Mozilla/5.0"
replace
字段可以使用一组模板函数,通过利用 Go 的 text/template 包。
以下示例展示了如何将此功能与命名捕获组、示例日志行和阶段一起使用。
11.11.11.11 - alloy [01/Jan/2023:00:00:01 +0200]
stage.replace {
expression = "^(?P<ip>\\S+) (?P<identd>\\S+) (?P<user>\\S+) \\[(?P<timestamp>[\\w:/]+\\s[+\\-]\\d{4})\\]"
replace = "{{ .Value | ToUpper }}"
}
由于 source
为空,因此正则表达式解析日志行本身,并将命名捕获组提取到共享的值映射中。replace
字段作用于这些提取的值,并将它们转换为大写
ip: 11.11.11.11
identd: -
user: FRANK
timestamp: 01/JAN/2023:00:00:01 +0200
并且日志行变为
11.11.11.11 - FRANK [01/JAN/2023:00:00:01 +0200]
以下列表包含可用的函数以及更复杂的 replace
字段的示例。
ToLower, ToUpper, Replace, Trim, TrimLeftTrimRight, TrimPrefix, TrimSuffix, TrimSpace, Hash, Sha2Hash, regexReplaceAll, regexReplaceAllLiteral
| "{{ if eq .Value \"200\" }}{{ Replace .Value \"200\" \"HttpStatusOk\" -1 }}{{ else }}{{ .Value | ToUpper }}{{ end }}" |
| "*IP4*{{ .Value | Hash "salt" }}*" |
stage.sampling
sampling
阶段用于采样日志。配置值 rate = 0.1
意味着 10% 的日志将继续被处理。剩余 90% 的日志将被丢弃。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
rate | float | 采样率,范围为 [0, 1] | 是 | |
drop_counter_reason | string | 当日志被此阶段丢弃时,要添加到 loki_process_dropped_lines_total 指标的标签。 | sampling_stage | 否 |
例如,以下配置将采样 25% 的日志,并丢弃剩余的 75%。当日志被丢弃时,loki_process_dropped_lines_total
指标将递增,并带有额外的 reason=logs_sampling
标签。
stage.sampling {
rate = 0.25
drop_counter_reason = "logs_sampling"
}
stage.static_labels
stage.static_labels
内部块配置一个 static_labels 处理阶段,该阶段向传入的日志条目添加一组静态标签。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
values | map(string) | 配置 static_labels 处理阶段。 | {} | 否 |
stage.static_labels {
values = {
foo = "fooval",
bar = "barval",
}
}
stage.structured_metadata
stage.structured_metadata
内部块配置一个阶段,该阶段可以从提取的值映射中读取数据,并将它们作为结构化元数据添加到日志条目中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
values | map(string) | 指定要从提取的值映射添加到日志条目的标签列表。 | {} | 否 |
在 structured_metadata
阶段,映射的键定义要设置的标签,值是如何查找它们。如果值为空,则推断为与键相同。
stage.structured_metadata {
values = {
env = "", // Sets up an 'env' property to structured metadata, based on the 'env' extracted value.
user = "username", // Sets up a 'user' property to structured metadata, based on the 'username' extracted value.
}
}
stage.template
stage.template
内部块配置一个转换阶段,该阶段允许用户通过使用 Go 的 text/template
package 语法来操作提取的映射中的值。此阶段主要用于在将来自先前阶段的数据设置为后续阶段中的标签之前,对其进行操作和标准化。示例用例包括将空格替换为下划线、将大写字符串转换为小写或哈希值。
template 阶段还可以在提取的映射中创建新键。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
source | string | 要解析的提取数据中的名称。如果键不存在,则会创建一个新条目。 | 是 | |
template | string | 要使用的 Go 模板字符串。 | 是 |
模板字符串可以是 Go 的 text/template
可以使用的任何有效模板。它支持来自 sprig package 的所有函数,以及以下自定义函数列表
ToLower, ToUpper, Replace, Trim, TrimLeftTrimRight, TrimPrefix, TrimSuffix, TrimSpace, Hash, Sha2Hash, regexReplaceAll, regexReplaceAllLiteral
有关这些函数的更多详细信息,请参见 支持的函数 部分。
假设提取的映射中没有数据,则以下阶段仅将 new_key: "hello_world"
键值对添加到共享映射。
stage.template {
source = "new_key"
template = "hello_world"
}
如果 source
值存在于提取字段中,则可以在模板中将其值引用为 .Value
。下一个阶段获取提取映射中 app
的当前值,将其转换为小写,并向其值添加后缀
stage.template {
source = "app"
template = "{{ ToLower .Value }}_some_suffix"
}
任何先前提取的键都可用于 template
扩展和使用。下一个阶段获取 level
、app
和 module
的当前值,并创建一个名为 output_message
的新键
stage.template {
source = "output_msg"
template = "{{ .level }} for app {{ ToUpper .app }} in module {{.module}}"
}
名为 Entry
的特殊键可用于引用当前行。当您需要向日志行添加前缀/后缀时,这可能很有用,例如此代码段
stage.template {
source = "message"
template = "{{.app }}: {{ .Entry }}"
}
stage.output {
source = "message"
}
支持的函数
除了支持来自 sprig package 的所有函数外,template
阶段还支持以下自定义函数。
ToLower
和 ToUpper
ToLower
和 ToUpper
分别将整个字符串转换为小写和大写。
以下示例展示了如何使用此函数。
stage.template {
source = "out"
template = "{{ ToLower .app }}"
}
stage.template {
source = "out"
template = "{{ .app | ToUpper }}"
}
Replace
Replace
函数语法定义为 {{ Replace <string> <old> <new> <n> }}
。
该函数返回输入字符串的副本,其中 <old>
参数的实例被 <new>
替换。该函数最多替换第二个参数的 <n>
个非重叠实例。如果 <n>
小于零,则对替换次数没有限制。最后,如果 <old>
为空,则它与字符串中每个 UTF-8 字符之前和之后的位置匹配。
此示例将前两个 loki
单词实例替换为 Loki
stage.template {
source = "output"
template = `{{ Replace .Value "loki" "Loki" 2 }}`
}
Trim
、TrimLeft
、TrimRight
、TrimSpace
、TrimPrefix
、TrimSuffix
Trim
返回字符串s
的切片,其中删除了cutset
中包含的所有前导和尾随 Unicode 代码点。TrimLeft
和TrimRight
与 Trim 相同,只是它们分别仅修剪前导和尾随字符。TrimSpace
返回字符串 s 的切片,其中删除了 Unicode 定义的所有前导和尾随空格。TrimPrefix
和TrimSuffix
分别修剪提供的前缀或后缀。
以下示例展示了如何使用此函数。
stage.template {
source = "output"
template = `{{ Trim .Value ",. " }}`
}
stage.template {
source = "output"
template = "{{ TrimSpace .Value }}"
}
stage.template {
source = "output"
template = `{{ TrimPrefix .Value "--" }}`
}
regexReplaceAll
和 regexReplaceAllLiteral
regexReplaceAll
返回输入字符串的副本,将 Regexp 的匹配项替换为替换字符串。在替换字符串内部,$
字符的解释方式与 Expand 函数中相同。例如,$1 表示第一个捕获的子匹配项。
regexReplaceAllLiteral
返回输入字符串的副本,将 Regexp 的匹配项替换为替换字符串。替换字符串被直接替换,而不使用 Expand。
stage.template {
source = "output"
template = `{{ regexReplaceAll "(a*)bc" .Value "${1}a" }}`
}
stage.template {
source = "output"
template = `{{ regexReplaceAllLiteral "(ts=)" .Value "timestamp=" }}`
}
Hash
和 Sha2Hash
Hash
返回字符串的 Sha3_256
哈希值,表示为 64 位十六进制数。您可以使用它来混淆日志中的敏感数据和 PII。它需要一个(固定的)salt 值,以增加低输入域的复杂性,例如,所有可能的社会安全号码。Sha2Hash
返回字符串的 Sha2_256
,它比 Hash
更快且 CPU 密集程度更低,但安全性较低。
以下示例展示了如何使用此函数。
stage.template {
source = "output"
template = `{{ Hash .Value "salt" }}`
}
stage.template {
source = "output"
template = `{{ Sha2Hash .Value "salt" }}`
}
我们建议使用 Hash,因为它具有更强大的哈希算法。
stage.tenant
stage.tenant
内部块通过从提取的数据映射、标签或提供的值中的字段获取租户 ID,来为日志条目设置租户 ID。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
label | string | 要设置为租户 ID 的标签。 | "" | 否 |
source | string | 要用作租户 ID 的提取值中的名称。 | "" | 否 |
value | string | 要设置为租户 ID 的值。 | "" | 否 |
该块仅期望提供 label
、source
或 value
中的一个。
以下阶段将固定值 team-a
分配为租户 ID
stage.tenant {
value = "team-a"
}
在将日志条目解析为 JSON 后,此阶段从共享提取映射中的 customer_id
字段提取租户 ID
stage.json {
expressions = { "customer_id" = "" }
}
stage.tenant {
source = "customer_id"
}
最后一个示例从先前阶段设置的标签集中提取租户 ID
stage.labels {
"namespace" = "k8s_namespace"
}
stage.tenant {
label = "namespace"
}
stage.timestamp
stage.timestamp
内部块配置一个处理阶段,该阶段在将日志条目转发到下一个组件之前设置日志条目的时间戳。当未设置时间戳阶段时,日志条目时间戳默认为抓取日志条目的时间。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
format | string | 确定如何解析源字符串。 | 是 | |
source | string | 从提取的值映射中获取用于时间戳的名称。 | 是 | |
action_on_failure | string | 当无法提取或解析时间戳时要执行的操作。 | "fudge" | 否 |
fallback_formats | list(string) | 如果 format 字段失败,则尝试使用的回退格式。 | [] | 否 |
location | string | 解析时要使用的 IANA 时区数据库位置。 | "" | 否 |
注意
请注意,后面的阶段也可能覆盖时间戳。例如,将
ingest_timestamp
设置为true
的stage.pack
可能会替换stage.timestamp
之前在pipeline中设置的时间戳。
source
字段定义了阶段应尝试解析为时间戳的共享提取值映射中的哪个值。
format
字段定义了如何解析该源。
可以将 format
设置为以下常用形式的简写值之一
ANSIC: Mon Jan _2 15:04:05 2006
UnixDate: Mon Jan _2 15:04:05 MST 2006
RubyDate: Mon Jan 02 15:04:05 -0700 2006
RFC822: 02 Jan 06 15:04 MST
RFC822Z: 02 Jan 06 15:04 -0700
RFC850: Monday, 02-Jan-06 15:04:05 MST
RFC1123: Mon, 02 Jan 2006 15:04:05 MST
RFC1123Z: Mon, 02 Jan 2006 15:04:05 -0700
RFC3339: 2006-01-02T15:04:05-07:00
RFC3339Nano: 2006-01-02T15:04:05.999999999-07:00
此外,以下格式值支持常见的 Unix 时间戳
Unix: 1562708916 or with fractions 1562708916.000000123
UnixMs: 1562708916414
UnixUs: 1562708916414123
UnixNs: 1562708916000000123
否则,该字段接受自定义格式字符串,该字符串定义了阶段应如何解释历史记录中的任意参考点。任意参考点是 Mon Jan 2 15:04:05 -0700 MST 2006。
该字段的字符串值直接传递给 Go 的 time.Parse
函数中的 layout 参数。
如果自定义格式没有年份组件,则该阶段将使用当前年份,具体取决于系统时钟。
下表显示了定义自定义格式时要使用的受支持参考值。
时间戳组件 | 格式值 |
---|---|
年份 | 06, 2006 |
月份 | 1, 01, Jan, January |
日 | 2, 02, _2(两位数,右对齐) |
星期几 | Mon, Monday |
小时 | 3(12 小时制), 03(12 小时制,零填充), 15(24 小时制) |
分钟 | 4, 04 |
秒 | 5, 05 |
秒的小数部分 | .000(毫秒,零填充), .000000(微秒), .000000000(纳秒), .999(毫秒,无尾随零), .999999(微秒), .999999999(纳秒) |
12 小时制周期 | pm, PM |
时区名称 | MST |
时区偏移 | -0700, -070000(带秒), -07, -07:00, -07:00:00(带秒) |
时区 ISO-8601 | Z0700(UTC 或时区偏移的 Z), Z070000, Z07, Z07:00, Z07:00:00 |
注意
如果您定义自定义时间戳,则每个时间戳组件的
format
值必须是上表中指定的值之一。例如,要指示年份,format
值必须是06
或2006
,而不是任何其他值,如23
或2023
。
如果使用 format
解析失败,则 fallback_formats
字段定义了一个或多个格式字段,以尝试使用它们解析时间戳。
location
字段必须是有效的 IANA 时区数据库位置,并确定时间戳值在哪个时区被解释。
action_on_failure
字段定义了当源字段在共享提取映射中不存在时,或者时间戳解析失败时应发生的情况。
支持的操作是
- fudge(默认):将时间戳更改为上次已知的时间戳,并累加 1 纳秒以保证日志条目的顺序。
- skip:不更改时间戳,并保留抓取日志条目的时间。
以下阶段从共享值映射中获取 time
值,将其解析为 RFC3339 格式,并将其设置为日志条目的时间戳。
stage.timestamp {
source = "time"
format = "RFC3339"
}
以下示例将解析诸如 2024-12-20T09:14:58,381+02:00
的时间戳
stage.timestamp {
source = "time"
format = "2006-01-02T15:04:05,000-07:00"
}
导出的字段
以下字段已导出,可供其他组件引用
名称 | 类型 | 描述 |
---|---|---|
receiver | LogsReceiver | 其他组件可用于向其发送日志条目的值。 |
组件健康状况
仅当 loki.process
给定无效配置时,才报告为不健康。
调试信息
loki.process
不公开任何特定于组件的调试信息。
调试指标
loki_process_dropped_lines_total
(计数器):作为处理阶段一部分丢弃的行数。loki_process_dropped_lines_by_label_total
(计数器):当 stage.limit 中by_label_name
为非空时,丢弃的行数。
示例
此示例创建一个 loki.process
组件,该组件从 JSON 日志行中提取 environment
值,并将其设置为名为“env”的标签。
loki.process "local" {
forward_to = [loki.write.onprem.receiver]
stage.json {
expressions = { "extracted_env" = "environment" }
}
stage.labels {
values = { "env" = "extracted_env" }
}
}
兼容组件
loki.process
可以接受来自以下组件的参数
- 导出 Loki
LogsReceiver
的组件
loki.process
具有可以被以下组件使用的导出
- 使用 Loki
LogsReceiver
的组件
注意
连接某些组件可能不明智,或者组件可能需要进一步配置才能使连接正常工作。有关更多详细信息,请参阅链接的文档。