菜单
通用可用性 (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 事件日志中的消息字段提取数据。
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_truncatebool截断长度超过 max_partial_line_size 的部分行。false
max_partial_line_sizenumber部分行可以具有的最大字符数。0
max_partial_linesnumber内存中要保留的最大部分行数。100

只有当 max_partial_line_size_truncate 设置为 true 时,才会考虑 max_partial_line_size

alloy
stage.cri {}

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

  • time:日志的时间戳字符串。
  • streamstdoutstderr
  • flags:CRI 标志,包括 FP
  • 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:日志行的内容。
  • streamstdoutstderr
  • 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 子句,并且所有选项都必须为 true,日志条目才会被删除。要使用 OR 子句删除条目,请按顺序指定多个 drop 块。

支持以下参数

名称类型描述默认值必需
drop_counter_reasonstring报告已删除行的自定义原因。"drop_stage"
expressionstring有效的 RE2 正则表达式。""
longer_thanstring如果指定,则该阶段会删除大小超过配置值的行。""
older_thanduration如果指定,则该阶段会删除时间戳早于当前时间减去此持续时间的行。""
separatorstringsource 是以逗号分隔的名称列表时,此分隔符放置在连接的提取数据值之间。";"
sourcestring要匹配的提取数据中的名称或以逗号分隔的名称列表。如果为空或未定义,则使用日志消息。""
valuestring如果同时指定了 sourcevalue,则该阶段会删除 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 的日志条目。

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

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

支持以下参数

名称类型描述默认值必需
drop_invalid_labelsbool是否删除不是有效标签名称的字段。false
overwrite_existingbool是否覆盖现有的提取数据字段。false
sourcestringsourcemessage

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 数据库用于查找。

支持以下参数

名称类型描述默认值必需
dbstringMaxmind DB 文件的路径。
sourcestringsource
custom_lookupsmap(string)JMESPath 表达式的键值对。
db_typestringMaxmind DB 类型。允许的值为 "city""asn""country"

使用 City 数据库的 GeoIP 示例

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   = "",
        }
    }
}

json 阶段从日志行中的 client_ip 键中提取 IP 地址。然后,将提取的 ip 值作为源提供给 geoip 阶段。geoip 阶段对 IP 执行查找,并在共享映射中填充以下字段,这些字段使用 labels 阶段添加为标签。

此示例中使用的 IP 的提取数据

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

使用 ASN(自治系统号)数据库的 GeoIP 示例

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 = "",
        }
    }
}

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

此示例中使用的 IP 的提取数据

text
geoip_autonomous_system_number: 396982
geoip_autonomous_system_organization: GOOGLE-CLOUD-PLATFORM

使用 Country 数据库的 GeoIP 示例

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     = "",
        }
    }
}

json 阶段从日志行中的 client_ip 键中提取 IP 地址。然后,将提取的 ip 值作为源提供给 geoip 阶段。geoip 阶段对 IP 执行查找,并在共享映射中填充以下字段,这些字段使用 labels 阶段添加为标签。

此示例中使用的 IP 的提取数据

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

使用自定义字段的 GeoIP 示例

如果使用的 MMDB 文件使用自定义数据进行了丰富,例如,Maxmind 博客文章中解释的私有 IP 地址,则可以使用 custom_lookups 属性从记录中提取它。

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      = "",
        }
    }
}

json 阶段从日志行中的 client_ip 键中提取 IP 地址。然后,将提取的 ip 值作为源提供给 geoip 阶段。geoip 阶段对 IP 执行查找,并在共享映射中填充城市数据库结果中的数据以及自定义查找。最后,共享映射中的自定义查找字段将添加为标签。

stage.json

stage.json 内部块配置一个 JSON 处理阶段,该阶段将传入的日志行或先前提取的值解析为 JSON,并使用 JMESPath 表达式从中提取新值。

支持以下参数

名称类型描述默认值必需
expressionsmap(string)JMESPath 表达式的键值对。
drop_malformedbool删除输入无法解析为有效 JSON 的行。false
sourcestringsource""

