mirror of
https://github.com/prometheus/prometheus.git
synced 2025-08-05 13:47:10 +02:00
Add template functions to support various use cases. (#16619)
Presumably, this will help with Loki alerts, but the added functionality is also generally useful. For one, this enables `parseDuration` to also accept negative duration (as that's something that is also used in PromQL by now). This also adds a function `now` to return the evaluation time of the template (as seconds since epoch AKA Unix time) and a function `toDuration` (akin to `toTime`), which creates a Go `time.Duration` from a duration in seconds. --------- Signed-off-by: Dmitry Ponomaryov <me@halje.ru> Signed-off-by: Dmitry Ponomaryov <iamhalje@gmail.com>
This commit is contained in:
parent
846acc10bb
commit
b18272a572
@ -55,8 +55,10 @@ If functions are used in a pipeline, the pipeline value is passed as the last ar
|
||||
| humanize1024 | number or string | string | Like `humanize`, but uses 1024 as the base rather than 1000. |
|
||||
| humanizeDuration | number or string | string | Converts a duration in seconds to a more readable format. |
|
||||
| humanizePercentage | number or string | string | Converts a ratio value to a fraction of 100. |
|
||||
| humanizeTimestamp | number or string | string | Converts a Unix timestamp in seconds to a more readable format. |
|
||||
| toTime | number or string | *time.Time | Converts a Unix timestamp in seconds to a time.Time. |
|
||||
| humanizeTimestamp | number or string | string | Converts a Unix timestamp in seconds to a more readable format. |
|
||||
| toTime | number or string | *time.Time | Converts a Unix timestamp in seconds to a time.Time. |
|
||||
| toDuration | number or string | *time.Duration | Converts a duration in seconds to a time.Duration. |
|
||||
| now | none | float64 | Returns the Unix timestamp in seconds at the time of the template evaluation. |
|
||||
|
||||
Humanizing functions are intended to produce reasonable output for consumption
|
||||
by humans, and are not guaranteed to return the same results between Prometheus
|
||||
|
@ -263,6 +263,17 @@ func NewTemplateExpander(
|
||||
|
||||
return floatToTime(v)
|
||||
},
|
||||
"toDuration": func(i interface{}) (*time.Duration, error) {
|
||||
v, err := common_templates.ConvertToFloat(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d := time.Duration(v * float64(time.Second))
|
||||
return &d, nil
|
||||
},
|
||||
"now": func() float64 {
|
||||
return float64(timestamp) / 1000.0
|
||||
},
|
||||
"pathPrefix": func() string {
|
||||
return externalURL.Path
|
||||
},
|
||||
@ -270,7 +281,7 @@ func NewTemplateExpander(
|
||||
return externalURL.String()
|
||||
},
|
||||
"parseDuration": func(d string) (float64, error) {
|
||||
v, err := model.ParseDuration(d)
|
||||
v, err := model.ParseDurationAllowNegative(d)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/model/histogram"
|
||||
@ -467,6 +468,31 @@ func TestTemplateExpansion(t *testing.T) {
|
||||
text: `{{ ("1435065584.128" | toTime).Format "2006" }}`,
|
||||
output: "2015",
|
||||
},
|
||||
{
|
||||
// toDuration - input as float64 seconds, returns *time.Duration.
|
||||
text: `{{ (1800 | toDuration).String }}`,
|
||||
output: "30m0s",
|
||||
},
|
||||
{
|
||||
// toDuration - input as string seconds, returns *time.Duration.
|
||||
text: `{{ ("1800" | toDuration).String }}`,
|
||||
output: "30m0s",
|
||||
},
|
||||
{
|
||||
// now - returns fixed timestamp as float64 seconds.
|
||||
text: `{{ now }}`,
|
||||
output: "1.353755652e+09",
|
||||
},
|
||||
{
|
||||
// now - returns fixed timestamp converted to formatted time string.
|
||||
text: `{{ (now | toTime).Format "Mon Jan 2 15:04:05 2006" }}`,
|
||||
output: "Sat Nov 24 11:14:12 2012",
|
||||
},
|
||||
{
|
||||
// returns Unix milliseconds timestamp for 30 minutes ago.
|
||||
text: `{{ ("-30m" | parseDuration | toDuration | (now | toTime).Add).UnixMilli }}`,
|
||||
output: "1353753852000",
|
||||
},
|
||||
{
|
||||
// Title.
|
||||
text: "{{ \"aa bb CC\" | title }}",
|
||||
@ -514,10 +540,15 @@ func TestTemplateExpansion(t *testing.T) {
|
||||
output: "http://testhost:9090/path/prefix",
|
||||
},
|
||||
{
|
||||
// parseDuration (using printf to ensure the return is a string).
|
||||
// parseDuration with positive duration (using printf to ensure the return is a string).
|
||||
text: "{{ printf \"%0.2f\" (parseDuration \"1h2m10ms\") }}",
|
||||
output: "3720.01",
|
||||
},
|
||||
{
|
||||
// parseDuration with negative duration (using printf to ensure the return is a string).
|
||||
text: "{{ printf \"%0.2f\" (parseDuration \"-1h2m10ms\") }}",
|
||||
output: "-3720.01",
|
||||
},
|
||||
{
|
||||
// Simple hostname.
|
||||
text: "{{ \"foo.example.com\" | stripDomain }}",
|
||||
@ -579,7 +610,7 @@ func testTemplateExpansion(t *testing.T, scenarios []scenario) {
|
||||
}
|
||||
var result string
|
||||
var err error
|
||||
expander := NewTemplateExpander(context.Background(), s.text, "test", s.input, 0, queryFunc, extURL, s.options)
|
||||
expander := NewTemplateExpander(context.Background(), s.text, "test", s.input, model.Time(1353755652000), queryFunc, extURL, s.options)
|
||||
if s.html {
|
||||
result, err = expander.ExpandHTML(nil)
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user