logs-analyzer/signoz/pkg/query-service/formatter/scale.go

137 lines
2.7 KiB
Go
Raw Permalink Normal View History

2024-09-02 22:47:30 +03:00
package formatter
import (
"fmt"
"math"
"strconv"
"strings"
"github.com/samber/lo"
)
type IntervalsInSecondsType map[Interval]int
type Interval string
const (
Year Interval = "year"
Month Interval = "month"
Week Interval = "week"
Day Interval = "day"
Hour Interval = "hour"
Minute Interval = "minute"
Second Interval = "second"
Millisecond Interval = "millisecond"
)
var Units = []Interval{
Year,
Month,
Week,
Day,
Hour,
Minute,
Second,
Millisecond,
}
var IntervalsInSeconds = IntervalsInSecondsType{
Year: 31536000,
Month: 2592000,
Week: 604800,
Day: 86400,
Hour: 3600,
Minute: 60,
Second: 1,
Millisecond: 1,
}
type DecimalCount *int
func toFixed(value float64, decimals DecimalCount) string {
if value == 0 {
return strconv.FormatFloat(value, 'f', getDecimalsForValue(value), 64)
}
if math.IsInf(value, 0) {
return strconv.FormatFloat(value, 'f', -1, 64)
}
if decimals == nil {
count := getDecimalsForValue(value)
decimals = &count
}
factor := math.Pow(10, math.Max(0, float64(*decimals)))
formatted := strconv.FormatFloat(math.Round(value*factor)/factor, 'f', -1, 64)
if formatted == "NaN" {
return ""
}
if formatted == "-0" {
formatted = "0"
}
if value == 0 || strings.Contains(formatted, "e") {
return formatted
}
decimalPos := strings.Index(formatted, ".")
precision := 0
if decimalPos != -1 {
precision = len(formatted) - decimalPos - 1
if precision < *decimals {
return formatted + strings.Repeat("0", *decimals-precision)
}
}
return formatted
}
func toFixedScaled(value float64, decimals DecimalCount, scaleFormat string) string {
return toFixed(value, decimals) + scaleFormat
}
func getDecimalsForValue(value float64) int {
absValue := math.Abs(value)
log10 := math.Floor(math.Log10(absValue))
dec := int(-log10 + 1)
magn := math.Pow10(-dec)
norm := absValue / magn
if norm > 2.25 {
dec++
}
if math.Mod(value, 1) == 0 {
dec = 0
}
return int(math.Max(float64(dec), 0))
}
type ValueFormatter func(value float64, decimals *int) string
func logb(base, x float64) float64 {
return math.Log10(x) / math.Log10(base)
}
func scaledUnits(factor float64, extArray []string, offset int) ValueFormatter {
return func(value float64, decimals *int) string {
if value == 0 || math.IsNaN(value) || math.IsInf(value, 0) {
return fmt.Sprintf("%f", value)
}
siIndex := int(math.Floor(logb(factor, math.Abs(value))))
if value < 0 {
siIndex = -siIndex
}
siIndex = lo.Clamp(siIndex+offset, 0, len(extArray)-1)
suffix := extArray[siIndex]
return toFixed(value/math.Pow(factor, float64(siIndex-offset)), decimals) + suffix
}
}