菜单
正式可用 (GA) 开源

loki.process

loki.process 接收来自其他 loki 组件的日志条目,应用一个或多个处理*阶段*,并将结果转发到组件参数中指定的接收器列表。

阶段是一种多用途工具,可以在日志条目传递到下游组件之前对其进行解析、转换和过滤。这些阶段按照它们在配置文件中出现的顺序应用于每个日志条目。loki.process 块内的所有阶段都可以访问日志条目的标签集、日志行、日志时间戳,以及一个共享的“提取”值映射,以便一个阶段的结果可以在后续阶段中使用。

您可以通过为多个 loki.process 组件提供不同的标签来指定它们。

用法

alloy
loki.process "<LABEL>" {
  forward_to = <RECEIVER_LIST>

  stage.<STAGENAME> {
    ...
  }
  ...
}

参数

您可以将以下参数与 loki.process 一起使用

名称类型描述默认值必需
forward_tolist(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_truncatebool截断长度超过 max_partial_line_size 的部分行。false
max_partial_line_sizenumber部分行可以包含的最大字符数。0
max_partial_linesnumberint100

在内存中保存的最大部分行数。max_partial_line_size 仅在 max_partial_line_size_truncate 设置为 true 时生效。

alloy
stage.cri {}

CRI 将日志行指定为以单个空格分隔的值,包含以下组件

  • time:日志的时间戳字符串。
  • stream:stdout 或 stderr。
  • flags:CRI 标志,包括 F 或 P。
  • log:日志行的内容。

给定以下日志行,将在提取数据的共享映射中创建后续的键值对

text
"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 块不支持任何参数或内部块,因此它总是空的。

alloy
stage.decolorize {}

stage.decolorize 将每条带有颜色代码的行转换为无颜色的行。例如

text
[2022-11-04 22:17:57.811] \033[0;32http\033[0m: GET /_health (0 ms) 204

转换为

text
[2022-11-04 22:17:57.811] http: GET /_health (0 ms) 204

stage.docker

stage.docker 内部块启用一个预定义的管道,该管道读取标准 Docker 日志文件格式的日志行。

stage.docker 块不支持任何参数或内部块,因此它总是空的。

alloy
stage.docker {}

Docker 日志条目格式为 JSON,包含以下键

  • log:日志行的内容。
  • stream:stdout 或 stderr。
  • time:日志行的时间戳字符串。

给定以下日志行,将在提取数据的共享映射中创建后续的键值对

text
{"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_reasonstringstring报告丢弃行的自定义原因。
"drop_stage"stringexpression""
stringstring有效的 RE2 正则表达式。""
longer_thannumber如果指定,该阶段会丢弃大小超过配置值的行。""
older_thanstringduration";"
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。stringseparator""
stringstringsource 是逗号分隔的名称列表时,此分隔符会放在连接后的提取数据值之间。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 的日志条目。

alloy
stage.drop {
    expression  = ".*debug.*"
    longer_than = "1KB"
}

以下示例定义了多个 drop 块,因此 loki.process 会丢弃早于或等于 24 小时前的条目、长于 8KB 的条目,*或者* app 的提取值等于 example 的条目。

alloy
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_labelsboolboolfalse
是否丢弃无效标签名称的字段。booloverwrite_existingfalse
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。stringbool是否覆盖现有的提取数据字段。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 结合使用的示例

alloy
stage.json {
    expressions = {
        message = "",
        Overwritten = "",
    }
}

stage.eventlogmessage {
    source = "message"
    overwrite_existing = true
}

给定以下日志行

text
{"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 数据库。

支持以下参数

名称类型描述默认值必需
dbstringstring
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。stringMaxmind DB 文件的路径。sourceIP from extracted data to parse.
custom_lookupsmap(string)JMESPath 表达式的键值对。
db_typestringstring

Maxmind DB 类型。允许的值包括 "city", "asn", "country"

alloy
{"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 阶段添加为标签。

text
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 的提取数据

alloy
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 阶段添加为标签。

text
geoip_autonomous_system_number: 396982
geoip_autonomous_system_organization: GOOGLE-CLOUD-PLATFORM

json 阶段从日志行中的 client_ip 键提取 IP 地址。然后将提取的 ip 值作为 source 提供给 geoip 阶段。geoip 阶段对该 IP 进行查找,并填充共享映射。

alloy
{"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 阶段添加为标签。

text
geoip_country_name: United States
geoip_country_code: US
geoip_continent_name: North America
geoip_continent_code: NA

使用 Country 数据库的 GeoIP 示例

带有自定义字段的 GeoIP 示例

alloy
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 表达式从中提取新值。

支持以下参数

名称类型描述默认值必需
expressionsmap(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
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。stringdrop_malformed""

bool

丢弃输入无法解析为有效 JSON 的行。sourceSource of the data to parse as JSON.

source

alloy
{"log":"log message\n","extra":"{\"user\":\"alloy\"}"}

loki.process "username" {
  stage.json {
      expressions = {output = "log", extra = ""}
  }

  stage.json {
      source      = "extra"
      expressions = {username = "user"}
  }
}

string

text
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.

text
username: alloy

配置 JSON 阶段时,source 字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。

以下示例展示了给定的日志行和两个 JSON 阶段。

在此示例中,第一个阶段使用日志行作为源,并在共享映射中填充这些值。空表达式意味着使用与键相同的值,例如 extra="extra"

第二个阶段使用 extra 中的值作为输入,并将以下键值对附加到提取数据集中。

  1. 注意
  2. 由于上游 jmespath 库的限制,您必须用引号将包含连字符 - 的任何字符串括起来,以使其不被视为数字表达式。

stage.label_drop

如果您不使用引号来包装包含连字符的字符串,您将收到类似以下错误:Unexpected token at the end of the expression: tNumber

支持以下参数

名称类型描述默认值必需
您可以使用以下两种方法之一来规避此问题转义的双引号。例如:http_user_agent = "\"request_User-Agent\""配置一个 label_drop 处理阶段。{}
alloy
stage.label_drop {
    values = [ "kubernetes_node_name", "kubernetes_namespace" ]
}

stage.label_keep

反引号。例如:http_user_agent = `"request_User-Agent"`

支持以下参数

名称类型描述默认值必需
您可以使用以下两种方法之一来规避此问题转义的双引号。例如:http_user_agent = "\"request_User-Agent\""配置一个 label_keep 处理阶段。{}
alloy
stage.label_keep {
    values = [ "kubernetes_pod_name", "kubernetes_pod_container_name" ]
}

stage.labels

stage.label_drop 内部块配置一个处理阶段,该阶段从传入的日志条目中丢弃标签。

支持以下参数

名称类型描述默认值必需
您可以使用以下两种方法之一来规避此问题map(string)配置一个 labels 处理阶段。{}

values

alloy
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)

支持以下参数

名称类型描述默认值必需
要丢弃的标签集。numberstage.label_keep 内部块配置一个处理阶段,该阶段将传入日志条目的标签集过滤到一个子集中。
valuesnumberlist(string)
要保留的标签集。stringstage.labels 内部块配置一个 labels 处理阶段,该阶段可以从提取值映射中读取数据,并为传入的日志条目设置新标签。""
valuesboolmap(string)false
在 labels 阶段,映射的键定义了要设置的标签,而值定义了如何查找它们。如果值为空,则推断其与键相同。numberstage.limit 内部块配置一个限速阶段,该阶段根据多个选项对日志进行节流。10000

burst

alloy
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.

alloy
stage.limit {
    rate  = 10
    burst = 10
    drop  = true

    by_label_name = "namespace"
}

stage.logfmt

rate

支持以下参数

名称类型描述默认值必需
numbermap(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.
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。stringby_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

alloy
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 进行限速时跟踪的唯一值数量。如果设置了 by_label_name,则 drop 必须设置为 true。这使得该阶段可以按标签数量而不是行数量进行限速。以下示例独立地对每个唯一的 namespace 值对应的条目进行限速。任何没有 namespace 标签的条目都不会被限速。该阶段最多跟踪 max_distinct_labels 个唯一值,默认为 10000。13
stage.logfmt 内部块配置一个处理阶段,该阶段将传入的日志行读取为 logfmt 格式并从中提取值。stringmappingmap(string)
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。string要提取的 logfmt 字段的键值对。sourceSource of the data to parse as logfmt.""

source

string

alloy
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 缺失或为空时,该阶段解析日志行本身,但它也可以用于解析之前提取的值。

text
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
第二个阶段解析 extra 的内容,并将 username: example_name 键值对附加到提取数据集中。stringstage.luhn 内部块配置一个处理阶段,该阶段读取传入的日志行并对符合 Luhn 算法的字符串进行脱敏。Luhn 算法是一种简单的校验和公式,用于验证各种识别号码,例如信用卡号、IMEI 号码、美国国家提供商标识号以及加拿大社会保险号码。许多支付卡行业环境要求对这些号码进行脱敏。
drop_counter_reasonstringstringmin_length
intstring要考虑的最小数字长度""

配置 JSON 阶段时,source 字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。

replacement

string

用于替换匹配模式的字符串

source

alloy
{ "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 流选择器和行过滤表达式。

描述必需
actionstring
当选择器匹配日志行时要执行的操作。支持的值包括 "keep""drop""keep"
drop_counter_reasonstring

配置 JSON 阶段时,source 字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。

丢弃行时报告的自定义原因。

action

pipeline_name

支持以下参数

名称类型描述默认值必需
第二个阶段解析 extra 的内容,并将 username: example_name 键值对附加到提取数据集中。stringstring
嵌套管道使用的自定义名称。string过滤器不包含标签过滤表达式,例如 | label == "examplelabel"
stage.match 块支持多个 stage.* 内部块,与顶级块类似。这些内部块用于构建如果选择器匹配日志条目的标签和内容时要运行的嵌套阶段集。它支持 loki.process 组件顶级中所有相同的 stage.NAME 块。bool如果指定的 action 是 "drop",则每丢弃一行,指标 loki_process_dropped_lines_total 都会增加。默认情况下,原因标签是 "match_stage",但可以使用 drop_counter_reason 参数提供自定义原因。false
以下示例日志行和阶段展示了这是如何工作的。string前两个阶段将日志行解析为 JSON,将 app 值解码到共享提取映射中作为 appname,并将其值用作 applbl 标签。""
第三个阶段使用 LogQL 选择器,仅在 applbl="examplelabel" 的行上执行嵌套阶段。因此,对于第一行,嵌套的 JSON 阶段会在提取映射中添加 msg="app1 log line"bool第四个阶段使用 LogQL 选择器,仅在 applbl="qux" 的行上执行。这意味着它不会匹配任何输入,嵌套的 JSON 阶段也不会运行。false
第五个阶段丢弃 applbl 设置为 'example2' 且行内容匹配正则表达式 .*noisy error.* 的日志条目。它还会增加 loki_process_dropped_lines_total 指标,标签 drop_counter_reason="discard_noisy_errors"number最后的 output 阶段将日志行的内容更改为提取映射中 msg 的值。在此示例中,第一个日志条目的内容被更改为 app1 log linestage.metrics 内部块配置一个阶段,允许您根据共享提取映射中的值定义和更新指标。创建的指标可在 Alloy 根目录的 /metrics 端点访问。
stage.metrics 块不支持任何参数,仅通过多个嵌套的内部 metric.* 块进行配置,每个块对应一个应生成的指标。stringstage.metrics 定义内部支持以下块metric.counter
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。string定义一个 counter 指标。""
stringstringmetric.gauge""

定义一个 gauge 指标。

当选择器匹配日志行时要执行的操作。支持的值包括 "keep""drop"

metric.histogram

支持以下参数

名称类型描述默认值必需
第二个阶段解析 extra 的内容,并将 username: example_name 键值对附加到提取数据集中。string定义一个 histogram 指标。
嵌套管道使用的自定义名称。string过滤器不包含标签过滤表达式,例如 | label == "examplelabel"
以下示例日志行和阶段展示了这是如何工作的。string前两个阶段将日志行解析为 JSON,将 app 值解码到共享提取映射中作为 appname,并将其值用作 applbl 标签。""
第五个阶段丢弃 applbl 设置为 'example2' 且行内容匹配正则表达式 .*noisy error.* 的日志条目。它还会增加 loki_process_dropped_lines_total 指标,标签 drop_counter_reason="discard_noisy_errors"number最后的 output 阶段将日志行的内容更改为提取映射中 msg 的值。在此示例中,第一个日志条目的内容被更改为 app1 log linestage.metrics 内部块配置一个阶段,允许您根据共享提取映射中的值定义和更新指标。创建的指标可在 Alloy 根目录的 /metrics 端点访问。
stage.metrics 块不支持任何参数,仅通过多个嵌套的内部 metric.* 块进行配置,每个块对应一个应生成的指标。stringstage.metrics 定义内部支持以下块metric.counter
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。string定义一个 counter 指标。""
stringstringmetric.gauge""

如果您重新加载 Alloy 配置文件,指标将被重置。

drop_counter_reason

定义一个值只增加的指标。

支持以下参数

名称类型描述默认值必需
actionstring要执行的操作。有效操作包括 incadd
嵌套管道使用的自定义名称。string过滤器不包含标签过滤表达式,例如 | label == "examplelabel"
以下示例日志行和阶段展示了这是如何工作的。string前两个阶段将日志行解析为 JSON,将 app 值解码到共享提取映射中作为 appname,并将其值用作 applbl 标签。""
第五个阶段丢弃 applbl 设置为 'example2' 且行内容匹配正则表达式 .*noisy error.* 的日志条目。它还会增加 loki_process_dropped_lines_total 指标,标签 drop_counter_reason="discard_noisy_errors"number最后的 output 阶段将日志行的内容更改为提取映射中 msg 的值。在此示例中,第一个日志条目的内容被更改为 app1 log linestage.metrics 内部块配置一个阶段,允许您根据共享提取映射中的值定义和更新指标。创建的指标可在 Alloy 根目录的 /metrics 端点访问。
stage.metrics 块不支持任何参数,仅通过多个嵌套的内部 metric.* 块进行配置,每个块对应一个应生成的指标。stringstage.metrics 定义内部支持以下块metric.counter
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。string定义一个 counter 指标。""
stringstringmetric.gauge""

name

string

指标名称。

count_entry_bytes

  • bool
  • 如果设置为 true,则计算所有日志行的字节数。
  • description
    • string
    • 指标的描述和帮助文本。
  • match_all
    • bool
    • 如果设置为 true,则计算所有日志行,而不尝试将 source 与提取映射匹配。

max_idle_duration

duration

alloy
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"
    }
}

在指标被标记为“过期”并移除之前等待的最长时间。

alloy
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"

alloy
stage.regex {
    expression = "^.* retries=(?P<retries>\\d+) .*$"
}
stage.metrics {
    metric.gauge {
        name        = "retries_total"
        description = "total_retries"
        source      = "retries"
        action      = "add"
    }
}

prefix

alloy
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_"
sourcenumberstring128
用于指标的提取数据映射中的键。默认为指标名称。numbervaluestring

如果设置,指标仅在 source 与 value 完全匹配时才更改。

counter 不能同时将 match_all 设置为 true 和设置一个 value。counter 不能在未设置 match_all=trueaction=add 的情况下设置 count_entry_bytes。有效的 action 值是 incaddinc 操作对每条通过过滤器的日志行将指标值增加 1。add 操作将提取的值转换为正浮点数并将其添加到指标。

定义一个值可以增加或减少的 gauge 指标。

text
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

alloy
{"user": "John Doe", "message": "hello, world!"}

stage.json {
    expressions = { "user" = "user", "message" = "message" }
}

stage.labels {
    values = { "user" = "user" }
}

stage.output {
    source = "message"
}

name

text
user: John Doe
message: hello, world!

string

stage.pack

指标名称。

支持以下参数

名称类型描述默认值必需
prefix转义的双引号。例如:http_user_agent = "\"request_User-Agent\""string
指标名称的前缀。bool"loki_process_custom_"source

string

用于指标的提取数据映射中的键。默认为指标名称。

value

text
log_line: "something went wrong"
labels:   { "level" = "error", "env" = "dev", "user_id" = "f8fas0r" }

string

alloy
stage.pack {
    labels = ["env", "user_id"]
}

如果设置,指标仅在 source 与 value 完全匹配时才更改。

有效的 action 值是 inc, dec, set, add, 或 subincdec 分别将指标的值增加和减少 1。如果选择 set, add, 或 sub,则提取的值必须可转换为正浮点数,并用于设置、添加到或从指标值中减去。
{
  "_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,则该阶段会解析之前提取的同名值。

假定有以下日志行和正则表达式阶段,提取的值如下所示

alloy
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 值,则正则表达式将应用于存储在共享映射中该名称下的值。

以下日志行通过此两阶段管道处理

alloy
{"timestamp":"2022-01-01T01:00:00.000000001Z"}

stage.json {
    expressions = { time = "timestamp" }
}
stage.regex {
    expression = "^(?P<year>\\d+)"
    source     = "time"
}

第一阶段将以下键值对添加到提取映射中

text
time: 2022-01-01T01:00:00.000000001Z

然后,正则表达式阶段从共享值中解析时间值,并将随后的键值对附加回提取值映射中

text
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 被省略,替换发生在日志行本身。

alloy
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    = "*****"
}

日志行被转换为

text
2023-01-01T01:00:00.000000001Z stderr P i'm a log message who has sensitive information with password *****!

如果 replace 为空,则捕获的值将被省略。

在以下示例中,定义了 source

alloy
{"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 阶段将在提取数据集中创建以下键值对

text
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 值最终转换为

text
msg: "11.11.11.11 - "POST redacted_url HTTP/1.1" 200 932 "-" "Mozilla/5.0"

replace 字段可以使用一组模板函数,通过利用 Go 的 text/template 包来实现。

以下示例展示了如何将此与命名捕获组以及示例日志行和阶段结合使用。

alloy
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 字段作用于这些提取的值并将它们转换为大写

text
ip: 11.11.11.11
identd: -
user: FRANK
timestamp: 01/JAN/2023:00:00:01 +0200

日志行变为

text
11.11.11.11 - FRANK [01/JAN/2023:00:00:01 +0200]

以下列表包含可用函数以及更复杂的 replace 字段示例。

text
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_reasonstring当日志被此阶段丢弃时,要添加到 loki_process_dropped_lines_total 指标的标签。采样阶段

例如,以下配置将对 25% 的日志进行采样,丢弃剩余的 75%。当日志被丢弃时,loki_process_dropped_lines_total 指标会增加,并带有额外的 reason=logs_sampling 标签。

alloy
stage.sampling {
    rate = 0.25
    drop_counter_reason = "logs_sampling"
}

stage.static_labels

stage.static_labels 内部块配置了一个 static_labels 处理阶段,该阶段为传入的日志条目添加一组静态标签。

支持以下参数

名称类型描述默认值必需
您可以使用以下两种方法之一来规避此问题map(string)配置一个 static_labels 处理阶段。{}
alloy
stage.static_labels {
    values = {
      foo = "fooval",
      bar = "barval",
    }
}

stage.structured_metadata

stage.structured_metadata 内部块配置了一个阶段,该阶段可以从提取值映射中读取数据并将其作为结构化元数据添加到日志条目中。

支持以下参数

名称类型描述默认值必需
您可以使用以下两种方法之一来规避此问题map(string)指定从提取值映射添加到日志条目的标签列表。{}

structured_metadata 阶段中,映射的键定义了要设置的标签,值定义了如何查找它们。如果值为空,则推断其与键相同。

alloy
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 包中的所有函数,以及以下自定义函数列表

text
ToLower, ToUpper, Replace, Trim, TrimLeftTrimRight, TrimPrefix, TrimSuffix, TrimSpace, Hash, Sha2Hash, regexReplaceAll, regexReplaceAllLiteral

有关每个函数的更多详细信息,请参阅 支持的函数 部分。

假设提取映射中没有数据,以下阶段只需将 new_key: "hello_world" 键值对添加到共享映射中。

alloy
stage.template {
    source   = "new_key"
    template = "hello_world"
}

如果提取字段中存在 source 值,则可以在模板中将其引用为 .Value。下一阶段从提取映射中获取 app 的当前值,将其转换为小写,并为其值添加后缀

alloy
stage.template {
    source   = "app"
    template = "{{ ToLower .Value }}_some_suffix"
}

任何先前提取的键都可以用于 template 扩展和使用。下一阶段获取 levelappmodule 的当前值,并创建一个名为 output_message 的新键

alloy
stage.template {
    source   = "output_msg"
    template = "{{ .level }} for app {{ ToUpper .app }} in module {{.module}}"
}

可以使用名为 Entry 的特殊键来引用当前行。当您需要向日志行附加/前置内容时,这很有用,如下面的代码片段所示

alloy
stage.template {
    source   = "message"
    template = "{{.app }}: {{ .Entry }}"
}
stage.output {
    source = "message"
}

支持的函数

除了支持 sprig 包中的所有函数外,template 阶段还支持以下自定义函数。

ToLowerToUpper

ToLowerToUpper 分别将整个字符串转换为小写和大写。

以下示例展示了如何使用此函数。

alloy
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

alloy
stage.template {
    source   = "output"
    template = `{{ Replace .Value "loki" "Loki" 2 }}`
}
Trim, TrimLeft, TrimRight, TrimSpace, TrimPrefix, TrimSuffix
  • Trim 返回字符串 s 的切片,其中包含在 cutset 中的所有前导和尾随 Unicode 代码点已被移除。
  • TrimLeftTrimRight 与 Trim 相同,但它们分别仅修剪前导和尾随字符。
  • TrimSpace 返回字符串 s 的切片,其中所有前导和尾随空白字符(由 Unicode 定义)已被移除。
  • TrimPrefixTrimSuffix 分别修剪提供的前缀或后缀。

以下示例展示了如何使用此函数。

alloy
stage.template {
    source   = "output"
    template = `{{ Trim .Value ",. " }}`
}
stage.template {
    source   = "output"
    template = "{{ TrimSpace .Value }}"
}
stage.template {
    source   = "output"
    template = `{{ TrimPrefix .Value "--" }}`
}
regexReplaceAllregexReplaceAllLiteral

regexReplaceAll 返回输入字符串的副本,将正则表达式的匹配项替换为替换字符串。在替换字符串内部,$ 字符的解释方式与 Expand 函数中相同。例如,$1 代表第一个捕获的子匹配项。

regexReplaceAllLiteral 返回输入字符串的副本,将正则表达式的匹配项替换为替换字符串。替换字符串被直接替换,不使用 Expand。

alloy
stage.template {
    source   = "output"
    template = `{{ regexReplaceAll "(a*)bc" .Value "${1}a" }}`
}
stage.template {
    source   = "output"
    template = `{{ regexReplaceAllLiteral "(ts=)" .Value "timestamp=" }}`
}
HashSha2Hash

Hash 返回字符串的 Sha3_256 哈希值,表示为 64 位十六进制数。您可以使用它来混淆日志中的敏感数据和个人身份信息 (PII)。它需要一个(固定)盐值,以增加低输入域的复杂性,例如,所有可能的社会安全号码。Sha2Hash 返回字符串的 Sha2_256 值,它比 Hash 更快且 CPU 密集度更低,但安全性较差。

以下示例展示了如何使用此函数。

alloy
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 的提取值的名称。""
stringstring设置为租户 ID 的值。""

该块仅期望提供 labelsourcevalue 中的一个。

以下阶段将固定值 team-a 指定为租户 ID

alloy
stage.tenant {
    value = "team-a"
}

此阶段在共享提取映射中将日志条目解析为 JSON 后,从 customer_id 字段中提取租户 ID

alloy
stage.json {
    expressions = { "customer_id" = "" }
}
stage.tenant {
    source = "customer_id"
}

最后一个示例从前一个阶段设置的标签中提取租户 ID

alloy
stage.labels {
  values = {
    "namespace" = "k8s_namespace",
  }
}

stage.tenant {
    label = "namespace"
}

stage.timestamp

stage.timestamp 内部块配置了一个处理阶段,用于在日志条目转发到下一个组件之前设置其时间戳。如果未设置 timestamp 阶段,日志条目的时间戳默认为抓取日志条目的时间。

支持以下参数

名称类型描述默认值必需
格式string确定如何解析源字符串。
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。string从提取值映射中用于时间戳的名称。
失败时的操作string当无法提取或解析时间戳时应执行的操作。"fudge"
回退格式转义的双引号。例如:http_user_agent = "\"request_User-Agent\""如果 format 字段解析失败时尝试的回退格式。[]
位置string解析时使用的 IANA 时区数据库位置。""

配置 JSON 阶段时,source 字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。

请注意后续可能也会覆盖时间戳的阶段。例如,一个设置了 ingest_timestamptruestage.pack 可能会替换流水线中较早由 stage.timestamp 设置的时间戳。

source 字段定义了阶段应尝试将共享提取值映射中的哪个值解析为时间戳。

format 字段定义了如何解析该源。

format 可以设置为以下常用形式的速记值之一

text
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 时间戳

text
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-8601Z0700 (UTC 或时区偏移的 Z), Z070000, Z07, Z07:00, Z07:00:00

配置 JSON 阶段时,source 字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。

如果您定义自定义时间戳,则每个时间戳组件的 format 值必须是上表中指定的值之一。例如,要表示年份,format 值必须是 062006,而不是其他任何值,例如 232023

fallback_formats 字段定义了一个或多个格式字段,以便在使用 format 解析失败时尝试使用它们来解析时间戳。

location 字段必须是有效的 IANA 时区数据库位置,并确定时间戳值应被解释为哪个时区。

action_on_failure 字段定义了当源字段不存在于共享提取映射中,或者时间戳解析失败时应该发生什么。

支持的操作有

  • fudge (默认): 将时间戳更改为最后一个已知时间戳,加上 1 纳秒以保证日志条目排序。
  • skip: 不更改时间戳,保留抓取日志条目时的时间。

以下阶段从共享值映射中获取 time 值,将其解析为 RFC3339 格式,并将其设置为日志条目的时间戳。

alloy
stage.timestamp {
    source = "time"
    format = "RFC3339"
}

以下示例将解析诸如 2024-12-20T09:14:58,381+02:00 的时间戳

alloy
stage.timestamp {
    source = "time"
    format = "2006-01-02T15:04:05,000-07:00"
}

stage.windowsevent

windowsevent 阶段从 Windows 事件日志中的消息字符串中提取数据。

支持以下参数

名称类型描述默认值必需
如果指定,该阶段会丢弃时间戳早于当前时间减去此持续时间的行。stringbool是否覆盖现有的提取数据字段。sourceName of the field in the extracted data to parse.
drop_invalid_labelsboolboolfalse
是否丢弃无效标签名称的字段。booloverwrite_existingfalse

drop_invalid_labels 设置为 true 时,该阶段会丢弃无效标签名称的字段。如果设置为 false,该阶段会自动将它们转换为有效的标签,用下划线替换无效字符。当 overwrite_existing 设置为 true 时,该阶段会覆盖同名的现有提取数据字段。如果设置为 false,则 _extracted 后缀会附加到现有字段名称。

drop_invalid_labels 设置为 true 时,该阶段会丢弃不是有效标签名称的字段。如果设置为 false,该阶段会自动将它们转换为有效标签,将无效字符替换为下划线。

windowsevent 阶段期望消息以空行分隔成多个部分。

输入的第一部分被视为一个整体块,并以键 Description 存储在提取映射中。

Description 后面的部分应包含 key:value 格式的键值对。

如果某个部分的第一行没有值,例如“Subject:”,则该键将作为同一部分后续键的前缀。

如果某个部分中的行不包含 : 符号,则将其视为前一个条目值的一部分。该行将附加到前一个值,用逗号分隔。

部分中没有前导有效条目(键值对)的行将被忽略和丢弃。

loki.source.windowsevent 示例

alloy
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 组件。

假定以下事件

text
{"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 阶段使用提取的值 DescriptionSubject_SecurityIDSubject_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”的标签。

alloy
loki.process "local" {
  forward_to = [loki.write.onprem.receiver]

  stage.json {
      expressions = { "extracted_env" = "environment" }
  }

  stage.labels {
      values = { "env" = "extracted_env" }
  }
}

兼容组件

loki.process 可以接受来自以下组件的参数

loki.process 具有可供以下组件使用的导出项

配置 JSON 阶段时,source 字段定义要解析为 JSON 的数据源。默认情况下,这是日志行本身,但它也可以是之前提取的值。

连接某些组件可能没有意义,或者组件可能需要进一步配置才能使连接正常工作。有关更多详细信息,请参阅链接的文档。