Loki: Add new logql template functions `bytes`, `duration`, `unixEpochMillis`, `unixEpochNanos`, `toDateInZone`, `b64Enc`, and `b64Dec` (#8774)

**What this PR does / why we need it**:

This adds several new template functions to the logql to be used in
`line_format` and `label_format`

- bytes
- duration (and duration_seconds)
- unixEpochMillis
- unixEpochNanos
- toDateInZone
- b64Enc and b64Dec

`bytes` and `duration` adds parity with the `unwrap` pipeline stage in
logql, allowing you to convert human readable versions of bytes and
times into their respective primitives of bytes and seconds. This makes
it possible to do math and comparisons of these extracted values in
`line_format` and `label_format`

`unixEpochMillis` and `unixEpochNanos` extends the existing `unixEpoch`
function which can only generate seconds level precision to allow having
millisecond and nanosecond level precision.

`toDateInZone` allows for specifying a specific timezone when parsing a
date.

`b64Enc` and `b64Dec` allow base64 encoding and decoding values.

**Which issue(s) this PR fixes**:
Fixes #<issue number>

**Special notes for your reviewer**:

@JStickler I made a lot of changes to the template_functions.md doc page
to try and create some more consistency as well as remove some notices
that really aren't relevant anymore:

* Tried to make sure every function had a `Signature` and `Examples`
block
* Removed a lot of `NOTE` about functions being introduced in a specific
version
* Removed documentation for some deprecated string functions (they still
exist in code but I removed the docs for them, their exist better
replacements for all of them)

**Checklist**
- [x] Reviewed the
[`CONTRIBUTING.md`](https://github.com/grafana/loki/blob/main/CONTRIBUTING.md)
guide (**required**)
- [x] Documentation added
- [x] Tests updated
- [ ] `CHANGELOG.md` updated
- [ ] Changes that require user attention or interaction to upgrade are
documented in `docs/sources/upgrading/_index.md`

---------

Signed-off-by: Edward Welch <edward.welch@grafana.com>
pull/8777/head
Ed Welch 2 years ago committed by GitHub
parent 55c96bfe90
commit 0352b75f0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 381
      docs/sources/logql/template_functions.md
  3. 30
      pkg/logql/log/fmt.go
  4. 162
      pkg/logql/log/fmt_test.go

@ -33,6 +33,7 @@
* [7906](https://github.com/grafana/loki/pull/7906) **kavirajk**: Add API endpoint that formats LogQL expressions and support new `fmt` subcommand in `logcli` to format LogQL query.
* [6675](https://github.com/grafana/loki/pull/6675) **btaani**: Add logfmt expression parser for selective extraction of labels from logfmt formatted logs
* [8474](https://github.com/grafana/loki/pull/8474) **farodin91**: Add support for short-lived S3 session tokens
* [8774](https://github.com/grafana/loki/pull/8774) **slim-bean**: Add new logql template functions `bytes`, `duration`, `unixEpochMillis`, `unixEpochNanos`, `toDateInZone`, `b64Enc`, and `b64Dec`
##### Fixes

@ -29,9 +29,7 @@ Example:
This function returns the current log line.
Signature:
`line() string`
Signature: `line() string`
Examples:
@ -44,9 +42,7 @@ Examples:
This function returns the current log lines timestamp.
Signature:
`timestamp() time.Time`
Signature: `timestamp() time.Time`
```template
"{{ __timestamp__ }}"
@ -56,110 +52,29 @@ Signature:
See the blog: [Parsing and formatting date/time in Go](https://www.pauladamsmith.com/blog/2011/05/go_time.html) for more information.
## ToLower and ToUpper
This function converts the entire string to lowercase or uppercase.
Signatures:
- `ToLower(string) string`
- `ToUpper(string) string`
Examples:
```template
"{{.request_method | ToLower}}"
"{{.request_method | ToUpper}}"
`{{ToUpper "This is a string" | ToLower}}`
```
> **Note:** In Grafana Loki 2.1 you can also use respectively [`lower`](#lower) and [`upper`](#upper) shortcut, e.g `{{.request_method | lower }}`.
## Replace string
> **Note:** In Loki 2.1 [`replace`](#replace) (as opposed to `Replace`) is available with a different signature but easier to chain within pipeline.
Use this function to perform a simple string replacement.
Signature:
`Replace(s, old, new string, n int) string`
It takes four arguments:
- `s` source string
- `old` string to replace
- `new` string to replace with
- `n` the maximun amount of replacement (-1 for all)
Example:
```template
`{{ Replace "This is a string" " " "-" -1 }}`
```
The results in `This-is-a-string`.
## Trim, TrimLeft, TrimRight, and TrimSpace
> **Note:** In Loki 2.1 [trim](#trim), [trimAll](#trimall), [trimSuffix](#trimsuffix) and [trimPrefix](#trimprefix) have been added with a different signature for better pipeline chaining.
`Trim` returns a slice of the string s with all leading and
trailing Unicode code points contained in cutset removed.
Signature: `Trim(value, cutset string) string`
`TrimLeft` and `TrimRight` are the same as `Trim` except that it trims only leading and trailing characters respectively.
```template
`{{ Trim .query ",. " }}`
`{{ TrimLeft .uri ":" }}`
`{{ TrimRight .path "/" }}`
```
`TrimSpace` TrimSpace returns string s with all leading
and trailing white space removed, as defined by Unicode.
Signature: `TrimSpace(value string) string`
```template
{{ TrimSpace .latency }}
```
`TrimPrefix` and `TrimSuffix` will trim respectively the prefix or suffix supplied.
Signature:
- `TrimPrefix(value string, prefix string) string`
- `TrimSuffix(value string, suffix string) string`
```template
{{ TrimPrefix .path "/" }}
```
## regexReplaceAll and regexReplaceAllLiteral
`regexReplaceAll` returns a copy of the input string, replacing matches of the Regexp with the replacement string replacement. Inside string replacement, $ signs are interpreted as in Expand, so for instance $1 represents the text of the first sub-match. See the golang [Regexp.replaceAll documentation](https://golang.org/pkg/regexp/#Regexp.ReplaceAll) for more examples.
Example:
```template
`{{ regexReplaceAll "(a*)bc" .some_label "${1}a" }}`
```
`regexReplaceAllLiteral` function returns a copy of the input string and replaces matches of the Regexp with the replacement string replacement. The replacement string is substituted directly, without using Expand.
Example:
```template
`{{ regexReplaceAllLiteral "(ts=)" .timestamp "timestamp=" }}`
```
## lower
> Added in Loki 2.1
Use this function to convert to lower case.
Signature:
`lower(string) string`
Signature: `lower(string) string`
Examples:
@ -172,13 +87,9 @@ The last example will return `hello`.
## upper
> Added in Loki 2.1
Use this function to convert to upper case.
Signature:
`upper(string) string`
Signature: `upper(string) string`
Examples:
@ -191,13 +102,9 @@ This results in `HELLO`.
## title
> **Note:** Added in Loki 2.1.
Convert to title case.
Signature:
`title(string) string`
Signature: `title(string) string`
Examples:
@ -210,13 +117,9 @@ The last example will return `Hello World`.
## trunc
> **Note:** Added in Loki 2.1.
Truncate a string and add no suffix.
Signature:
`trunc(count int,value string) string`
Signature: `trunc(count int,value string) string`
Examples:
@ -228,13 +131,9 @@ Examples:
## substr
> **Note:** Added in Loki 2.1.
Get a substring from a string.
Signature:
`substr(start int,end int,value string) string`
Signature: `substr(start int,end int,value string) string`
If start is < 0, this calls value[:end].
If start is >= 0 and end < 0 or end bigger than s length, this calls value[start:]
@ -250,8 +149,6 @@ Examples:
## replace
> **Note:** Added in Loki 2.1.
This function performs simple string replacement.
Signature: `replace(old string, new string, src string) string`
@ -273,8 +170,6 @@ The last example will return `world world`.
## trim
> **Note:** Added in Loki 2.1.
The trim function removes space from either side of a string.
Signature: `trim(string) string`
@ -288,8 +183,6 @@ Examples:
## trimAll
> **Note:** Added in Loki 2.1.
Use this function to remove given characters from the front or back of a string.
Signature: `trimAll(chars string,src string) string`
@ -303,8 +196,6 @@ Examples:
## trimSuffix
> **Note:** Added in Loki 2.1.
Use this function to trim just the suffix from a string.
Signature: `trimSuffix(suffix string, src string) string`
@ -318,8 +209,6 @@ Examples:
## trimPrefix
> **Note:** Added in Loki 2.1.
Use this function to trim just the prefix from a string.
Signature: `trimPrefix(prefix string, src string) string`
@ -333,12 +222,12 @@ Examples:
## indent
> **Note:** Added in Loki 2.1.
The indent function indents every line in a given string to the specified indent width. This is useful when aligning multi-line strings.
Signature: `indent(spaces int,src string) string`
Example:
```template
{{ indent 4 .query }}
```
@ -347,12 +236,12 @@ This indents each line contained in the `.query` by four (4) spaces.
## nindent
> **Note:** Added in Loki 2.1.
The nindent function is the same as the indent function, but prepends a new line to the beginning of the string.
Signature: `nindent(spaces int,src string) string`
Example:
```template
{{ nindent 4 .query }}
```
@ -361,20 +250,18 @@ This will indent every line of text by 4 space characters and add a new line to
## repeat
> **Note:** Added in Loki 2.1.
Use this function to repeat a string multiple times.
Signature: `repeat(c int,value string) string`
Example:
```template
{{ repeat 3 "hello" }} // output: hellohellohello
```
## contains
> **Note:** Added in Loki 2.1.
Use this function to test to see if one string is contained inside of another.
Signature: `contains(s string, src string) bool`
@ -388,8 +275,6 @@ Examples:
## hasPrefix and hasSuffix
> **Note:** Added in Loki 2.1.
The `hasPrefix` and `hasSuffix` functions test whether a string has a given prefix or suffix.
Signatures:
@ -406,198 +291,200 @@ Examples:
## add
> **Note:** Added in Loki 2.3.
Sum numbers. Supports multiple numbers
Signature: `func(i ...interface{}) int64`
Example:
```template
{{ add 3 2 5 }} // output: 10
```
## sub
> **Note:** Added in Loki 2.3.
Subtract numbers.
Signature: `func(a, b interface{}) int64`
Example:
```template
{{ sub 5 2 }} // output: 3
```
## mul
> **Note:** Added in Loki 2.3.
Mulitply numbers. Supports multiple numbers.
Signature: `func(a interface{}, v ...interface{}) int64`
Example:
```template
{{ mul 5 2 3}} // output: 30
```
## div
> **Note:** Added in Loki 2.3.
Integer divide numbers.
Signature: `func(a, b interface{}) int64`
Example:
```template
{{ div 10 2}} // output: 5
```
## addf
> **Note:** Added in Loki 2.3.
Sum numbers. Supports multiple numbers.
Signature: `func(i ...interface{}) float64`
Example:
```template
{{ addf 3.5 2 5 }} // output: 10.5
```
## subf
> **Note:** Added in Loki 2.3.
Subtract numbers. Supports multiple numbers.
Signature: `func(a interface{}, v ...interface{}) float64`
Example:
```template
{{ subf 5.5 2 1.5 }} // output: 2
```
## mulf
> **Note:** Added in Loki 2.3.
Mulitply numbers. Supports multiple numbers
Signature: `func(a interface{}, v ...interface{}) float64`
Example:
```template
{{ mulf 5.5 2 2.5 }} // output: 27.5
```
## divf
> **Note:** Added in Loki 2.3.
Divide numbers. Supports multiple numbers.
Signature: `func(a interface{}, v ...interface{}) float64`
Example:
```template
{{ divf 10 2 4}} // output: 1.25
```
## mod
> **Note:** Added in Loki 2.3.
Modulo wit mod.
Signature: `func(a, b interface{}) int64`
Example:
```template
{{ mod 10 3}} // output: 1
```
## max
> **Note:** Added in Loki 2.3.
Return the largest of a series of integers:
Signature: `max(a interface{}, i ...interface{}) int64`
Example:
```template
{{ max 1 2 3 }} //output 3
```
## min
> **Note:** Added in Loki 2.3.
Return the smallest of a series of integers.
Signature: `min(a interface{}, i ...interface{}) int64`
Example:
```template
{{ max 1 2 3 }} //output 1
```
## maxf
> **Note:** Added in Loki 2.3.
Return the largest of a series of floats:
Signature: `maxf(a interface{}, i ...interface{}) float64`
Example:
```template
{{ maxf 1 2.5 3 }} //output 3
```
## minf
> **Note:** Added in Loki 2.3.
Return the smallest of a series of floats.
Signature: `minf(a interface{}, i ...interface{}) float64`
Example:
```template
{{ minf 1 2.5 3 }} //output 1.5
```
## ceil
> **Note:** Added in Loki 2.3.
Returns the greatest float value greater than or equal to input value
Signature: `ceil(a interface{}) float64`
Example:
```template
{{ ceil 123.001 }} //output 124.0
```
## floor
> **Note:** Added in Loki 2.3.
Returns the greatest float value less than or equal to input value
Signature: `floor(a interface{}) float64`
Example:
```template
{{ floor 123.9999 }} //output 123.0
```
## round
> **Note:** Added in Loki 2.3.
Returns a float value with the remainder rounded to the given number of digits after the decimal point.
Signature: `round(a interface{}, p int, rOpt ...float64) float64`
Example:
```template
{{ round 123.555555 3 }} //output 123.556
```
We can also provide a `roundOn` number as third parameter
Example:
```template
{{ round 123.88571428571 5 .2 }} //output 123.88572
```
@ -606,33 +493,35 @@ With default `roundOn` of `.5` the above value would be `123.88571`
## int
> **Note:** Added in Loki 2.3.
Convert value to an int.
Signature: `toInt(v interface{}) int`
Example:
```template
{{ "3" | int }} //output 3
```
## float64
> **Note:** Added in Loki 2.3.
Convert to a float64.
Signature: `toFloat64(v interface{}) float64`
Example:
```template
{{ "3.5" | float64 }} //output 3.5
```
## fromJson
> **Note:** Added in Loki 2.3.
Decodes a JSON document into a structure. If the input cannot be decoded as JSON the function will return an empty string.
Signature: `fromJson(v string) interface{}`
fromJson decodes a JSON document into a structure. If the input cannot be decoded as JSON the function will return an empty string.
Example:
```template
fromJson "{\"foo\": 55}"
@ -646,7 +535,11 @@ Example of a query to print a newline per queries stored as a json array in the
## now
`now` returns the current local time.
Returns the current time in the local timezone of the Loki server.
Signature: `Now() time.Time`
Example:
```template
{{ now }}
@ -654,15 +547,45 @@ Example of a query to print a newline per queries stored as a json array in the
## toDate
`toDate` parses a formatted string and returns the time value it represents.
Parses a formatted string and returns the time value it represents using the local timezone of the server running Loki.
For more consistency between Loki installations, it's recommended to use `toDateInZone`
The format string must use the exact date as defined in the [golang datetime layout](https://pkg.go.dev/time#pkg-constants)
Signature: `toDate(fmt, str string) time.Time`
Examples:
```template
{{ toDate "2006-01-02" "2021-11-02" }}
{{ .foo | toDate "2006-01-02T15:04:05.999999999Z" }}
```
## toDateInZone
Parses a formatted string and returns the time value it represents in the provided timezone.
The format string must use the exact date as defined in the [golang datetime layout](https://pkg.go.dev/time#pkg-constants)
The timezone value can be `Local`, `UTC`, or any of the IANA Time Zone database values
Signature: `toDateInZone(fmt, zone, str string) time.Time`
Examples:
```template
{{ toDateInZone "2006-01-02" "UTC" "2021-11-02" }}
{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" }}
```
## date
`date` returns a textual representation of the time value formatted according to the provided [golang datetime layout](https://pkg.go.dev/time#pkg-constants).
Returns a textual representation of the time value formatted according to the provided [golang datetime layout](https://pkg.go.dev/time#pkg-constants).
Signature: `date(fmt string, date interface{}) string`
Example:
```template
{{ date "2006-01-02" now }}
@ -670,10 +593,15 @@ Example of a query to print a newline per queries stored as a json array in the
## unixEpoch
`unixEpoch` returns the number of seconds elapsed since January 1, 1970 UTC.
Returns the number of seconds elapsed since January 1, 1970 UTC.
Signature: `unixEpoch(date time.Time) string`
Examples:
```template
{{ unixEpoch now }}
{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpoch }}
```
Example of a query to filter Loki querier jobs which create time is 1 day before:
@ -681,9 +609,35 @@ Example of a query to filter Loki querier jobs which create time is 1 day before
{job="loki/querier"} | label_format nowEpoch=`{{(unixEpoch now)}}`,createDateEpoch=`{{unixEpoch (toDate "2006-01-02" .createDate)}}` | label_format dateTimeDiff="{{sub .nowEpoch .createDateEpoch}}" | dateTimeDiff > 86400
```
## unixEpochMillis
Returns the number of milliseconds elapsed since January 1, 1970 UTC.
Signature: `unixEpochMillis(date time.Time) string`
Examples:
```template
{{ unixEpochMillis now }}
{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpochMillis }}
```
## unixEpochNanos
Returns the number of nanoseconds elapsed since January 1, 1970 UTC.
Signature: `unixEpochNanos(date time.Time) string`
Examples:
```template
{{ unixEpochNanos now }}
{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpochNanos }}
```
## default
`default` checks whether the string(`src`) is set, and returns default(`d`) if not set.
Checks whether the string(`src`) is set, and returns default(`d`) if not set.
Signature: `default(d string, src string) string`
@ -701,7 +655,7 @@ Example of a query to print a `-` if the `http_request_headers_x_forwarded_for`
## count
`count` counts occurrences of the regex (`regex`) in (`src`).
Counts occurrences of the regex (`regex`) in (`src`).
Signature: `count(regex string, src string) int`
@ -719,11 +673,9 @@ Example of a query to print how many times XYZ occurs in a line:
## urlencode
Use this function to encode the URL(s) in log messages.
Signature:
Use this function to [urlencode](https://en.wikipedia.org/wiki/URL_encoding) a string.
`urlencode(string) string`
Signature: `urlencode(string) string`
Examples:
@ -734,11 +686,9 @@ Examples:
## urldecode
Use this function to decode the URL(s) in log messages.
Use this function to [urldecode](https://en.wikipedia.org/wiki/URL_encoding) a string.
Signature:
`urldecode(string) string`
Signature: `urldecode(string) string`
Examples:
@ -746,3 +696,66 @@ Examples:
"{{ .request_url | urldecode }}"
`{{ urldecode .request_url}}`
```
## b64enc
Base64 encode a string.
Signature: `b64enc(string) string`
Examples:
```template
"{{ .foo | b64enc }}"
`{{ b64enc .foo }}`
```
## b64dec
Base64 decode a string.
Signature: `b64dec(string) string`
Examples:
```template
"{{ .foo | b64dec }}"
`{{ b64dec .foo }}`
```
## bytes
Convert a humanized byte string to bytes using [go-humanize](https://pkg.go.dev/github.com/dustin/go-humanize#ParseBytes)
Signature: `bytes(string) string`
Examples:
```template
"{{ .foo | bytes }}"
`{{ bytes .foo }}`
```
## duration
An alias for `duration_seconds`
Examples:
```template
"{{ .foo | duration }}"
`{{ duration .foo }}`
```
## duration_seconds
Convert a humanized time duration to seconds using [time.ParseDuration](https://pkg.go.dev/time#ParseDuration)
Signature: `duration_seconds(string) float64`
Examples:
```template
"{{ .foo | duration_seconds }}"
`{{ duration_seconds .foo }}`
```

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"net/url"
"strconv"
"strings"
"text/template"
"text/template/parse"
@ -58,12 +59,20 @@ var (
matches := r.FindAllStringIndex(s, -1)
return len(matches), nil
},
"urldecode": url.QueryUnescape,
"urlencode": url.QueryEscape,
"urldecode": url.QueryUnescape,
"urlencode": url.QueryEscape,
"bytes": convertBytes,
"duration": convertDuration,
"duration_seconds": convertDuration,
"unixEpochMillis": unixEpochMillis,
"unixEpochNanos": unixEpochNanos,
"toDateInZone": toDateInZone,
}
// sprig template functions
templateFunctions = []string{
"b64enc",
"b64dec",
"lower",
"upper",
"title",
@ -121,6 +130,23 @@ func addLineAndTimestampFunctions(currLine func() string, currTimestamp func() i
return functions
}
func unixEpochMillis(date time.Time) string {
return strconv.FormatInt(date.UnixMilli(), 10)
}
func unixEpochNanos(date time.Time) string {
return strconv.FormatInt(date.UnixNano(), 10)
}
func toDateInZone(fmt, zone, str string) time.Time {
loc, err := time.LoadLocation(zone)
if err != nil {
loc, _ = time.LoadLocation("UTC")
}
t, _ := time.ParseInLocation(fmt, str, loc)
return t
}
func init() {
sprigFuncMap := sprig.GenericFuncMap()
for _, v := range templateFunctions {

@ -385,6 +385,87 @@ func Test_lineFormatter_Format(t *testing.T) {
},
nil,
},
{
"bytes 1",
newMustLineFormatter("{{ .foo | bytes }}"),
labels.Labels{{Name: "foo", Value: "3 kB"}},
1656353124120000000,
[]byte("3000"),
labels.Labels{{Name: "foo", Value: "3 kB"}},
[]byte("1"),
},
{
"bytes 2",
newMustLineFormatter("{{ .foo | bytes }}"),
labels.Labels{{Name: "foo", Value: "3MB"}},
1656353124120000000,
[]byte("3e+06"),
labels.Labels{{Name: "foo", Value: "3MB"}},
[]byte("1"),
},
{
"duration 1",
newMustLineFormatter("{{ .foo | duration }}"),
labels.Labels{{Name: "foo", Value: "3ms"}},
1656353124120000000,
[]byte("0.003"),
labels.Labels{{Name: "foo", Value: "3ms"}},
[]byte("1"),
},
{
"duration 2",
newMustLineFormatter("{{ .foo | duration_seconds }}"),
labels.Labels{{Name: "foo", Value: "3m10s"}},
1656353124120000000,
[]byte("190"),
labels.Labels{{Name: "foo", Value: "3m10s"}},
[]byte("1"),
},
{
"toDateInZone",
newMustLineFormatter("{{ .foo | toDateInZone \"2006-01-02T15:04:05.999999999Z\" \"UTC\" | unixEpochMillis }}"),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}},
1656353124120000000,
[]byte("1678411960340"),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}},
[]byte("1"),
},
{
"unixEpochMillis",
newMustLineFormatter("{{ .foo | toDateInZone \"2006-01-02T15:04:05.999999999Z\" \"UTC\" | unixEpochMillis }}"),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}},
1656353124120000000,
[]byte("1678411960340"),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}},
[]byte("1"),
},
{
"unixEpochNanos",
newMustLineFormatter("{{ .foo | toDateInZone \"2006-01-02T15:04:05.999999999Z\" \"UTC\" | unixEpochNanos }}"),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}},
1656353124120000000,
[]byte("1678411960340485723"),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}},
[]byte("1"),
},
{
"base64encode",
newMustLineFormatter("{{ .foo | b64enc }}"),
labels.Labels{{Name: "foo", Value: "i'm a string, encode me!"}},
1656353124120000000,
[]byte("aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"),
labels.Labels{{Name: "foo", Value: "i'm a string, encode me!"}},
[]byte("1"),
},
{
"base64decode",
newMustLineFormatter("{{ .foo | b64dec }}"),
labels.Labels{{Name: "foo", Value: "aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"}},
1656353124120000000,
[]byte("i'm a string, encode me!"),
labels.Labels{{Name: "foo", Value: "aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"}},
[]byte("1"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -512,6 +593,87 @@ func Test_labelsFormatter_Format(t *testing.T) {
{Name: "count", Value: "0"},
},
},
{
"bytes 1",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | bytes }}")}),
labels.Labels{{Name: "foo", Value: "3 kB"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "3 kB"},
{Name: "bar", Value: "3000"},
},
},
{
"bytes 2",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | bytes }}")}),
labels.Labels{{Name: "foo", Value: "3MB"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "3MB"},
{Name: "bar", Value: "3e+06"},
},
},
{
"duration 1",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | duration }}")}),
labels.Labels{{Name: "foo", Value: "3ms"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "3ms"},
{Name: "bar", Value: "0.003"},
},
},
{
"duration 2",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | duration }}")}),
labels.Labels{{Name: "foo", Value: "3m10s"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "3m10s"},
{Name: "bar", Value: "190"},
},
},
{
"toDateInZone",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | toDateInZone \"2006-01-02T15:04:05.999999999Z\" \"UTC\" | unixEpochMillis }}")}),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"},
{Name: "bar", Value: "1678411960340"},
},
},
{
"unixEpochMillis",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | toDateInZone \"2006-01-02T15:04:05.999999999Z\" \"UTC\" | unixEpochMillis }}")}),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"},
{Name: "bar", Value: "1678411960340"},
},
},
{
"unixEpochNanos",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | toDateInZone \"2006-01-02T15:04:05.999999999Z\" \"UTC\" | unixEpochNanos }}")}),
labels.Labels{{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "2023-03-10T01:32:40.340485723Z"},
{Name: "bar", Value: "1678411960340485723"},
},
},
{
"base64encode",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | b64enc }}")}),
labels.Labels{{Name: "foo", Value: "i'm a string, encode me!"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "i'm a string, encode me!"},
{Name: "bar", Value: "aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"},
},
},
{
"base64decode",
mustNewLabelsFormatter([]LabelFmt{NewTemplateLabelFmt("bar", "{{ .foo | b64dec }}")}),
labels.Labels{{Name: "foo", Value: "aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"}, {Name: "bar", Value: "blop"}},
labels.Labels{
{Name: "foo", Value: "aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"},
{Name: "bar", Value: "i'm a string, encode me!"},
},
},
}
for _, tt := range tests {

Loading…
Cancel
Save