diff --git a/template/template.go b/template/template.go index a8abda8f0..138aa74e4 100644 --- a/template/template.go +++ b/template/template.go @@ -104,6 +104,10 @@ func convertToFloat(i interface{}) (float64, error) { return v, nil case string: return strconv.ParseFloat(v, 64) + case int: + return float64(v), nil + case uint: + return float64(v), nil default: return 0, fmt.Errorf("can't convert %T to float", v) } @@ -244,10 +248,11 @@ func NewTemplateExpander( sign = "-" v = -v } - seconds := int64(v) % 60 - minutes := (int64(v) / 60) % 60 - hours := (int64(v) / 60 / 60) % 24 - days := int64(v) / 60 / 60 / 24 + duration := int64(v) + seconds := duration % 60 + minutes := (duration / 60) % 60 + hours := (duration / 60 / 60) % 24 + days := duration / 60 / 60 / 24 // For days to minutes, we display seconds as an integer. if days != 0 { return fmt.Sprintf("%s%dd %dh %dm %ds", sign, days, hours, minutes, seconds), nil @@ -286,7 +291,11 @@ func NewTemplateExpander( if math.IsNaN(v) || math.IsInf(v, 0) { return fmt.Sprintf("%.4g", v), nil } - t := model.TimeFromUnixNano(int64(v * 1e9)).Time().UTC() + timestamp := v * 1e9 + if timestamp > math.MaxInt64 || timestamp < math.MinInt64 { + return "", fmt.Errorf("%v cannot be represented as a nanoseconds timestamp since it overflows int64", v) + } + t := model.TimeFromUnixNano(int64(timestamp)).Time().UTC() return fmt.Sprint(t), nil }, "pathPrefix": func() string { diff --git a/template/template_test.go b/template/template_test.go index 063c43b6e..8f7fd0a5c 100644 --- a/template/template_test.go +++ b/template/template_test.go @@ -243,6 +243,18 @@ func TestTemplateExpansion(t *testing.T) { shouldFail: true, errorMsg: `error executing template test: template: test:1:3: executing "test" at : error calling humanize: strconv.ParseFloat: parsing "one": invalid syntax`, }, + { + // Humanize - int. + text: "{{ range . }}{{ humanize . }}:{{ end }}", + input: []int{0, -1, 1, 1234567, math.MaxInt64}, + output: "0:-1:1:1.235M:9.223E:", + }, + { + // Humanize - uint. + text: "{{ range . }}{{ humanize . }}:{{ end }}", + input: []uint{0, 1, 1234567, math.MaxUint64}, + output: "0:1:1.235M:18.45E:", + }, { // Humanize1024 - float64. text: "{{ range . }}{{ humanize1024 . }}:{{ end }}", @@ -261,6 +273,18 @@ func TestTemplateExpansion(t *testing.T) { shouldFail: true, errorMsg: `error executing template test: template: test:1:3: executing "test" at : error calling humanize1024: strconv.ParseFloat: parsing "one": invalid syntax`, }, + { + // Humanize1024 - int. + text: "{{ range . }}{{ humanize1024 . }}:{{ end }}", + input: []int{0, -1, 1, 1234567, math.MaxInt64}, + output: "0:-1:1:1.177Mi:8Ei:", + }, + { + // Humanize1024 - uint. + text: "{{ range . }}{{ humanize1024 . }}:{{ end }}", + input: []uint{0, 1, 1234567, math.MaxUint64}, + output: "0:1:1.177Mi:16Ei:", + }, { // HumanizeDuration - seconds - float64. text: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", @@ -291,6 +315,18 @@ func TestTemplateExpansion(t *testing.T) { shouldFail: true, errorMsg: `error executing template test: template: test:1:3: executing "test" at : error calling humanizeDuration: strconv.ParseFloat: parsing "one": invalid syntax`, }, + { + // HumanizeDuration - int. + text: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + input: []int{0, -1, 1, 1234567, math.MaxInt64}, + output: "0s:-1s:1s:14d 6h 56m 7s:-106751991167300d -15h -30m -8s:", + }, + { + // HumanizeDuration - uint. + text: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + input: []uint{0, 1, 1234567, math.MaxUint64}, + output: "0s:1s:14d 6h 56m 7s:-106751991167300d -15h -30m -8s:", + }, { // Humanize* Inf and NaN - float64. text: "{{ range . }}{{ humanize . }}:{{ humanize1024 . }}:{{ humanizeDuration . }}:{{humanizeTimestamp .}}:{{ end }}", @@ -308,6 +344,18 @@ func TestTemplateExpansion(t *testing.T) { text: "{{ -0.22222 | humanizePercentage }}:{{ 0.0 | humanizePercentage }}:{{ 0.1234567 | humanizePercentage }}:{{ 1.23456 | humanizePercentage }}", output: "-22.22%:0%:12.35%:123.5%", }, + { + // HumanizePercentage - int. + text: "{{ range . }}{{ humanizePercentage . }}:{{ end }}", + input: []int{0, -1, 1, 1234567, math.MaxInt64}, + output: "0%:-100%:100%:1.235e+08%:9.223e+20%:", + }, + { + // HumanizePercentage - uint. + text: "{{ range . }}{{ humanizePercentage . }}:{{ end }}", + input: []uint{0, 1, 1234567, math.MaxUint64}, + output: "0%:100%:1.235e+08%:1.845e+21%:", + }, { // HumanizePercentage - model.SampleValue input - string. text: `{{ "-0.22222" | humanizePercentage }}:{{ "0.0" | humanizePercentage }}:{{ "0.1234567" | humanizePercentage }}:{{ "1.23456" | humanizePercentage }}`, @@ -319,6 +367,32 @@ func TestTemplateExpansion(t *testing.T) { shouldFail: true, errorMsg: `error executing template test: template: test:1:11: executing "test" at : error calling humanizePercentage: strconv.ParseFloat: parsing "one": invalid syntax`, }, + { + // HumanizeTimestamp - int. + text: "{{ range . }}{{ humanizeTimestamp . }}:{{ end }}", + input: []int{0, -1, 1, 1234567, 9223372036}, + output: "1970-01-01 00:00:00 +0000 UTC:1969-12-31 23:59:59 +0000 UTC:1970-01-01 00:00:01 +0000 UTC:1970-01-15 06:56:07 +0000 UTC:2262-04-11 23:47:16 +0000 UTC:", + }, + { + // HumanizeTimestamp - uint. + text: "{{ range . }}{{ humanizeTimestamp . }}:{{ end }}", + input: []uint{0, 1, 1234567, 9223372036}, + output: "1970-01-01 00:00:00 +0000 UTC:1970-01-01 00:00:01 +0000 UTC:1970-01-15 06:56:07 +0000 UTC:2262-04-11 23:47:16 +0000 UTC:", + }, + { + // HumanizeTimestamp - int with error. + text: "{{ range . }}{{ humanizeTimestamp . }}:{{ end }}", + input: []int{math.MinInt64, math.MaxInt64}, + shouldFail: true, + errorMsg: `error executing template test: template: test:1:16: executing "test" at : error calling humanizeTimestamp: -9.223372036854776e+18 cannot be represented as a nanoseconds timestamp since it overflows int64`, + }, + { + // HumanizeTimestamp - uint with error. + text: "{{ range . }}{{ humanizeTimestamp . }}:{{ end }}", + input: []uint{math.MaxUint64}, + shouldFail: true, + errorMsg: `error executing template test: template: test:1:16: executing "test" at : error calling humanizeTimestamp: 1.8446744073709552e+19 cannot be represented as a nanoseconds timestamp since it overflows int64`, + }, { // HumanizeTimestamp - model.SampleValue input - float64. text: "{{ 1435065584.128 | humanizeTimestamp }}",