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 事件日志的 Message 字段中提取数据。 | 否 |
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 | 配置一个 structured metadata 处理阶段。 | 否 |
stage.template | 配置一个 template 处理阶段。 | 否 |
stage.tenant | 配置一个 tenant 处理阶段。 | 否 |
stage.timestamp | 配置一个 timestamp 处理阶段。 | 否 |
stage.windowsevent | 配置一个 windowsevent 处理阶段。 | 否 |
您可以在 loki.process
内部嵌套任意数量的这些 stage 块。这些块按照它们在配置文件中出现的顺序运行。
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 | int | 100 | 否 |
在内存中保存的最大部分行数。max_partial_line_size
仅在 max_partial_line_size_truncate
设置为 true
时生效。
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 条件,日志条目必须 *全部* 满足条件才会被丢弃。要丢弃满足 OR 条件的条目,请按顺序指定多个 drop
块。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
drop_counter_reason | string | string | 报告丢弃行的自定义原因。 | 否 |
"drop_stage" | string | expression | "" | 否 |
string | string | 有效的 RE2 正则表达式。 | "" | 否 |
longer_than | number | 如果指定,该阶段会丢弃大小超过配置值的行。 | "" | 否 |
older_than | string | duration | ";" | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | separator | "" | 否 |
string | string | 当 source 是逗号分隔的名称列表时,此分隔符会放在连接后的提取数据值之间。sourceName or comma-separated list of names from extracted data to match. If empty or not defined, it uses the log message.valueIf both source and value are specified, the stage drops lines where value exactly matches the source content. | "" | 否 |
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
已弃用,推荐使用 stage.windowsevent
块。
eventlogmessage
阶段从 Windows 事件日志中出现的 Message 字符串中提取数据。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
drop_invalid_labels | bool | bool | false | 否 |
是否丢弃无效标签名称的字段。 | bool | overwrite_existing | false | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | bool | 是否覆盖现有的提取数据字段。sourceName of the field in the extracted data to parse. | 否 |
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 | string | 是 | |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | Maxmind DB 文件的路径。sourceIP from extracted data to parse. | 是 | |
custom_lookups | map(string) | JMESPath 表达式的键值对。 | 否 | |
db_type | string | string | 否 |
Maxmind DB 类型。允许的值包括 "city"
, "asn"
, "country"
。
{"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 = "",
}
}
}
使用 City 数据库的 GeoIP 示例
json
阶段从日志行中的 client_ip
键提取 IP 地址。然后将提取的 ip
值作为 source 提供给 geoip
阶段。geoip
阶段对该 IP 进行查找,并在共享映射中填充以下字段,这些字段将使用 labels
阶段添加为标签。
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
此示例中使用的 IP 的提取数据
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 = "",
}
}
}
使用 ASN(自治系统号)数据库的 GeoIP 示例
json
阶段从日志行中的 client_ip
键提取 IP 地址。然后将提取的 ip
值作为 source 提供给 geoip
阶段。geoip
阶段对该 IP 进行查找,并在共享映射中填充以下字段,这些字段将使用 labels
阶段添加为标签。
geoip_autonomous_system_number: 396982
geoip_autonomous_system_organization: GOOGLE-CLOUD-PLATFORM
json
阶段从日志行中的 client_ip
键提取 IP 地址。然后将提取的 ip
值作为 source 提供给 geoip
阶段。geoip
阶段对该 IP 进行查找,并填充共享映射。
{"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 = "",
}
}
}
使用 City 数据库的 GeoIP 示例
json
阶段从日志行中的 client_ip
键提取 IP 地址。然后将提取的 ip
值作为 source 提供给 geoip
阶段。geoip
阶段对该 IP 进行查找,并在共享映射中填充以下字段,这些字段将使用 labels
阶段添加为标签。
geoip_country_name: United States
geoip_country_code: US
geoip_continent_name: North America
geoip_continent_code: NA
使用 Country 数据库的 GeoIP 示例
带有自定义字段的 GeoIP 示例
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 = "",
}
}
}
如果使用的 MMDB 文件富含自定义数据,例如 Maxmind 博客文章中解释的私有 IP 地址,则可以使用 custom_lookups
属性从记录中提取它们。json
阶段从日志行中的 client_ip
键提取 IP 地址。然后将提取的 ip
值作为 source 提供给 geoip
阶段。geoip
阶段对该 IP 进行查找,并使用来自城市数据库结果以及自定义查找的数据填充共享映射。最后,来自共享映射的自定义查找字段作为标签添加。
stage.json
stage.json
内部块配置一个 JSON 处理阶段,该阶段将传入的日志行或之前提取的值解析为 JSON,并使用 JMESPath 表达式从中提取新值。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
expressions | map(string) | JMESPath 表达式的键值对。 | 是 | |
map(string) | bool | 要运行的 JMESPath 表达式的键值对。drop_malformedDrop lines whose input can’t be parsed as valid JSON.sourceSource of the data to parse as JSON. | false | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | drop_malformed | "" | 否 |
bool
丢弃输入无法解析为有效 JSON 的行。sourceSource of the data to parse as JSON.
source
{"log":"log message\n","extra":"{\"user\":\"alloy\"}"}
loki.process "username" {
stage.json {
expressions = {output = "log", extra = ""}
}
stage.json {
source = "extra"
expressions = {username = "user"}
}
}
string
output: log message\n
extra: {"user": "alloy"}
要解析为 JSON 的数据源。expressionsThe expressions
field is the set of key-value pairs of JMESPath expressions to run. The map key defines the name with which the data is extracted, while the map value is the expression used to populate the value.
username: alloy
配置 JSON 阶段时,
source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。以下示例展示了给定的日志行和两个 JSON 阶段。
在此示例中,第一个阶段使用日志行作为源,并在共享映射中填充这些值。空表达式意味着使用与键相同的值,例如
extra="extra"
。第二个阶段使用
extra
中的值作为输入,并将以下键值对附加到提取数据集中。
- 注意
- 由于上游
jmespath
库的限制,您必须用引号将包含连字符-
的任何字符串括起来,以使其不被视为数字表达式。
stage.label_drop
如果您不使用引号来包装包含连字符的字符串,您将收到类似以下错误:Unexpected token at the end of the expression: tNumber
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
您可以使用以下两种方法之一来规避此问题 | 转义的双引号。例如: | 配置一个 label_drop 处理阶段。 | {} | 否 |
stage.label_drop {
values = [ "kubernetes_node_name", "kubernetes_namespace" ]
}
stage.label_keep
反引号。例如:http_user_agent = `"request_User-Agent"`
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
您可以使用以下两种方法之一来规避此问题 | 转义的双引号。例如: | 配置一个 label_keep 处理阶段。 | {} | 否 |
stage.label_keep {
values = [ "kubernetes_pod_name", "kubernetes_pod_container_name" ]
}
stage.labels
stage.label_drop
内部块配置一个处理阶段,该阶段从传入的日志条目中丢弃标签。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
您可以使用以下两种方法之一来规避此问题 | map(string) | 配置一个 labels 处理阶段。 | {} | 否 |
values
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
list(string)
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
要丢弃的标签集。 | number | stage.label_keep 内部块配置一个处理阶段,该阶段将传入日志条目的标签集过滤到一个子集中。 | 是 | |
values | number | list(string) | 是 | |
要保留的标签集。 | string | stage.labels 内部块配置一个 labels 处理阶段,该阶段可以从提取值映射中读取数据,并为传入的日志条目设置新标签。 | "" | 否 |
values | bool | map(string) | false | 否 |
在 labels 阶段,映射的键定义了要设置的标签,而值定义了如何查找它们。如果值为空,则推断其与键相同。 | number | stage.limit 内部块配置一个限速阶段,该阶段根据多个选项对日志进行节流。 | 10000 | 否 |
burst
stage.limit {
rate = 5
burst = 10
}
int
该阶段转发的最大突发行数。rateThe maximum rate of lines per second that the stage forwards.by_label_nameThe label to use when rate-limiting on a label name.dropWhether to discard or backpressure lines that exceed the rate limit.max_distinct_labelsThe number of unique values to keep track of when rate-limiting by_label_name
.
stage.limit {
rate = 10
burst = 10
drop = true
by_label_name = "namespace"
}
stage.logfmt
rate
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
number | map(string) | 该阶段每秒转发的最大行数速率。by_label_nameThe label to use when rate-limiting on a label name.dropWhether to discard or backpressure lines that exceed the rate limit.max_distinct_labelsThe number of unique values to keep track of when rate-limiting by_label_name . | 是 | |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | by_label_name | "" | 否 |
string
对标签名称进行限速时使用的标签。dropWhether to discard or backpressure lines that exceed the rate limit.max_distinct_labelsThe number of unique values to keep track of when rate-limiting by_label_name
.
drop
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"
}
bool
是否丢弃或施压超出限速的行。max_distinct_labelsThe number of unique values to keep track of when rate-limiting by_label_name
.
stage.luhn
max_distinct_labels
int
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
限速是一种大小为 burst 的“令牌桶”。它最初是满的,并以 rate 每秒填充令牌。每个收到的日志条目消耗桶中的一个令牌。当 drop 设置为 true 时,超出限速的传入条目会被丢弃,否则它们会排队等待更多令牌可用。对 by_label_name 进行限速时跟踪的唯一值数量。 | 如果设置了 | 以下示例独立地对每个唯一的 namespace 值对应的条目进行限速。任何没有 namespace 标签的条目都不会被限速。该阶段最多跟踪 max_distinct_labels 个唯一值,默认为 10000。 | 13 | 否 |
| string | mapping | map(string) | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 要提取的 logfmt 字段的键值对。sourceSource of the data to parse as logfmt . | "" | 否 |
source
string
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**"
}
source 字段定义要解析为 logfmt 的数据源。当 source
缺失或为空时,该阶段解析日志行本身,但它也可以用于解析之前提取的值。
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
此阶段使用 go-logfmt 解组器,因此数字或布尔类型会被解组为正确的形式。该阶段不执行任何其他类型转换。如果提取的值是复杂类型,则将其视为字符串。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
以下日志行和阶段演示了这是如何工作的。 | string | 第一个阶段解析日志行本身,并在提取数据集中插入 extra 键,其值为 user=example_name 。 | 是 | |
第二个阶段解析 | string | stage.luhn 内部块配置一个处理阶段,该阶段读取传入的日志行并对符合 Luhn 算法的字符串进行脱敏。 | Luhn 算法是一种简单的校验和公式,用于验证各种识别号码,例如信用卡号、IMEI 号码、美国国家提供商标识号以及加拿大社会保险号码。许多支付卡行业环境要求对这些号码进行脱敏。 | 否 |
drop_counter_reason | string | string | min_length | 否 |
int | string | 要考虑的最小数字长度 | "" | 否 |
配置 JSON 阶段时,
source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。replacement
string
用于替换匹配模式的字符串
source
{ "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"
}
string
source 字段定义要搜索的数据源。当 source
缺失或为空时,该阶段解析日志行本身,但它也可以用于解析之前提取的值。源数据。
以下示例日志行包含一个已批准的信用卡号。
该阶段解析日志行,对信用卡号进行脱敏,并生成以下更新后的日志行
stage.match
内部块配置一个过滤阶段,当日志条目匹配可配置的 LogQL 流选择器和过滤表达式时,可以选择性地应用一组嵌套的处理阶段或丢弃该条目。
stage.metrics
selector
string
要使用的 LogQL 流选择器和行过滤表达式。
块 | 描述 | 必需 |
---|---|---|
action | string | 否 |
当选择器匹配日志行时要执行的操作。支持的值包括 | "keep" | 否 |
drop_counter_reason | string | 否 |
配置 JSON 阶段时,
source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。丢弃行时报告的自定义原因。
action
pipeline_name
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
第二个阶段解析 | string | string | 是 | |
嵌套管道使用的自定义名称。 | string | 过滤器不包含标签过滤表达式,例如 | label == "examplelabel" 。 | 是 | |
| bool | 如果指定的 action 是 "drop" ,则每丢弃一行,指标 loki_process_dropped_lines_total 都会增加。默认情况下,原因标签是 "match_stage" ,但可以使用 drop_counter_reason 参数提供自定义原因。 | false | 否 |
以下示例日志行和阶段展示了这是如何工作的。 | string | 前两个阶段将日志行解析为 JSON,将 app 值解码到共享提取映射中作为 appname ,并将其值用作 applbl 标签。 | "" | 否 |
第三个阶段使用 LogQL 选择器,仅在 | bool | 第四个阶段使用 LogQL 选择器,仅在 applbl="qux" 的行上执行。这意味着它不会匹配任何输入,嵌套的 JSON 阶段也不会运行。 | false | 否 |
第五个阶段丢弃 | number | 最后的 output 阶段将日志行的内容更改为提取映射中 msg 的值。在此示例中,第一个日志条目的内容被更改为 app1 log line 。 |
| 否 |
| string | stage.metrics 定义内部支持以下块 | metric.counter | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 定义一个 counter 指标。 | "" | 否 |
string | string | metric.gauge | "" | 否 |
定义一个 gauge 指标。
当选择器匹配日志行时要执行的操作。支持的值包括 "keep"
和 "drop"
"keep"
和 "drop"
metric.histogram
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
第二个阶段解析 | string | 定义一个 histogram 指标。 | 是 | |
嵌套管道使用的自定义名称。 | string | 过滤器不包含标签过滤表达式,例如 | label == "examplelabel" 。 | 是 | |
以下示例日志行和阶段展示了这是如何工作的。 | string | 前两个阶段将日志行解析为 JSON,将 app 值解码到共享提取映射中作为 appname ,并将其值用作 applbl 标签。 | "" | 否 |
第五个阶段丢弃 | number | 最后的 output 阶段将日志行的内容更改为提取映射中 msg 的值。在此示例中,第一个日志条目的内容被更改为 app1 log line 。 |
| 否 |
| string | stage.metrics 定义内部支持以下块 | metric.counter | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 定义一个 counter 指标。 | "" | 否 |
string | string | metric.gauge | "" | 否 |
如果您重新加载 Alloy 配置文件,指标将被重置。
drop_counter_reason
定义一个值只增加的指标。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
action | string | 要执行的操作。有效操作包括 inc 和 add 。 | 是 | |
嵌套管道使用的自定义名称。 | string | 过滤器不包含标签过滤表达式,例如 | label == "examplelabel" 。 | 是 | |
以下示例日志行和阶段展示了这是如何工作的。 | string | 前两个阶段将日志行解析为 JSON,将 app 值解码到共享提取映射中作为 appname ,并将其值用作 applbl 标签。 | "" | 否 |
第五个阶段丢弃 | number | 最后的 output 阶段将日志行的内容更改为提取映射中 msg 的值。在此示例中,第一个日志条目的内容被更改为 app1 log line 。 |
| 否 |
| string | stage.metrics 定义内部支持以下块 | metric.counter | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 定义一个 counter 指标。 | "" | 否 |
string | string | metric.gauge | "" | 否 |
name
string
指标名称。
count_entry_bytes
- bool
- 如果设置为 true,则计算所有日志行的字节数。
- description
- string
- 指标的描述和帮助文本。
- match_all
- bool
- 如果设置为 true,则计算所有日志行,而不尝试将 source 与提取映射匹配。
max_idle_duration
duration
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"
}
}
在指标被标记为“过期”并移除之前等待的最长时间。
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"
}
}
"5m"
stage.regex {
expression = "^.* retries=(?P<retries>\\d+) .*$"
}
stage.metrics {
metric.gauge {
name = "retries_total"
description = "total_retries"
source = "retries"
action = "add"
}
}
prefix
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
string
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
指标名称的前缀。 | string | "loki_process_custom_" | 是 | |
source | number | string | 128 | 否 |
用于指标的提取数据映射中的键。默认为指标名称。 | number | value | string | 否 |
如果设置,指标仅在 source 与 value 完全匹配时才更改。
counter 不能同时将 match_all
设置为 true 和设置一个 value
。counter 不能在未设置 match_all=true
或 action=add
的情况下设置 count_entry_bytes
。有效的 action
值是 inc
和 add
。inc
操作对每条通过过滤器的日志行将指标值增加 1。add
操作将提取的值转换为正浮点数并将其添加到指标。
定义一个值可以增加或减少的 gauge 指标。
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 -
action
stage.output
string
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | "loki_process_custom_" | 是 |
要执行的操作。有效操作包括 inc
, dec
, set
, add
, 或 sub
。
{"user": "John Doe", "message": "hello, world!"}
stage.json {
expressions = { "user" = "user", "message" = "message" }
}
stage.labels {
values = { "user" = "user" }
}
stage.output {
source = "message"
}
name
user: John Doe
message: hello, world!
string
stage.pack
指标名称。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
prefix | 转义的双引号。例如: | string | 是 | |
指标名称的前缀。 | bool | "loki_process_custom_" | source | 否 |
string
用于指标的提取数据映射中的键。默认为指标名称。
value
log_line: "something went wrong"
labels: { "level" = "error", "env" = "dev", "user_id" = "f8fas0r" }
string
stage.pack {
labels = ["env", "user_id"]
}
如果设置,指标仅在 source 与 value 完全匹配时才更改。
{
"_entry": "something went wrong",
"env": "dev",
"user_id": "f8fas0r"
}
定义一个 histogram 指标,其值记录在预定义的桶中。
buckets
stage.regex
stage.regex
内部块配置了一个处理阶段,它使用正则表达式解析日志行,并使用命名捕获组将数据添加到共享的提取值映射中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
"drop_stage" | string | 有效的 RE2 正则表达式。每个捕获组都必须命名。 | 是 | |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 从提取的数据中解析的名称。如果为空,则使用日志消息。 | "" | 否 |
expression
字段需要是 RE2 正则表达式字符串。每个匹配的捕获组都会添加到提取映射中,因此必须命名,例如:(?P<name>re)
。然后,捕获组的名称将用作提取映射中匹配值的键。
由于 Alloy 语法字符串的工作方式,expression
中的任何反斜杠都必须用双反斜杠转义,例如,"\\w"
或 "\\S+"
。
如果 source
为空或缺失,则该阶段解析日志行本身。如果设置了 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
值,则正则表达式将应用于存储在共享映射中该名称下的值。
以下日志行通过此两阶段管道处理
{"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
然后,正则表达式阶段从共享值中解析时间值,并将随后的键值对附加回提取值映射中
year: 2022
stage.replace
stage.replace
内部块配置了一个阶段,它使用正则表达式解析日志行并替换日志行内容。正则表达式中的命名捕获组也支持将数据添加到共享的提取映射中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
"drop_stage" | string | 包含捕获组的 RE2 正则表达式。 | 是 | |
替换 | string | 被捕获组替换的值。 | 否 | |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | 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% 的日志将被丢弃。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
values | 浮点数 | 采样率,范围为 [0, 1] | 是 | |
drop_counter_reason | string | 当日志被此阶段丢弃时,要添加到 loki_process_dropped_lines_total 指标的标签。 | 采样阶段 | 否 |
例如,以下配置将对 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 处理阶段,该阶段为传入的日志条目添加一组静态标签。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
您可以使用以下两种方法之一来规避此问题 | map(string) | 配置一个 static_labels 处理阶段。 | {} | 否 |
stage.static_labels {
values = {
foo = "fooval",
bar = "barval",
}
}
stage.structured_metadata
stage.structured_metadata
内部块配置了一个阶段,该阶段可以从提取值映射中读取数据并将其作为结构化元数据添加到日志条目中。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
您可以使用以下两种方法之一来规避此问题 | 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
包语法来操作提取映射中的值。此阶段主要用于在后续阶段将先前阶段的数据设置为标签之前对其进行操作和标准化。示例用例包括将空格替换为下划线、将大写字符串转换为小写或哈希值。
template 阶段还可以在提取映射中创建新的键。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 从提取数据中解析的名称。如果键不存在,则创建新条目。 | 是 | |
模板 | string | 要使用的 Go 模板字符串。 | 是 |
模板字符串可以是 Go 的 text/template
可以使用的任何有效模板。它支持 sprig 包中的所有函数,以及以下自定义函数列表
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 包中的所有函数外,template
阶段还支持以下自定义函数。
ToLower
和 ToUpper
ToLower
和 ToUpper
分别将整个字符串转换为小写和大写。
以下示例展示了如何使用此函数。
stage.template {
source = "out"
template = "{{ ToLower .app }}"
}
stage.template {
source = "out"
template = "{{ .app | ToUpper }}"
}
替换
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
返回输入字符串的副本,将正则表达式的匹配项替换为替换字符串。在替换字符串内部,$
字符的解释方式与 Expand 函数中相同。例如,$1 代表第一个捕获的子匹配项。
regexReplaceAllLiteral
返回输入字符串的副本,将正则表达式的匹配项替换为替换字符串。替换字符串被直接替换,不使用 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)。它需要一个(固定)盐值,以增加低输入域的复杂性,例如,所有可能的社会安全号码。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。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
标签 | string | 设置为租户 ID 的标签。 | "" | 否 |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 用作租户 ID 的提取值的名称。 | "" | 否 |
string | 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 {
values = {
"namespace" = "k8s_namespace",
}
}
stage.tenant {
label = "namespace"
}
stage.timestamp
stage.timestamp
内部块配置了一个处理阶段,用于在日志条目转发到下一个组件之前设置其时间戳。如果未设置 timestamp 阶段,日志条目的时间戳默认为抓取日志条目的时间。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
格式 | string | 确定如何解析源字符串。 | 是 | |
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | 从提取值映射中用于时间戳的名称。 | 是 | |
失败时的操作 | string | 当无法提取或解析时间戳时应执行的操作。 | "fudge" | 否 |
回退格式 | 转义的双引号。例如: | 如果 format 字段解析失败时尝试的回退格式。 | [] | 否 |
位置 | string | 解析时使用的 IANA 时区数据库位置。 | "" | 否 |
配置 JSON 阶段时,
source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。请注意后续可能也会覆盖时间戳的阶段。例如,一个设置了
ingest_timestamp
为true
的stage.pack
可能会替换流水线中较早由stage.timestamp
设置的时间戳。
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 |
配置 JSON 阶段时,
source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。如果您定义自定义时间戳,则每个时间戳组件的
format
值必须是上表中指定的值之一。例如,要表示年份,format
值必须是06
或2006
,而不是其他任何值,例如23
或2023
。
fallback_formats
字段定义了一个或多个格式字段,以便在使用 format
解析失败时尝试使用它们来解析时间戳。
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"
}
stage.windowsevent
windowsevent
阶段从 Windows 事件日志中的消息字符串中提取数据。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。 | string | bool | 是否覆盖现有的提取数据字段。sourceName of the field in the extracted data to parse. | 否 |
drop_invalid_labels | bool | bool | false | 否 |
是否丢弃无效标签名称的字段。 | bool | overwrite_existing | false | 否 |
当 drop_invalid_labels
设置为 true
时,该阶段会丢弃无效标签名称的字段。如果设置为 false
,该阶段会自动将它们转换为有效的标签,用下划线替换无效字符。当 overwrite_existing
设置为 true
时,该阶段会覆盖同名的现有提取数据字段。如果设置为 false
,则 _extracted
后缀会附加到现有字段名称。
当 drop_invalid_labels
设置为 true
时,该阶段会丢弃不是有效标签名称的字段。如果设置为 false
,该阶段会自动将它们转换为有效标签,将无效字符替换为下划线。
windowsevent
阶段期望消息以空行分隔成多个部分。
输入的第一部分被视为一个整体块,并以键 Description
存储在提取映射中。
Description 后面的部分应包含 key:value 格式的键值对。
如果某个部分的第一行没有值,例如“Subject:”,则该键将作为同一部分后续键的前缀。
如果某个部分中的行不包含 :
符号,则将其视为前一个条目值的一部分。该行将附加到前一个值,用逗号分隔。
部分中没有前导有效条目(键值对)的行将被忽略和丢弃。
loki.source.windowsevent
示例
loki.source.windowsevent "security" {
eventlog_name = "Security"
forward_to = [loki.process.default.receiver]
}
loki.process "default" {
forward_to = [loki.write.default.receiver]
stage.json {
expressions = {
message = "",
Overwritten = "",
}
}
stage.windowsevent {
source = "message"
overwrite_existing = true
}
stage.labels {
values = {
Description = "",
Subject_SecurityID = "",
ReadOP = "Subject_ReadOperation",
}
}
}
loki.source.windowsevent
组件将 Windows 安全事件转发到 loki.process
组件。
假定以下事件
{"event_id": 1, "Overwritten": "old", "message": ""Special privileges assigned to new logon.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-1-1-1\r\n\tAccount Name:\t\tSYSTEM\r\n\tAccount Domain:\t\tNT AUTHORITY\r\n\tLogon ID:\t\t0xAAA\r\n\r\nPrivileges:\t\tSeAssignPrimaryTokenPrivilege\r\n\t\t\tSeTcbPrivilege\r\n\t\t\tSeSecurityPrivilege\r\n\t\t\tSeTakeOwnershipPrivilege\r\n\t\t\tSeLoadDriverPrivilege\r\n\t\t\tSeBackupPrivilege\r\n\t\t\tSeRestorePrivilege\r\n\t\t\tSeDebugPrivilege\r\n\t\t\tSeAuditPrivilege\r\n\t\t\tSeSystemEnvironmentPrivilege\r\n\t\t\tSeImpersonatePrivilege\r\n\t\t\tSeDelegateSessionUserImpersonatePrivilege""}
json
阶段将在提取数据集中创建以下键值对
message
: 其值为"Special privileges assigned to new logon.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-1-1-1\r\n\tAccount Name:\t\tSYSTEM\r\n\tAccount Domain:\t\tNT AUTHORITY\r\n\tLogon ID:\t\t0xAAA\r\n\r\nPrivileges:\t\tSeAssignPrimaryTokenPrivilege\r\n\t\t\tSeTcbPrivilege\r\n\t\t\tSeSecurityPrivilege"
Overwritten
:old
windowsevent
阶段从提取数据中解析 message
的值,并将以下键值对附加或覆盖到提取数据集中
Description
: “Special privileges assigned to new logon.”,Subject_SecurityID
: “S-1-1-1”,Subject_AccountName
: “SYSTEM”,Subject_AccountDomain
: “NT AUTHORITY”,Subject_LogonID
: “0xAAA”,Privileges
: “SeAssignPrimaryTokenPrivilege,SeTcbPrivilege,SeSecurityPrivilege”,
最后,labels
阶段使用提取的值 Description
、Subject_SecurityID
和 Subject_ReadOperation
将它们作为日志条目的标签,然后再将其转发到 loki.write
组件。
导出的字段
以下字段被导出,可供其他组件引用
名称 | 类型 | 描述 |
---|---|---|
接收器 | 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
的组件
配置 JSON 阶段时,
source
字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。连接某些组件可能没有意义,或者组件可能需要进一步配置才能使连接正常工作。有关更多详细信息,请参阅链接的文档。