expressions 字段是要运行的 JMESPath 表达式的键值对集合。映射键定义提取数据的名称,而映射值是用于填充值的表达式。

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

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

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

text
output: log message\n
extra: {"user": "alloy"}

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

text
username: alloy

注意

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

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

您可以使用以下两种选项之一来规避此问题

  1. 转义的双引号。例如:http_user_agent = "\"request_User-Agent\""
  2. 反引号。例如:http_user_agent = `"request_User-Agent"`

stage.label_drop

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

支持以下参数

名称类型描述默认值必需
valueslist(string)配置 label_drop 处理阶段。{}
alloy
stage.label_drop {
    values = [ "kubernetes_node_name", "kubernetes_namespace" ]
}

stage.label_keep

stage.label_keep 内部块配置一个处理阶段,该阶段将传入日志条目的标签集过滤为子集。

支持以下参数

名称类型描述默认值必需
valueslist(string)配置 label_keep 处理阶段。{}
alloy
stage.label_keep {
    values = [ "kubernetes_pod_name", "kubernetes_pod_container_name" ]
}

stage.labels

stage.labels 内部块配置一个标签处理阶段,该阶段可以从提取的值映射中读取数据,并在传入的日志条目上设置新标签。

支持以下参数

名称类型描述默认值必需
valuesmap(string)配置 labels 处理阶段。{}

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

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

stage.limit 内部块配置一个速率限制阶段,该阶段根据多个选项限制日志的速率。

支持以下参数

名称类型描述默认值必需
burstnumber该阶段转发的最大突发行数。
ratenumber该阶段每秒转发的最大行数速率。
by_label_namestring在按标签名称进行速率限制时要使用的标签。""
dropbool是丢弃还是背压超过速率限制的行。false
max_distinct_labelsnumber在按 by_label_name 进行速率限制时要跟踪的唯一值数量。10000

速率限制是大小为 burst 的“令牌桶”。它最初是满的,并以每秒 rate 个令牌的速度重新填充。每个收到的日志条目消耗桶中的一个令牌。当 drop 设置为 true 时,超过速率限制的传入条目将被删除,否则它们将被排队,直到有更多令牌可用。

alloy
stage.limit {
    rate  = 5
    burst = 10
}

如果设置了 by_label_name,则 drop 必须设置为 true。这使该阶段能够按标签数量而不是行数进行速率限制。

以下示例独立地对每个唯一 namespace 值中的条目进行速率限制。任何没有 namespace 标签的条目都不会受到速率限制。该阶段最多跟踪 max_distinct_labels 个唯一值,默认为 10000。

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

    by_label_name = "namespace"
}

stage.logfmt

stage.logfmt 内部块配置一个处理阶段,该阶段将传入的日志行读取为 logfmt 并从中提取值。

支持以下参数

名称类型描述默认值必需
mappingmap(string)要提取的 logmft 字段的键值对。
sourcestringsource""

source 字段定义要解析为 logfmt 的数据源。当 source 缺失或为空时,该阶段将解析日志行本身,但它也可以用于解析先前提取的值。

此阶段使用 go-logfmt unmarshaler,以便将数字或布尔类型解组为其正确的形式。该阶段不执行任何其他类型转换。如果提取的值是复杂类型,则将其视为字符串。

以下日志行和阶段演示了其工作原理。

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

第一个阶段解析日志行本身,并在提取数据集中插入 extra 键,其值为 user=example_name

第二个阶段解析 extra 的内容,并将 username: example_name 键值对附加到提取数据集中。

stage.luhn

stage.luhn 内部块配置一个处理阶段,该阶段读取传入的日志行并编辑与 Luhn 算法匹配的字符串。

Luhn 算法 是一种简单的校验和公式,用于验证各种识别号码,例如信用卡号、IMEI 号、美国国家提供商标识号码和加拿大社会保险号码。许多支付卡行业环境要求编辑这些号码。

支持以下参数

