The helpers/templates package provides helper functions for template processing, with a focus on time and duration formatting in human-readable formats.
import "github.com/prometheus/common/helpers/templates"This package provides utility functions commonly used in template processing, particularly for formatting time values and durations in human-readable ways. These functions are designed to be used with Go's text/template or html/template packages.
func ConvertToFloat(i interface{}) (float64, error)Converts various numeric types and time.Duration to float64. This is a utility function used internally by other template helpers.
Parameters:
i - Value to convert (supports: float64, string, int, uint, int64, uint64, time.Duration)Returns:
float64 - The converted valueerror - Error if conversion is not possibleSupported Types:
float64 - returned as-isstring - parsed using strconv.ParseFloatint, int64 - converted to float64uint, uint64 - converted to float64time.Duration - converted to seconds as float64Example:
val, err := templates.ConvertToFloat("123.45")
// val = 123.45
val, err = templates.ConvertToFloat(time.Hour)
// val = 3600.0 (seconds)func FloatToTime(v float64) (*time.Time, error)Converts a Unix timestamp (in seconds) to a time.Time pointer.
Parameters:
v - Unix timestamp in seconds (can include fractional seconds)Returns:
*time.Time - Pointer to the time valueerror - Error if conversion failsSpecial Cases:
errNaNOrInf error if the value is NaN or InfExample:
t, err := templates.FloatToTime(1609459200.0)
// Returns time for 2021-01-01 00:00:00 UTCfunc HumanizeDuration(i interface{}) (string, error)Formats a duration value in human-readable format using units: days (d), hours (h), minutes (m), seconds (s), and SI prefixes for sub-second values.
Parameters:
i - Duration value (converted to float64 via ConvertToFloat, interpreted as seconds)Returns:
string - Human-readable duration (e.g., "1d 2h 3m 4s")error - Error if conversion failsFormat:
Special Cases:
Example:
dur, err := templates.HumanizeDuration(90061)
// Returns: "1d 1h 1m 1s"
dur, err = templates.HumanizeDuration(3661)
// Returns: "1h 1m 1s"
dur, err = templates.HumanizeDuration(45.5)
// Returns: "45.5s"
dur, err = templates.HumanizeDuration(0.5)
// Returns: "500ms"
dur, err = templates.HumanizeDuration(0.000001)
// Returns: "1us"
dur, err = templates.HumanizeDuration(time.Hour * 25)
// Returns: "1d 1h"func HumanizeTimestamp(i interface{}) (string, error)Formats a Unix timestamp in human-readable format. The timestamp is expected to be in seconds since the Unix epoch.
Parameters:
i - Timestamp value (converted to float64 via ConvertToFloat, interpreted as Unix seconds)Returns:
string - Human-readable timestamp (includes sub-second precision when present)error - Error if conversion failsSpecial Cases:
Example:
ts, err := templates.HumanizeTimestamp(1609459200.0)
// Returns: "2021-01-01 00:00:00 +0000 UTC"
ts, err = templates.HumanizeTimestamp(1609459200.123456789)
// Returns: "2021-01-01 00:00:00.123456789 +0000 UTC"
// Using Prometheus model.Time
ts, err = templates.HumanizeTimestamp(model.Now().Unix())
// Returns current time formattedpackage main
import (
"fmt"
"time"
"github.com/prometheus/common/helpers/templates"
)
func main() {
// Humanize a duration
duration := 3665.0 // seconds
humanDur, _ := templates.HumanizeDuration(duration)
fmt.Println("Duration:", humanDur)
// Output: Duration: 1h 1m 5s
// Humanize a timestamp
timestamp := 1609459200.0 // Unix timestamp
humanTime, _ := templates.HumanizeTimestamp(timestamp)
fmt.Println("Time:", humanTime)
// Output: Time: 2021-01-01 00:00:00 +0000 UTC
// Convert time.Duration to float
goTime := 2*time.Hour + 30*time.Minute
seconds, _ := templates.ConvertToFloat(goTime)
fmt.Printf("%.0f seconds\n", seconds)
// Output: 9000 seconds
}package main
import (
"os"
"text/template"
"time"
"github.com/prometheus/common/helpers/templates"
)
func main() {
// Create template with helper functions
tmpl := template.New("alert").Funcs(template.FuncMap{
"humanizeDuration": templates.HumanizeDuration,
"humanizeTimestamp": templates.HumanizeTimestamp,
})
tmpl, _ = tmpl.Parse(`
Alert fired at {{ humanizeTimestamp .Timestamp }}
Duration: {{ humanizeDuration .Duration }}
`)
data := map[string]interface{}{
"Timestamp": float64(time.Now().Unix()),
"Duration": 3665.0,
}
tmpl.Execute(os.Stdout, data)
// Output:
// Alert fired at 2024-01-15 10:30:00 +0000 UTC
// Duration: 1h 1m 5s
}package main
import (
"text/template"
"time"
"github.com/prometheus/common/helpers/templates"
"github.com/prometheus/common/model"
)
func main() {
// Create alert template
tmpl := template.New("alert").Funcs(template.FuncMap{
"humanizeDuration": templates.HumanizeDuration,
})
tmpl, _ = tmpl.Parse(`
Alert: {{ .Labels.alertname }}
Firing for: {{ humanizeDuration .Duration }}
`)
// Calculate alert duration
alert := struct {
Labels model.LabelSet
Duration float64
}{
Labels: model.LabelSet{
"alertname": "HighMemoryUsage",
},
Duration: 3600.0, // 1 hour
}
tmpl.Execute(os.Stdout, alert)
// Output:
// Alert: HighMemoryUsage
// Firing for: 1h
}package main
import (
"os"
"text/template"
"time"
"github.com/prometheus/common/helpers/templates"
)
const alertTemplate = `
{{- define "alert" -}}
Alert: {{ .Name }}
Started: {{ humanizeTimestamp .StartTime }}
Duration: {{ humanizeDuration .Duration }}
{{- end -}}
`
func main() {
tmpl := template.New("alerts").Funcs(template.FuncMap{
"humanizeDuration": templates.HumanizeDuration,
"humanizeTimestamp": templates.HumanizeTimestamp,
})
tmpl, _ = tmpl.Parse(alertTemplate)
alerts := []map[string]interface{}{
{
"Name": "HighCPU",
"StartTime": float64(time.Now().Add(-2 * time.Hour).Unix()),
"Duration": 7200.0,
},
{
"Name": "DiskFull",
"StartTime": float64(time.Now().Add(-30 * time.Minute).Unix()),
"Duration": 1800.0,
},
}
for _, alert := range alerts {
tmpl.ExecuteTemplate(os.Stdout, "alert", alert)
println()
}
}The HumanizeDuration function uses the following unit conversions:
The HumanizeTimestamp function returns times in UTC by default. If you need local times, you should convert the time.Time after using FloatToTime.
Duration values support sub-second precision down to yoctoseconds (10^-24 seconds). All sub-second values are displayed with 4 significant digits. For durations with days, hours, or minutes components, seconds are shown as integers without sub-second precision.