From 7ae79070df5e750e2d73e837054d50b72c744364 Mon Sep 17 00:00:00 2001 From: J Stickler Date: Tue, 1 Oct 2024 12:26:05 -0400 Subject: [PATCH] docs: Reorganize Query Templates page (#14138) (#14336) --- docs/sources/query/template_functions.md | 787 +++++++++++++---------- 1 file changed, 430 insertions(+), 357 deletions(-) diff --git a/docs/sources/query/template_functions.md b/docs/sources/query/template_functions.md index 9ba67620a488e..f5700976ea497 100644 --- a/docs/sources/query/template_functions.md +++ b/docs/sources/query/template_functions.md @@ -1,26 +1,31 @@ --- -title: Template functions -menuTItle: -description: Describes functions that are supported by the Go text template. -aliases: +title: LogQL template functions +menuTItle: Template functions +description: Describes query functions that are supported by the Go text template. +aliases: - ../logql/template_functions/ weight: 30 --- -# Template functions +# LogQL template functions +The Go templating language is embedded in the Loki query language, LogQL. The [text template](https://golang.org/pkg/text/template) format used in `| line_format` and `| label_format` support the usage of functions. -All labels are added as variables in the template engine. They can be referenced using they label name prefixed by a `.`(e.g `.label_name`). For example the following template will output the value of the path label: +{{< admonition type="note" >}} +In the examples below we use backticks to quote the template strings. This is because some template strings contain double quotes, and using backticks lets us avoid escaping the double quotes. +If you are using a different quoting style, you may need to escape the double quotes. +{{< /admonition >}} -```template -{{ .path }} -``` +For more information, refer to the [Go template documentation](https://pkg.go.dev/text/template). + +Additionally you can also access the log line using the `__line__` function and the timestamp using the `__timestamp__` function. + +## Template pipeline syntax -Additionally you can also access the log line using the [`__line__`](#__line__) function and the timestamp using the [`__timestamp__`](#__timestamp__) function. +A pipeline is a possibly chained sequence of "commands". A command is a simple value (argument) or a function or method call, possibly with multiple arguments. A pipeline may be "chained" by separating a sequence of commands with pipeline characters '|'. In a chained pipeline, the result of each command is passed as the last argument of the following command. The output of the final command in the pipeline is the value of the pipeline. You can take advantage of [pipeline](https://golang.org/pkg/text/template/#hdr-Pipelines) to join together multiple functions. -In a chained pipeline, the result of each command is passed as the last argument of the following command. Example: @@ -33,14 +38,26 @@ For function that returns a `bool` such as `contains`, `eq`, `hasPrefix` and `ha Example: ```template -{{ if and (contains "he" "hello") (contains "llo" "hello") }} yes {{end}} -{{ if or (contains "he" "hello") (contains("llo" "hello") }} yes {{end}} -{{ if contains .err "ErrTimeout" }} timeout {{else if contains "he" "hello"}} yes {{else}} no {{end}} +`{{ if and (contains "he" "hello") (contains "llo" "hello") }} yes {{end}}` +`{{ if or (contains "he" "hello") (contains("llo" "hello") }} yes {{end}}` +`{{ if contains .err "ErrTimeout" }} timeout {{else if contains "he" "hello"}} yes {{else}} no {{end}}` +``` + +## Built-in variables for log line properties + +These variables provide a way of referencing something from the log line when writing a template expression. + +### .label_name + +All labels from the Log line are added as variables in the template engine. They can be referenced using the label name prefixed by a `.`(for example,`.label_name`). For example the following template will output the value of the `path` label: + +```template +`{{ .path }}` ``` -## __line__ +### __line__ -This function returns the current log line. +The `__line__` function returns the original log line without any modifications. Signature: `line() string` @@ -51,9 +68,9 @@ Examples: `{{ __line__ }}` ``` -## __timestamp__ +### __timestamp__ -This function returns the current log lines timestamp. +The `__timestamp__` function returns the current log line's timestamp. Signature: `timestamp() time.Time` @@ -63,203 +80,281 @@ Signature: `timestamp() time.Time` `{{ __timestamp__ | unixEpoch }}` ``` -See the blog: [Parsing and formatting date/time in Go](https://www.pauladamsmith.com/blog/2011/05/go_time.html) for more information. +For more information, refer to the blog [Parsing and formatting date/time in Go](https://www.pauladamsmith.com/blog/2011/05/go_time.html). -## regexReplaceAll and regexReplaceAllLiteral +## Date and time -`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. +You can use the following functions to manipulate dates and times when building LogQL queries. + +### date + +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 -`{{ regexReplaceAll "(a*)bc" .some_label "${1}a" }}` +`{{ date "2006-01-02" now }}` ``` -`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. +### duration -Example: +An alias for `duration_seconds` + +Examples: ```template -`{{ regexReplaceAllLiteral "(ts=)" .timestamp "timestamp=" }}` +`{{ .foo | duration }}` +`{{ duration .foo }}` ``` -## lower +### duration_seconds -Use this function to convert to lower case. +Convert a humanized time duration to seconds using [time.ParseDuration](https://pkg.go.dev/time#ParseDuration) -Signature: `lower(string) string` +Signature: `duration_seconds(string) float64` Examples: ```template -"{{ .request_method | lower }}" -`{{ lower "HELLO"}}` +`{{ .foo | duration_seconds }}` +`{{ duration_seconds .foo }}` ``` -The last example will return `hello`. +### now -## upper +Returns the current time in the local timezone of the Loki server. -Use this function to convert to upper case. +Signature: `Now() time.Time` -Signature: `upper(string) string` +Example: + +```template +`{{ now }}` +``` + +### toDate + +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 -"{{ .request_method | upper }}" -`{{ upper "hello"}}` +`{{ toDate "2006-01-02" "2021-11-02" }}` +`{{ .foo | toDate "2006-01-02T15:04:05.999999999Z" }}` ``` -This results in `HELLO`. +### toDateInZone -## title +Parses a formatted string and returns the time value it represents in the provided timezone. -Convert to title case. +The format string must use the exact date as defined in the [golang datetime layout](https://pkg.go.dev/time#pkg-constants) -Signature: `title(string) string` +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 -"{{.request_method | title}}" -`{{ title "hello world"}}` +`{{ toDateInZone "2006-01-02" "UTC" "2021-11-02" }}` +`{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" }}` ``` -The last example will return `Hello World`. - -## trunc +### unixEpoch -Truncate a string and add no suffix. +Returns the number of seconds elapsed since January 1, 1970 UTC. -Signature: `trunc(count int,value string) string` +Signature: `unixEpoch(date time.Time) string` Examples: ```template -"{{ .path | trunc 2 }}" -`{{ trunc 5 "hello world"}}` // output: hello -`{{ trunc -5 "hello world"}}` // output: world +`{{ unixEpoch now }}` +`{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpoch }}` ``` -## substr +Example of a query to filter Loki querier jobs which create time is 1 day before: -Get a substring from a string. +```logql +{job="loki/querier"} | label_format nowEpoch=`{{(unixEpoch now)}}`,createDateEpoch=`{{unixEpoch (toDate "2006-01-02" .createDate)}}` | label_format dateTimeDiff=`{{sub .nowEpoch .createDateEpoch}}` | dateTimeDiff > 86400 +``` -Signature: `substr(start int,end int,value string) string` +### unixEpochMillis -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:] -Otherwise, this calls value[start, end]. +Returns the number of milliseconds elapsed since January 1, 1970 UTC. + +Signature: `unixEpochMillis(date time.Time) string` Examples: ```template -"{{ .path | substr 2 5 }}" -`{{ substr 0 5 "hello world"}}` // output: hello -`{{ substr 6 11 "hello world"}}` // output: world +`{{ unixEpochMillis now }}` +`{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpochMillis }}` ``` -## replace +### unixEpochNanos -This function performs simple string replacement. +Returns the number of nanoseconds elapsed since January 1, 1970 UTC. -Signature: `replace(old string, new string, src string) string` +Signature: `unixEpochNanos(date time.Time) string` -It takes three arguments: +Examples: -- `old` string to replace -- `new` string to replace with -- `src` source string +```template +`{{ unixEpochNanos now }}` +`{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpochNanos }}` +``` + +### unixToTime + +Converts the string epoch to the time value it represents. Epoch times in days, seconds, milliseconds, microseconds and nanoseconds are supported. + +Signature: `unixToTime(epoch string) time.Time` Examples: -```template -{{ .cluster | replace "-cluster" "" }} -{{ replace "hello" "world" "hello world" }} +Consider the following log line `{"from": "1679577215","to":"1679587215","message":"some message"}`. To print the `from` field as human readable add the following at the end of the LogQL query: + +```logql +... | json | line_format `from="{{date "2006-01-02" (unixToTime .from)}}"` ``` -The last example will return `world world`. +## String manipulation -## trim +You can use the following templates to manipulate strings when building LogQL Queries. -The trim function removes space from either side of a string. +### alignLeft -Signature: `trim(string) string` +Use this function to format a string to a fixed with, aligning the content to the left. + +Signature: `alignLeft(count int, src string) string` Examples: ```template -{{ .ip | trim }} -{{ trim " hello " }} // output: hello +`{{ alignLeft 5 "hello world"}}` // output: "hello" +`{{ alignLeft 5 "hi"}}` // output: "hi " ``` -## trimAll +### alignRight -Use this function to remove given characters from the front or back of a string. +Use this function to format a string to a fixed with, aligning the content to the right. -Signature: `trimAll(chars string,src string) string` +Signature: `alignRight(count int, src string) string` Examples: ```template -{{ .path | trimAll "/" }} -{{ trimAll "$" "$5.00" }} // output: 5.00 +`{{ alignRight 5 "hello world"}}` // output: "world" +`{{ alignRight 5 "hi"}}` // output: " hi" ``` -## trimSuffix +### b64enc -Use this function to trim just the suffix from a string. +Base64 encode a string. -Signature: `trimSuffix(suffix string, src string) string` +Signature: `b64enc(string) string` Examples: ```template -{{ .path | trimSuffix "/" }} -{{ trimSuffix "-" "hello-" }} // output: hello +`{{ .foo | b64enc }}` +`{{ b64enc .foo }}` ``` -## trimPrefix +### b64dec -Use this function to trim just the prefix from a string. +Base64 decode a string. -Signature: `trimPrefix(prefix string, src string) string` +Signature: `b64dec(string) string` Examples: ```template -{{ .path | trimPrefix "/" }} -{{ trimPrefix "-" "-hello" }} // output: hello +`{{ .foo | b64dec }}` +`{{ b64dec .foo }}` ``` -## alignLeft +### bytes -Use this function to format a string to a fixed with, aligning the content to the left. +Convert a humanized byte string to bytes using go-humanize. Durations can be turned into strings such as "3 days ago", numbers +representing sizes like 82854982 into useful strings like, "83 MB" or +"79 MiB" -Signature: `alignLeft(count int, src string) string` +Signature: `bytes(string) string` Examples: ```template -`{{ alignLeft 5 "hello world"}}` // output: "hello" -`{{ alignLeft 5 "hi"}}` // output: "hi " +`{{ .foo | bytes }}` +`{{ bytes .foo }}` ``` -## alignRight +### default -Use this function to format a string to a fixed with, aligning the content to the right. +Enables outputting a default value if the source string is otherwise empty. If the 'src' parameter is not empty, this function returns the value of 'src'. Useful for JSON fields that can be missing, like HTTP headers in a log line that aren't required, as in the following example: -Signature: `alignRight(count int, src string) string` +```logql +{job="access_log"} | json | line_format `{{.http_request_headers_x_forwarded_for | default "-"}}` +``` + +Signature: `default(d string, src string) string` Examples: ```template -`{{ alignRight 5 "hello world"}}` // output: "world" -`{{ alignRight 5 "hi"}}` // output: " hi" +`{{ default "-" "" }}` // output: - +`{{ default "-" "foo" }}` // output: foo ``` -## indent +Example of a query to print a `-` if the `http_request_headers_x_forwarded_for` label is empty: + +```logql +{job="access_log"} | json | line_format `{{.http_request_headers_x_forwarded_for | default "-"}}` +``` + +### fromJson + +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{}` + +Example: + +```template +`{{fromJson "{\"foo\": 55}"}}` +``` + +Example of a query to print a newline per queries stored as a json array in the log line: + +```logql +{job="loki/querier"} |= "finish in prometheus" | logfmt | line_format `{{ range $q := fromJson .queries }} {{ $q.query }} {{ end }}` +``` + +### lower + +Use this function to convert to lower case. + +Signature: `lower(string) string` + +Examples: + +```template +"{{ .request_method | lower }}" +`{{ lower "HELLO"}}` +``` + +The last example will return `hello`. + +### indent The indent function indents every line in a given string to the specified indent width. This is useful when aligning multi-line strings. @@ -268,12 +363,12 @@ Signature: `indent(spaces int,src string) string` Example: ```template -{{ indent 4 .query }} +`{{ indent 4 .query }}` ``` This indents each line contained in the `.query` by four (4) spaces. -## nindent +### nindent The nindent function is the same as the indent function, but prepends a new line to the beginning of the string. @@ -282,12 +377,12 @@ Signature: `nindent(spaces int,src string) string` Example: ```template -{{ nindent 4 .query }} +`{{ nindent 4 .query }}` ``` This will indent every line of text by 4 space characters and add a new line to the beginning. -## repeat +### repeat Use this function to repeat a string multiple times. @@ -296,531 +391,509 @@ Signature: `repeat(c int,value string) string` Example: ```template -{{ repeat 3 "hello" }} // output: hellohellohello +`{{ repeat 3 "hello" }}` // output: hellohellohello ``` -## contains +### printf -Use this function to test to see if one string is contained inside of another. +Use this function to format a string in a custom way. For more information about the syntax, refer to the [Go documentation](https://pkg.go.dev/fmt). -Signature: `contains(src string, s string,) bool` +Signature: `printf(format string, a ...interface{})` Examples: ```template -{{ if contains "ErrTimeout" .err }} timeout {{end}} -{{ if contains "he" "hello" }} yes {{end}} -``` - -## eq - -Use this function to test to see if one string has exact matching inside of another. - -Signature: `eq(src string, s string) bool` +`{{ printf "The IP address was %s" .remote_addr }}` // output: The IP address was 129.168.1.1 -Examples: +`{{ printf "%-40.40s" .request_uri}} {{printf "%-5.5s" .request_method}}` +// output: +// /a/509965767/alternative-to-my-mtg.html GET +// /id/609259548/hpr.html GET +``` ```template -{{ if eq "ErrTimeout" .err}} timeout {{end}} -{{ if eq "hello" "hello" }} yes {{end}} +line_format "\"|\" {{printf \"%15.15s\" .ClientHost}} \"|\"" ``` -## hasPrefix and hasSuffix +### replace -The `hasPrefix` and `hasSuffix` functions test whether a string has a given prefix or suffix. +This function performs simple string replacement. -Signatures: +Signature: `replace(old string, new string, src string) string` -- `hasPrefix(prefix string, src string) bool` -- `hasSuffix(suffix string, src string) bool` +It takes three arguments: + +- `old` string to replace +- `new` string to replace with +- `src` source string Examples: ```template -{{ if hasSuffix .err "Timeout" }} timeout {{end}} -{{ if hasPrefix "he" "hello" }} yes {{end}} +{{ .cluster | replace "-cluster" "" }} +{{ replace "hello" "world" "hello world" }} ``` -## add +The last example will return `world world`. -Sum numbers. Supports multiple numbers +### substr -Signature: `func(i ...interface{}) int64` +Get a substring from a string. -Example: +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:] +Otherwise, this calls value[start, end]. + +Examples: ```template -{{ add 3 2 5 }} // output: 10 +`{{ .path | substr 2 5 }}` +`{{ substr 0 5 "hello world"}}` // output: hello +`{{ substr 6 11 "hello world"}}` // output: world ``` -## sub +### title -Subtract numbers. +Convert to title case. -Signature: `func(a, b interface{}) int64` +Signature: `title(string) string` -Example: +Examples: ```template -{{ sub 5 2 }} // output: 3 +`{{.request_method | title}}` +`{{ title "hello world"}}` ``` -## mul +The last example will return `Hello World`. -Multiply numbers. Supports multiple numbers. +### trim -Signature: `func(a interface{}, v ...interface{}) int64` +The trim function removes space from either side of a string. -Example: +Signature: `trim(string) string` + +Examples: ```template -{{ mul 5 2 3}} // output: 30 +{{ .ip | trim }} +{{ trim " hello " }} // output: hello ``` -## div +### trimAll -Integer divide numbers. +Use this function to remove given characters from the front or back of a string. -Signature: `func(a, b interface{}) int64` +Signature: `trimAll(chars string,src string) string` -Example: +Examples: ```template -{{ div 10 2}} // output: 5 +{{ .path | trimAll "/" }} +{{ trimAll "$" "$5.00" }} // output: 5.00 ``` -## addf +### trimPrefix -Sum numbers. Supports multiple numbers. +Use this function to trim just the prefix from a string. -Signature: `func(i ...interface{}) float64` +Signature: `trimPrefix(prefix string, src string) string` -Example: +Examples: ```template -{{ addf 3.5 2 5 }} // output: 10.5 +{{ .path | trimPrefix "/" }} +{{ trimPrefix "-" "-hello" }} // output: hello ``` -## subf +### trimSuffix -Subtract numbers. Supports multiple numbers. +Use this function to trim just the suffix from a string. -Signature: `func(a interface{}, v ...interface{}) float64` +Signature: `trimSuffix(suffix string, src string) string` -Example: +Examples: ```template -{{ subf 5.5 2 1.5 }} // output: 2 +`{{ .path | trimSuffix "/" }}` +`{{ trimSuffix "-" "hello-" }}` // output: hello ``` -## mulf +### trunc -Multiply numbers. Supports multiple numbers +Truncate a string and add no suffix. -Signature: `func(a interface{}, v ...interface{}) float64` +Signature: `trunc(count int,value string) string` -Example: +Examples: ```template -{{ mulf 5.5 2 2.5 }} // output: 27.5 +`{{ .path | trunc 2 }}` +`{{ trunc 5 "hello world"}}` // output: hello +`{{ trunc -5 "hello world"}}` // output: world ``` -## divf +### upper -Divide numbers. Supports multiple numbers. +Use this function to convert to upper case. -Signature: `func(a interface{}, v ...interface{}) float64` +Signature: `upper(string) string` -Example: +Examples: ```template -{{ divf 10 2 4}} // output: 1.25 +`{ .request_method | upper }}` +`{{ upper "hello"}}` ``` -## mod +This results in `HELLO`. -Modulo wit mod. +### urlencode -Signature: `func(a, b interface{}) int64` +Use this function to [urlencode](https://en.wikipedia.org/wiki/URL_encoding) a string. -Example: +Signature: `urlencode(string) string` + +Examples: ```template -{{ mod 10 3}} // output: 1 +`{{ .request_url | urlencode }}` +`{{ urlencode .request_url}}` ``` -## max +### urldecode -Return the largest of a series of integers: +Use this function to [urldecode](https://en.wikipedia.org/wiki/URL_encoding) a string. -Signature: `max(a interface{}, i ...interface{}) int64` +Signature: `urldecode(string) string` -Example: +Examples: ```template -{{ max 1 2 3 }} //output 3 +`{{ .request_url | urldecode }}` +`{{ urldecode .request_url}}` ``` -## min +## Logical functions -Return the smallest of a series of integers. +You can use the following logical functions to compare strings when building a template expression. -Signature: `min(a interface{}, i ...interface{}) int64` +### contains -Example: +Use this function to test to see if one string is contained inside of another. + +Signature: `contains(src string, s string,) bool` + +Examples: ```template -{{ min 1 2 3 }} //output 1 +{{ if contains "ErrTimeout" .err }} timeout {{end}} +{{ if contains "he" "hello" }} yes {{end}} ``` -## maxf +### eq -Return the largest of a series of floats: +Use this function to test to see if one string has exact matching inside of another. -Signature: `maxf(a interface{}, i ...interface{}) float64` +Signature: `eq(src string, s string) bool` -Example: +Examples: ```template -{{ maxf 1 2.5 3 }} //output 3 +{{ if eq "ErrTimeout" .err}} timeout {{end}} +{{ if eq "hello" "hello" }} yes {{end}} ``` -## minf +### hasPrefix and hasSuffix -Return the smallest of a series of floats. +The `hasPrefix` and `hasSuffix` functions test whether a string has a given prefix or suffix. -Signature: `minf(a interface{}, i ...interface{}) float64` +Signatures: -Example: +- `hasPrefix(prefix string, src string) bool` +- `hasSuffix(suffix string, src string) bool` + +Examples: ```template -{{ minf 1 2.5 3 }} //output 1.5 +{{ if hasSuffix .err "Timeout" }} timeout {{end}} +{{ if hasPrefix "he" "hello" }} yes {{end}} ``` -## ceil +## Mathematical functions -Returns the greatest float value greater than or equal to input value +You can use the following mathematical functions when writing template expressions. -Signature: `ceil(a interface{}) float64` +### add + +Sum numbers. Supports multiple numbers + +Signature: `func(i ...interface{}) int64` Example: ```template -{{ ceil 123.001 }} //output 124.0 +{{ add 3 2 5 }} // output: 10 ``` -## floor +### addf -Returns the greatest float value less than or equal to input value +Sum floating point numbers. Supports multiple numbers. -Signature: `floor(a interface{}) float64` +Signature: `func(i ...interface{}) float64` Example: ```template -{{ floor 123.9999 }} //output 123.0 +{{ addf 3.5 2 5 }} // output: 10.5 ``` -## round +### ceil -Returns a float value with the remainder rounded to the given number of digits after the decimal point. +Returns the greatest float value greater than or equal to input value -Signature: `round(a interface{}, p int, rOpt ...float64) float64` +Signature: `ceil(a interface{}) float64` Example: ```template -{{ round 123.555555 3 }} //output 123.556 +{{ ceil 123.001 }} //output 124.0 ``` -We can also provide a `roundOn` number as third parameter +### div + +Divide two integers. + +Signature: `func(a, b interface{}) int64` Example: ```template -{{ round 123.88571428571 5 .2 }} //output 123.88572 +`{{ div 10 2}}` // output: 5 ``` -With default `roundOn` of `.5` the above value would be `123.88571` +### divf -## int +Divide floating point numbers. Supports multiple numbers. -Convert value to an int. - -Signature: `toInt(v interface{}) int` +Signature: `func(a interface{}, v ...interface{}) float64` Example: ```template -{{ "3" | int }} //output 3 +`{{ divf 10 2 4}}` // output: 1.25 ``` -## float64 +### float64 -Convert to a float64. +Convert a string to a float64. Signature: `toFloat64(v interface{}) float64` Example: ```template -{{ "3.5" | float64 }} //output 3.5 +`{{ "3.5" | float64 }}` //output 3.5 ``` -## fromJson +### floor -Decodes a JSON document into a structure. If the input cannot be decoded as JSON the function will return an empty string. +Returns the greatest float value less than or equal to input value. -Signature: `fromJson(v string) interface{}` +Signature: `floor(a interface{}) float64` Example: ```template -fromJson "{\"foo\": 55}" -``` - -Example of a query to print a newline per queries stored as a json array in the log line: - -```logql -{job="loki/querier"} |= "finish in prometheus" | logfmt | line_format "{{ range $q := fromJson .queries }} {{ $q.query }} {{ end }}" +{{ floor 123.9999 }} //output 123.0 ``` -## now +### int -Returns the current time in the local timezone of the Loki server. +Convert value to an integer. -Signature: `Now() time.Time` +Signature: `toInt(v interface{}) int` Example: ```template -{{ now }} +`{{ "3" | int }}` //output 3 ``` -## toDate +### max -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) +Return the largest of a series of integers: -Signature: `toDate(fmt, str string) time.Time` +Signature: `max(a interface{}, i ...interface{}) int64` -Examples: +Example: ```template -{{ toDate "2006-01-02" "2021-11-02" }} -{{ .foo | toDate "2006-01-02T15:04:05.999999999Z" }} +`{{ max 1 2 3 }}` //output 3 ``` -## 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) +### maxf -The timezone value can be `Local`, `UTC`, or any of the IANA Time Zone database values +Return the largest of a series of floats: -Signature: `toDateInZone(fmt, zone, str string) time.Time` +Signature: `maxf(a interface{}, i ...interface{}) float64` -Examples: +Example: ```template -{{ toDateInZone "2006-01-02" "UTC" "2021-11-02" }} -{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" }} +`{{ maxf 1 2.5 3 }}` //output 3 ``` -## date +### min -Returns a textual representation of the time value formatted according to the provided [golang datetime layout](https://pkg.go.dev/time#pkg-constants). +Return the smallest of a series of integers. -Signature: `date(fmt string, date interface{}) string` +Signature: `min(a interface{}, i ...interface{}) int64` Example: ```template -{{ date "2006-01-02" now }} +`{{ min 1 2 3 }}`//output 1 ``` -## unixEpoch +### minf -Returns the number of seconds elapsed since January 1, 1970 UTC. +Return the smallest of a series of floats. -Signature: `unixEpoch(date time.Time) string` +Signature: `minf(a interface{}, i ...interface{}) float64` -Examples: +Example: ```template -{{ unixEpoch now }} -{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpoch }} +`{{ minf 1 2.5 3 }}` //output 1.5 ``` -Example of a query to filter Loki querier jobs which create time is 1 day before: -```logql -{job="loki/querier"} | label_format nowEpoch=`{{(unixEpoch now)}}`,createDateEpoch=`{{unixEpoch (toDate "2006-01-02" .createDate)}}` | label_format dateTimeDiff="{{sub .nowEpoch .createDateEpoch}}" | dateTimeDiff > 86400 -``` +### mul -## unixEpochMillis +Multiply numbers. Supports multiple numbers. -Returns the number of milliseconds elapsed since January 1, 1970 UTC. +Signature: `mul(a interface{}, v ...interface{}) int64` -Signature: `unixEpochMillis(date time.Time) string` - -Examples: +Example: ```template -{{ unixEpochMillis now }} -{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpochMillis }} +`{{ mul 5 2 3}}` // output: 30 ``` -## unixEpochNanos +### mulf -Returns the number of nanoseconds elapsed since January 1, 1970 UTC. +Multiply floating numbers. Supports multiple numbers -Signature: `unixEpochNanos(date time.Time) string` +Signature: `mulf(a interface{}, v ...interface{}) float64` -Examples: +Example: ```template -{{ unixEpochNanos now }} -{{ .foo | toDateInZone "2006-01-02T15:04:05.999999999Z" "UTC" | unixEpochNanos }} +`{{ mulf 5.5 2 2.5 }}` // output: 27.5 ``` -## unixToTime +### mod -Converts the string epoch to the time value it represents. Epoch times in days, seconds, milliseconds, microseconds and nanoseconds are supported. +Returns the remainder when number 'a' is divided by number 'b'. -Signature: `unixToTime(epoch string) time.Time` +Signature: `mod(a, b interface{}) int64` -Examples: +Example: -Consider the following log line `{"from": "1679577215","to":"1679587215","message":"some message"}`. To print the `from` field as human readable add the following at the end of the LogQL query: -```logql -... | json | line_format `from="{{date "2006-01-02" (unixToTime .from)}}"` +```template +`{{ mod 10 3}}` // output: 1 ``` -## default +### round -Checks whether the string(`src`) is set, and returns default(`d`) if not set. +Returns a float value with the remainder rounded to the given number of digits after the decimal point. -Signature: `default(d string, src string) string` +Signature: `round(a interface{}, p int, rOpt ...float64) float64` -Examples: +Example: ```template -{{ default "-" "" }} // output: - -{{ default "-" "foo" }} // output: foo -``` - -Example of a query to print a `-` if the `http_request_headers_x_forwarded_for` label is empty: -```logql -{job="access_log"} | json | line_format `{{.http_request_headers_x_forwarded_for | default "-"}}` +{{ round 123.555555 3 }} //output 123.556 ``` -## count - -Counts occurrences of the regex (`regex`) in (`src`). - -Signature: `count(regex string, src string) int` +We can also provide a `roundOn` number as third parameter -Examples: +Example: ```template -{{ count "a|b" "abab" }} // output: 4 -{{ count "o" "foo" }} // output: 2 +{{ round 123.88571428571 5 .2 }} //output 123.88572 ``` -Example of a query to print how many times XYZ occurs in a line: -```logql -{job="xyzlog"} | line_format `{{ __line__ | count "XYZ"}}` -``` +With default `roundOn` of `.5` the above value would be `123.88571` -## urlencode +### sub -Use this function to [urlencode](https://en.wikipedia.org/wiki/URL_encoding) a string. +Subtract one number from another. -Signature: `urlencode(string) string` +Signature: `func(a, b interface{}) int64` -Examples: +Example: ```template -"{{ .request_url | urlencode }}" -`{{ urlencode .request_url}}` +`{{ sub 5 2 }}` // output: 3 ``` -## urldecode +### subf -Use this function to [urldecode](https://en.wikipedia.org/wiki/URL_encoding) a string. +Subtract floating numbers. Supports multiple numbers. -Signature: `urldecode(string) string` +Signature: `func(a interface{}, v ...interface{}) float64` -Examples: +Example: ```template -"{{ .request_url | urldecode }}" -`{{ urldecode .request_url}}` +`{{ subf 5.5 2 1.5 }}` // output: 2 ``` -## b64enc +## Regular expression functions -Base64 encode a string. - -Signature: `b64enc(string) string` +You can use the following functions to perform regular expressions in a template expression. -Examples: +### count -```template -"{{ .foo | b64enc }}" -`{{ b64enc .foo }}` -``` - -## b64dec - -Base64 decode a string. +Counts occurrences of the regex (`regex`) in (`src`). -Signature: `b64dec(string) string` +Signature: `count(regex string, src string) int` Examples: ```template -"{{ .foo | b64dec }}" -`{{ b64dec .foo }}` +{{ count "a|b" "abab" }} // output: 4 +{{ count "o" "foo" }} // output: 2 ``` -## 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: +Example of a query to print how many times XYZ occurs in a line: -```template -"{{ .foo | bytes }}" -`{{ bytes .foo }}` +```logql +{job="xyzlog"} | line_format `{{ __line__ | count "XYZ"}}` ``` -## duration +### regexReplaceAll and regexReplaceAllLiteral -An alias for `duration_seconds` +`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. -Examples: +Signature: regexReplaceAll(regex string, src string, replacement string) +(source) + +Example: ```template -"{{ .foo | duration }}" -`{{ duration .foo }}` +`{{ regexReplaceAll "(a*)bc" .some_label "${1}a" }}` ``` -## duration_seconds - -Convert a humanized time duration to seconds using [time.ParseDuration](https://pkg.go.dev/time#ParseDuration) +`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. -Signature: `duration_seconds(string) float64` +Signature: regexReplaceAllLiteral(regex string, src string, replacement string) -Examples: +Example: ```template -"{{ .foo | duration_seconds }}" -`{{ duration_seconds .foo }}` +`{{ regexReplaceAllLiteral "(ts=)" .timestamp "timestamp=" }}` ```