名称类型描述默认值必需
min_lengthint要考虑的最小位数长度13
replacementstring用于替换匹配模式的字符串"**已编辑**"
sourcestringsource""

source 字段定义要搜索的数据源。当 source 缺失或为空时,该阶段将解析日志行本身,但它也可以用于解析先前提取的值。

以下示例日志行包含已批准的信用卡号。

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

该阶段解析日志行,编辑信用卡号,并生成以下更新的日志行

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

stage.match 内部块配置一个过滤阶段,当日志条目与可配置的 LogQL 流选择器和过滤器表达式匹配时,该阶段可以有条件地应用一组嵌套的处理阶段或删除条目。

支持以下参数

名称类型描述默认值必需
selectorstring要使用的 LogQL 流选择器和行过滤器表达式。
actionstring当选择器与日志行匹配时要采取的操作。支持的值为 "keep""drop""keep"
drop_counter_reasonstring报告已删除行的自定义原因。drop_counter_reason
pipeline_namestring用于嵌套管道的自定义名称。""

注意

过滤器不包括标签过滤器表达式,例如 | label == "examplelabel"

stage.match 块支持许多 stage.* 内部块,就像顶级块一样。这些用于构建一组嵌套阶段,以便在选择器与日志条目的标签和内容匹配时运行。它支持与 loki.process 组件的顶级相同的 stage.NAME 块。

如果指定的操作是 "drop",则每删除一行,指标 loki_process_dropped_lines_total 就会递增。默认情况下,原因标签为 "match_stage",但可以使用 drop_counter_reason 参数提供自定义原因。

以下示例日志行和阶段显示了其工作原理。

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

前两个阶段将日志行解析为 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

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

支持以下参数

名称类型描述默认值必需
actionstringaction
namestring指标名称。
count_entry_bytesbool如果设置为 true,则计算所有日志行字节数。false
descriptionstring指标的描述和帮助文本。""
match_allbool如果设置为 true,则计算所有日志行,而不尝试将 source 与提取映射匹配。false
max_idle_durationduration等待指标标记为“过时”并删除的最大时间量。"5m"
prefixstring指标名称的前缀。"loki_process_custom_"
sourcestringsource""
valuestringvalue""

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

metric.gauge

定义一个值可以上升或下降的 gauge 指标。

支持以下参数

名称类型描述默认值必需
actionstringaction
namestring指标名称。
descriptionstring指标的描述和帮助文本。""
max_idle_durationduration等待指标标记为“过时”并删除的最大时间量。"5m"
prefixstring指标名称的前缀。"loki_process_custom_"
sourcestringsource""
valuestringvalue""

有效的 action 值为 incdecsetaddsubincdec 分别将指标的值增加和减少 1。如果选择 setaddsub,则提取的值必须可转换为正浮点数,并且设置为、添加到或从指标的值中减去。

metric.histogram

定义一个直方图指标,其值记录在预定义的存储桶中。

支持以下参数

名称类型描述默认值必需
bucketslist(float)预定义的存储桶
namestring指标名称。
descriptionstring指标的描述和帮助文本。""
max_idle_durationduration等待指标标记为“过时”并删除的最大时间量。"5m"
prefixstring指标名称的前缀。"loki_process_custom_"
sourcestringsource""
valuestringvalue""

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小时内没有收到新的条目,这两个指标将消失,以避免累积不再有任何用途的指标。这两个指标是跟踪日志流的卷(包括条目数量和字节大小)的良好起点,以识别高容量或高基数数据的来源。

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

在这里,第一阶段使用正则表达式来提取日志行中格式为 order_status=<string> 的文本。第二阶段定义了一个计数器,根据先前提取的值,递增 successful_orders_totalfailed_orders_total

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

在本示例中,第一阶段从日志行中提取格式为 retries=<value> 的文本。第二阶段创建了一个仪表盘,其当前指标值会根据从 retries 字段提取的数字而增加。

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

