diff --git a/docs/notifications.md b/docs/notifications.md index 1a70d4aa..52c87e5d 100644 --- a/docs/notifications.md +++ b/docs/notifications.md @@ -97,3 +97,5 @@ templating. | stringSlice | ...string | Returns the passed strings as a slice of strings. | | date | string, time.Time | Returns the text representation of the time in the specified format. For documentation on formats refer to [pkg.go.dev/time](https://pkg.go.dev/time#pkg-constants). | | tz | string, time.Time | Returns the time in the timezone. For example, Europe/Paris. | +| since | time.Time | [time.Duration](https://pkg.go.dev/time#Since), returns the duration of how much time passed from the provided time till the current system time. | +| humanizeDuration | number or string | Returns a human-readable string representing the duration, and the error if it happened. | diff --git a/go.mod b/go.mod index 8b369980..c134a403 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/oklog/run v1.1.0 github.com/oklog/ulid v1.3.1 github.com/prometheus/client_golang v1.19.1 - github.com/prometheus/common v0.52.3 + github.com/prometheus/common v0.54.0 github.com/prometheus/common/assets v0.2.0 github.com/prometheus/common/sigv4 v0.1.0 github.com/prometheus/exporter-toolkit v0.11.0 @@ -77,7 +77,7 @@ require ( github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/procfs v0.14.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect @@ -86,10 +86,9 @@ require ( go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/crypto v0.22.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/oauth2 v0.19.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect - google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9d2a30d3..193ae6d5 100644 --- a/go.sum +++ b/go.sum @@ -423,15 +423,15 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA= -github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= +github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= +github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM= github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= @@ -640,8 +640,8 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -860,7 +860,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= diff --git a/template/template.go b/template/template.go index a34403d8..92f8323e 100644 --- a/template/template.go +++ b/template/template.go @@ -26,6 +26,7 @@ import ( tmpltext "text/template" "time" + commonTemplates "github.com/prometheus/common/helpers/templates" "github.com/prometheus/common/model" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -204,6 +205,8 @@ var DefaultFuncs = FuncMap{ } return t.In(loc), nil }, + "since": time.Since, + "humanizeDuration": commonTemplates.HumanizeDuration, } // Pair is a key/value string pair. diff --git a/template/template_test.go b/template/template_test.go index 103dd084..ea8915b1 100644 --- a/template/template_test.go +++ b/template/template_test.go @@ -522,6 +522,45 @@ func TestTemplateFuncs(t *testing.T) { in: `{{ . | tz "Invalid/Timezone" }}`, data: time.Date(2024, 1, 1, 8, 15, 30, 0, time.UTC), expErr: "template: :1:7: executing \"\" at : error calling tz: unknown time zone Invalid/Timezone", + }, { + title: "Template using HumanizeDuration - seconds - float64", + in: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + data: []float64{0, 1, 60, 3600, 86400, 86400 + 3600, -(86400*2 + 3600*3 + 60*4 + 5), 899.99}, + exp: "0s:1s:1m 0s:1h 0m 0s:1d 0h 0m 0s:1d 1h 0m 0s:-2d 3h 4m 5s:14m 59s:", + }, { + title: "Template using HumanizeDuration - seconds - string.", + in: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + data: []string{"0", "1", "60", "3600", "86400"}, + exp: "0s:1s:1m 0s:1h 0m 0s:1d 0h 0m 0s:", + }, { + title: "Template using HumanizeDuration - subsecond and fractional seconds - float64.", + in: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + data: []float64{.1, .0001, .12345, 60.1, 60.5, 1.2345, 12.345}, + exp: "100ms:100us:123.5ms:1m 0s:1m 0s:1.234s:12.35s:", + }, { + title: "Template using HumanizeDuration - subsecond and fractional seconds - string.", + in: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + data: []string{".1", ".0001", ".12345", "60.1", "60.5", "1.2345", "12.345"}, + exp: "100ms:100us:123.5ms:1m 0s:1m 0s:1.234s:12.35s:", + }, { + title: "Template using HumanizeDuration - string with error.", + in: `{{ humanizeDuration "one" }}`, + expErr: "template: :1:3: executing \"\" at : error calling humanizeDuration: strconv.ParseFloat: parsing \"one\": invalid syntax", + }, { + title: "Template using HumanizeDuration - int.", + in: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + data: []int{0, -1, 1, 1234567}, + exp: "0s:-1s:1s:14d 6h 56m 7s:", + }, { + title: "Template using HumanizeDuration - uint.", + in: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + data: []uint{0, 1, 1234567}, + exp: "0s:1s:14d 6h 56m 7s:", + }, { + title: "Template using since", + in: "{{ . | since | humanizeDuration }}", + data: time.Now().Add(-1 * time.Hour), + exp: "1h 0m 0s", }} { tc := tc t.Run(tc.title, func(t *testing.T) {