template
注意
Promtail 已被弃用,并在长期支持 (LTS) 期间持续到 2026 年 2 月 28 日。Promtail 将于 2026 年 3 月 2 日达到生命周期结束 (EOL)。您可以在此处找到迁移资源。
template
阶段是一个转换阶段,允许您使用Go 模板语法来操作提取映射中的值。
template
阶段主要用于在将数据设置为标签之前操作来自其他阶段的数据,例如将空格替换为下划线或将大写字符串转换为小写字符串。template
也可用于构建包含多个键的消息。
template 阶段还可以创建提取映射中的新键。
Schema
template:
# Name from extracted data to parse. If key in extract data doesn't exist, an
# entry for it will be created.
source: <string>
# Go template string to use. In additional to normal template
# functions, ToLower, ToUpper, Replace, Trim, TrimLeft, TrimRight,
# TrimPrefix, TrimSuffix, and TrimSpace are available as functions.
template: <string>
示例
- template:
source: new_key
template: 'hello world!'
假设提取映射中尚未添加任何数据,此阶段将首先在提取映射中添加一个值为`new_key`的空白键。然后其值将被设置为`hello world!`。
- template:
source: app
template: '{{ .Value }}_some_suffix'
此流水线获取现有提取映射中 `app` 键的值,并在其值后追加 `_some_suffix`。例如,如果提取映射有一个键为 `app` 且值为 `loki`,此阶段会将值从 `loki` 修改为 `loki_some_suffix`。
- template:
source: app
template: '{{ ToLower .Value }}'
此流水线获取提取映射中 `app` 的当前值,并将其值转换为全小写。例如,如果提取映射中包含 `app` 且值为 `LOKI`,此流水线会将其值更改为 `loki`。
- template:
source: output_msg
template: '{{ .level }} for app {{ ToUpper .app }}'
此流水线获取提取映射中 `level` 和 `app` 的当前值,并将在提取映射中添加一个新键 `output_msg`,其值为经过评估的模板。
例如,如果提取映射中包含 `app` 且值为 `loki`,此流水线会将其值更改为 `LOKI`。假设 `level` 的值为 `warn`。新的键 `output_msg` 将被添加到提取映射中,其值为 `warn for app LOKI`。
任何先前提取的键都可以在 `template` 中使用。所有提取的键都可用于 `template` 展开。
- template:
source: app
template: '{{ .level }} for app {{ ToUpper .Value }} in module {{.module}}'
此流水线获取提取映射中 `level`、`app` 和 `module` 的当前值,并将 `app` 的值转换为经过评估的模板。
例如,如果提取映射中包含 `app` 且值为 `loki`,此流水线会将其值更改为 `LOKI`。假设 `level` 的值为 `warn`,`module` 的值为 `test`。流水线会将 `app` 的值更改为 `warn for app LOKI in module test`。
任何先前提取的键都可以在 `template` 中使用。所有提取的键都可用于 `template` 展开。此外,如果 source 可用,可以在 `template` 中引用为 `.Value`。在这里,`app` 被提供为 `source`。因此,可以在 `template` 中引用为 `.Value`。
- template:
source: app
template: '{{ Replace .Value "loki" "blokey" 1 }}'
这里的模板使用 Go 的string.Replace
函数。当模板执行时,提取映射中 `app` 键的全部内容中最多 `1` 个 `loki` 实例将被更改为 `blokey`。
可以使用名为 `Entry` 的特殊键来引用当前行,当您需要向日志行前/后追加内容时,这非常有用。
- template:
source: message
template: '{{.app }}: {{ .Entry }}'
- output:
source: message
例如,上面的代码片段将在日志行前追加应用程序名称。
- template:
source: time
template: "\
{{ .date_local | substr 6 10 }}-{{ .date_local | substr 0 2 }}-{{ .date_local | substr 3 5 }}T\
{{ if eq (.time_local | substr 0 2) \"12\" }}\
{{ if eq .hour_period \"AM\" }}00{{ else }}12{{ end }}{{ .time_local | substr 2 10}}Z\
{{ else }}\
{{ if eq .hour_period \"AM\" }}\
{{ if or (eq (.time_local | substr 0 2) \"11\") (eq (.time_local | substr 0 2) \"10\") }}{{ .time_local }}Z\
{{ else }}0{{ .time_local }}Z\
{{ end }}\
{{ else }}\
{{ if eq (.time_local | substr 0 2) \"11\" }}23{{ .time_local | substr 2 10 }}Z{{ end }}\
{{ if eq (.time_local | substr 0 2) \"10\" }}22{{ .time_local | substr 2 10 }}Z{{ end }}\
{{ if eq (.time_local | substr 0 2) \"9:\" }}21{{ .time_local | substr 1 10 }}Z{{ end }}\
{{ if eq (.time_local | substr 0 2) \"8:\" }}20{{ .time_local | substr 1 10 }}Z{{ end }}\
{{ if and (le (.time_local | substr 0 1) \"7\") (eq (.time_local | substr 1 2) \":\") }}1{{ add (.time_local | substr 0 1) 2 }}{{ .time_local | substr 1 10 }}Z{{ end }}\
{{ end }}\
{{ end }}"
- timestamp:
source: time
format: RFC3339
上面的代码片段是一个没有空格的多行模板示例。从日志中使用正则表达式提取的数据将用于将 `11/08/2022, 12:53:24 PM` 转换为 `RFC3339` 时间格式。它还使用了 `eq`、`substr` 等函数,并展示了如何在 Go 模板中使用带 `and`、`or` 的 `if`。
支持的函数
所有sprig 函数已在 Loki 2.3 中添加到 template 阶段(以及下面描述的函数)。
ToLower 和 ToUpper
ToLower 和 ToUpper 分别将整个字符串转换为小写和大写。
示例
- template:
source: out
template: '{{ ToLower .app }}'
- template:
source: out
template: '{{ .app | ToUpper }}'
Replace
Replace
返回字符串 s 的副本,其中第一次出现的 n 个不重叠的 old 实例被 new 替换。如果 old 为空,则在字符串的开头以及每个 UTF-8 序列之后匹配,对于 k 个符文的字符串,最多产生 k+1 个替换。如果 n < 0,则对替换次数没有限制。
下面的示例将把前两个单词 `loki` 替换为 `Loki`。
- template:
source: output
template: '{{ Replace .Value "loki" "Loki" 2 }}'
Trim
Trim
返回字符串 s 的切片,其中所有前导和尾随的 Unicode 码点(包含在 cutset 中)已被移除。
TrimLeft
和 TrimRight
与 Trim
相同,但它们分别只修剪前导和尾随字符。
- template:
source: output
template: '{{ Trim .Value ",. " }}'
TrimSpace
TrimSpace 返回字符串 s 的切片,其中所有前导和尾随空白字符(由 Unicode 定义)已被移除。
- template:
source: output
template: '{{ TrimSpace .Value }}'
TrimPrefix
和 TrimSuffix
分别修剪提供的前缀或后缀。
- template:
source: output
template: '{{ TrimPrefix .Value "--" }}'
Regex
regexReplaceAll
返回输入字符串的副本,将 Regexp 的匹配项替换为替换字符串 replacement。在字符串 replacement 内部,$ 符号的解释与 Expand 中相同,例如 $1 表示第一个子匹配的文本
- template:
source: output
template: '{{ regexReplaceAll "(a*)bc" .Value "${1}a" }}'
regexReplaceAllLiteral
返回输入字符串的副本,将 Regexp 的匹配项替换为替换字符串 replacement。替换字符串被直接替换,不使用 Expand。
- template:
source: output
template: '{{ regexReplaceAllLiteral "(ts=)" .Value "timestamp=" }}'
Hash 和 Sha2Hash
Hash
返回字符串的 Sha3_256 哈希值,表示为 64 位数字的十六进制数。您可以使用它来混淆日志中的敏感数据/PII。它需要一个(固定的)盐值,以增加低输入域(例如所有可能的社会安全号码)的复杂性。
- template:
source: output
template: '{{ Hash .Value "salt" }}'
或者,您可以使用 Sha2Hash
计算字符串的 Sha2_256。Sha2_256 比 Sha3_256 更快且需要的 CPU 更少,但安全性较低。
我们建议使用 Hash
,因为它具有更强的哈希算法,我们计划随着时间的推移保持其强度,而无需客户端更改配置。
- template:
source: output
template: '{{ Sha2Hash .Value "salt" }}'