以下示例展示了一个直方图,该直方图从提取的映射中读取 response_time,并将其放入存储桶中,同时增加存储桶的计数和该特定存储桶的总和。

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

stage.multiline 内部块将多行合并成一个块,然后再将其传递到pipeline中的下一个阶段。

支持以下参数

名称类型描述默认值必需
firstlinestring从提取的数据中获取用于日志条目的名称。
max_linesnumber一个块可以拥有的最大行数。128
max_wait_timeduration等待多行块的最长时间。"3秒"

通过在 firstline 中传递的 RE2 正则表达式来识别新块。

任何与该表达式匹配的行都被认为是前一个匹配块的一部分。如果在 max_wait_time 内没有新的日志到达,则会发送该块。max_lines 字段定义了一个块可以拥有的最大行数。如果超过此限制,则会启动一个新块。

以下示例阶段和来自 Flask Web 服务的日志条目流展示了其工作原理。

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 -

构成单独 Web 请求的日志条目的所有“块”都以方括号中的时间戳开头。该阶段使用 firstline 中的正则表达式检测到这一点,以将回溯的所有行折叠成单个块,从而形成单个 Loki 日志条目。

stage.output

stage.output 内部块配置一个处理阶段,该阶段从提取的映射中读取数据,并更改转发到下一个组件的日志条目的内容。

支持以下参数

名称类型描述默认值必需
sourcestring从提取的数据中获取用于日志条目的名称。

以下示例日志行和三阶段pipeline展示了其工作原理。

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

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

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

stage.output {
    source = "message"
}

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

text
user: John Doe
message: hello, world!

然后,第二阶段将 user="John Doe" 添加到日志条目的标签集中,最后一个输出阶段将日志行从原始 JSON 更改为 hello, world!

stage.pack

stage.pack 内部块配置一个转换阶段,该阶段用 JSON 对象替换日志条目,该 JSON 对象嵌入了提取的值和标签。

支持以下参数

名称类型描述默认值必需
labelslist(string)要与日志条目一起打包的提取数据和标签中的值。
ingest_timestampbool是否将日志条目时间戳替换为 pack 阶段运行的时间。true

此阶段允许您将提取的值和标签与日志行一起嵌入,方法是将它们打包到 JSON 对象中。原始消息存储在 _entry 键下,所有其他键都保留其值。这在您确实想要保留某个标签或元数据的情况下很有用,但由于高基数,您不希望将其索引为标签。

Loki 的查询功能使您可以轻松访问这些数据,以便在查询时对其进行过滤和聚合。

例如,考虑以下日志条目

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

和此处理阶段

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

该阶段将日志条目转换为以下 JSON 对象,其中从原始日志条目中删除了两个嵌入式标签

json
{
  "_entry": "something went wrong",
  "env": "dev",
  "user_id": "f8fas0r"
}

在查询时,Loki unpack 解析器 可用于访问这些嵌入式标签,并将日志行自动替换为存储在 _entry 字段中的原始日志行。

当组合多个日志流以与 pack 阶段一起使用时,您可以将 ingest_timestamp 设置为 true,以避免交错的时间戳和乱序摄取问题。

stage.regex

stage.regex 内部块配置一个处理阶段,该阶段使用正则表达式解析日志行,并使用命名捕获组将数据添加到共享的提取值映射中。

支持以下参数

名称类型描述默认值必需
expressionstring有效的 RE2 正则表达式。每个捕获组都必须命名。
sourcestring要解析的提取数据中的名称。如果为空,则使用日志消息。""

expression 字段需要是 RE2 正则表达式字符串。每个匹配的捕获组都会添加到提取的映射中,因此必须像这样命名:(?P<name>re)。捕获组的名称随后用作提取映射中匹配值的键。

由于 Alloy 语法字符串的工作方式,expression 中的任何反斜杠都必须使用双反斜杠进行转义,例如,"\\w""\\S+"

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

以下日志行将通过此两阶段pipeline

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

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

text
year: 2022

stage.replace

stage.replace 内部块配置一个阶段,该阶段使用正则表达式解析日志行并替换日志行内容。正则表达式中的命名捕获组也支持将数据添加到共享的提取映射中。

支持以下参数

名称类型描述默认值必需
expressionstring包含捕获组的 RE2 正则表达式。
replacestring由捕获组替换的值。
sourcestring要解析的数据源。如果为空,则使用日志消息。

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% 的日志将被丢弃。

支持以下参数

名称类型描述默认值必需
ratefloat采样率,范围为 [0, 1]
drop_counter_reasonstring当日志被此阶段丢弃时,要添加到 loki_process_dropped_lines_total 指标的标签。sampling_stage

例如,以下配置将采样 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 处理阶段,该阶段向传入的日志条目添加一组静态标签。

支持以下参数

名称类型描述默认值必需
valuesmap(string)配置 static_labels 处理阶段。{}
alloy
stage.static_labels {
    values = {
      foo = "fooval",
      bar = "barval",
    }
}

stage.structured_metadata

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

支持以下参数

名称类型描述默认值必需
valuesmap(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 package 语法来操作提取的映射中的值。此阶段主要用于在将来自先前阶段的数据设置为后续阶段中的标签之前,对其进行操作和标准化。示例用例包括将空格替换为下划线、将大写字符串转换为小写或哈希值。

template 阶段还可以在提取的映射中创建新键。

支持以下参数

名称类型描述默认值必需
sourcestring要解析的提取数据中的名称。如果键不存在,则会创建一个新条目。
templatestring要使用的 Go 模板字符串。

模板字符串可以是 Go 的 text/template 可以使用的任何有效模板。它支持来自 sprig package 的所有函数,以及以下自定义函数列表

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 package 的所有函数外,template 阶段还支持以下自定义函数。

ToLowerToUpper

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

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

alloy
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

alloy
stage.template {
    source   = "output"
    template = `{{ Replace .Value "loki" "Loki" 2 }}`
}
TrimTrimLeftTrimRightTrimSpaceTrimPrefixTrimSuffix
  • 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 返回输入字符串的副本,将 Regexp 的匹配项替换为替换字符串。在替换字符串内部,$ 字符的解释方式与 Expand 函数中相同。例如,$1 表示第一个捕获的子匹配项。

regexReplaceAllLiteral 返回输入字符串的副本,将 Regexp 的匹配项替换为替换字符串。替换字符串被直接替换,而不使用 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。它需要一个(固定的)salt 值,以增加低输入域的复杂性,例如,所有可能的社会安全号码。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。

支持以下参数

名称类型描述默认值必需
labelstring要设置为租户 ID 的标签。""
sourcestring要用作租户 ID 的提取值中的名称。""
valuestring要设置为租户 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 {
    "namespace" = "k8s_namespace"
}
stage.tenant {
    label = "namespace"
}

stage.timestamp

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

支持以下参数

名称类型描述默认值必需
formatstring确定如何解析源字符串。
sourcestring从提取的值映射中获取用于时间戳的名称。
action_on_failurestring当无法提取或解析时间戳时要执行的操作。"fudge"
fallback_formatslist(string)如果 format 字段失败,则尝试使用的回退格式。[]
locationstring解析时要使用的 IANA 时区数据库位置。""

注意

请注意,后面的阶段也可能覆盖时间戳。例如,将 ingest_timestamp 设置为 truestage.pack 可能会替换 stage.timestamp 之前在pipeline中设置的时间戳。

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

注意

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

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

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

导出的字段

以下字段已导出,可供其他组件引用

名称类型描述
receiverLogsReceiver其他组件可用于向其发送日志条目的值。

组件健康状况

仅当 loki.process 给定无效配置时,才报告为不健康。

调试信息

loki.process 不公开任何特定于组件的调试信息。

调试指标

  • loki_process_dropped_lines_total (计数器):作为处理阶段一部分丢弃的行数。
  • loki_process_dropped_lines_by_label_total (计数器):当 stage.limitby_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 具有可以被以下组件使用的导出

注意

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