mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-20 20:29:12 +08:00
feat: add measurement unit converter (#2772)
This commit is contained in:
parent
edf7e9821f
commit
7086f7eafa
1
Makefile
1
Makefile
@ -139,3 +139,4 @@ clear-swarm-data:
|
||||
test:
|
||||
go test ./pkg/query-service/app/metrics/...
|
||||
go test ./pkg/query-service/app/...
|
||||
go test ./pkg/query-service/converter/...
|
16
pkg/query-service/converter/bool.go
Normal file
16
pkg/query-service/converter/bool.go
Normal file
@ -0,0 +1,16 @@
|
||||
package converter
|
||||
|
||||
// boolConverter is a Converter implementation for bool
|
||||
type boolConverter struct{}
|
||||
|
||||
func NewBoolConverter() Converter {
|
||||
return &boolConverter{}
|
||||
}
|
||||
|
||||
func (c *boolConverter) Convert(v Value, to Unit) Value {
|
||||
// There is no conversion to be done for bool
|
||||
return Value{
|
||||
F: v.F,
|
||||
U: to,
|
||||
}
|
||||
}
|
53
pkg/query-service/converter/converter.go
Normal file
53
pkg/query-service/converter/converter.go
Normal file
@ -0,0 +1,53 @@
|
||||
package converter
|
||||
|
||||
// Unit represents a unit of measurement
|
||||
type Unit string
|
||||
|
||||
// Value represents a value with a unit of measurement
|
||||
type Value struct {
|
||||
F float64
|
||||
U Unit
|
||||
}
|
||||
|
||||
// Converter converts values from one unit to another
|
||||
type Converter interface {
|
||||
Convert(v Value, to Unit) Value
|
||||
}
|
||||
|
||||
// noneConverter is a converter that does not convert
|
||||
type noneConverter struct{}
|
||||
|
||||
func (c *noneConverter) Convert(v Value, to Unit) Value {
|
||||
return v
|
||||
}
|
||||
|
||||
// Converters
|
||||
var (
|
||||
DurationConverter = NewDurationConverter()
|
||||
DataConverter = NewDataConverter()
|
||||
DataRateConverter = NewDataRateConverter()
|
||||
PercentConverter = NewPercentConverter()
|
||||
BoolConverter = NewBoolConverter()
|
||||
ThroughputConverter = NewThroughputConverter()
|
||||
NoneConverter = &noneConverter{}
|
||||
)
|
||||
|
||||
// FromUnit returns a converter for the given unit
|
||||
func FromUnit(u Unit) Converter {
|
||||
switch u {
|
||||
case "ns", "us", "ms", "s", "m", "h", "d":
|
||||
return DurationConverter
|
||||
case "bytes", "decbytes", "bits", "decbits", "kbytes", "decKbytes", "mbytes", "decMbytes", "gbytes", "decGbytes", "tbytes", "decTbytes", "pbytes", "decPbytes":
|
||||
return DataConverter
|
||||
case "binBps", "Bps", "binbps", "bps", "KiBs", "Kibits", "KBs", "Kbits", "MiBs", "Mibits", "MBs", "Mbits", "GiBs", "Gibits", "GBs", "Gbits", "TiBs", "Tibits", "TBs", "Tbits", "PiBs", "Pibits", "PBs", "Pbits":
|
||||
return DataRateConverter
|
||||
case "percent", "percentunit":
|
||||
return PercentConverter
|
||||
case "bool", "bool_yes_no", "bool_true_false", "bool_1_0":
|
||||
return BoolConverter
|
||||
case "cps", "ops", "reqps", "rps", "wps", "iops", "cpm", "opm", "rpm", "wpm":
|
||||
return ThroughputConverter
|
||||
default:
|
||||
return NoneConverter
|
||||
}
|
||||
}
|
97
pkg/query-service/converter/data.go
Normal file
97
pkg/query-service/converter/data.go
Normal file
@ -0,0 +1,97 @@
|
||||
package converter
|
||||
|
||||
const (
|
||||
// base 10 (SI prefixes)
|
||||
Bit float64 = 1e0
|
||||
Kilobit = Bit * 1e3
|
||||
Megabit = Bit * 1e6
|
||||
Gigabit = Bit * 1e9
|
||||
Terabit = Bit * 1e12
|
||||
Petabit = Bit * 1e15
|
||||
Exabit = Bit * 1e18
|
||||
Zettabit = Bit * 1e21
|
||||
Yottabit = Bit * 1e24
|
||||
Ronnabit = Bit * 1e27
|
||||
Quettabit = Bit * 1e30
|
||||
|
||||
Byte = Bit * 8
|
||||
Kilobyte = Byte * 1e3
|
||||
Megabyte = Byte * 1e6
|
||||
Gigabyte = Byte * 1e9
|
||||
Terabyte = Byte * 1e12
|
||||
Petabyte = Byte * 1e15
|
||||
Exabyte = Byte * 1e18
|
||||
Zettabyte = Byte * 1e21
|
||||
Yottabyte = Byte * 1e24
|
||||
Ronnabyte = Byte * 1e27
|
||||
Quettabyte = Byte * 1e30
|
||||
|
||||
// base 2 (IEC prefixes)
|
||||
Kibibit = Bit * 1024
|
||||
Mebibit = Kibibit * 1024
|
||||
Gibibit = Mebibit * 1024
|
||||
Tebibit = Gibibit * 1024
|
||||
Pebibit = Tebibit * 1024
|
||||
Exbibit = Pebibit * 1024
|
||||
Zebibit = Exbibit * 1024
|
||||
Yobibit = Zebibit * 1024
|
||||
|
||||
Kibibyte = Byte * 1024
|
||||
Mebibyte = Kibibyte * 1024
|
||||
Gibibyte = Mebibyte * 1024
|
||||
Tebibyte = Gibibyte * 1024
|
||||
Pebibyte = Tebibyte * 1024
|
||||
Exbibyte = Pebibyte * 1024
|
||||
Zebibyte = Exbibyte * 1024
|
||||
Yobibyte = Zebibyte * 1024
|
||||
)
|
||||
|
||||
// dataConverter is a Converter for data units.
|
||||
type dataConverter struct {
|
||||
}
|
||||
|
||||
func NewDataConverter() Converter {
|
||||
return &dataConverter{}
|
||||
}
|
||||
|
||||
func FromDataUnit(u Unit) float64 {
|
||||
switch u {
|
||||
case "bytes": // base 2
|
||||
return Byte
|
||||
case "decbytes": // base 10
|
||||
return Byte
|
||||
case "bits": // base 2
|
||||
return Bit
|
||||
case "decbits": // base 10
|
||||
return Bit
|
||||
case "kbytes": // base 2
|
||||
return Kibibyte
|
||||
case "deckbytes": // base 10
|
||||
return Kilobyte
|
||||
case "mbytes": // base 2
|
||||
return Mebibyte
|
||||
case "decmbytes": // base 10
|
||||
return Megabyte
|
||||
case "gbytes": // base 2
|
||||
return Gibibyte
|
||||
case "decgbytes": // base 10
|
||||
return Gigabyte
|
||||
case "tbytes": // base 2
|
||||
return Tebibyte
|
||||
case "dectbytes": // base 10
|
||||
return Terabyte
|
||||
case "pbytes": // base 2
|
||||
return Pebibyte
|
||||
case "decpbytes": // base 10
|
||||
return Petabyte
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func (c *dataConverter) Convert(v Value, to Unit) Value {
|
||||
return Value{
|
||||
F: v.F * FromDataUnit(v.U) / FromDataUnit(to),
|
||||
U: to,
|
||||
}
|
||||
}
|
114
pkg/query-service/converter/data_rate.go
Normal file
114
pkg/query-service/converter/data_rate.go
Normal file
@ -0,0 +1,114 @@
|
||||
package converter
|
||||
|
||||
const (
|
||||
// base 10 (SI prefixes)
|
||||
BitPerSecond float64 = 1e0
|
||||
KilobitPerSecond = BitPerSecond * 1e3
|
||||
MegabitPerSecond = BitPerSecond * 1e6
|
||||
GigabitPerSecond = BitPerSecond * 1e9
|
||||
TerabitPerSecond = BitPerSecond * 1e12
|
||||
PetabitPerSecond = BitPerSecond * 1e15
|
||||
ExabitPerSecond = BitPerSecond * 1e18
|
||||
ZettabitPerSecond = BitPerSecond * 1e21
|
||||
YottabitPerSecond = BitPerSecond * 1e24
|
||||
|
||||
BytePerSecond = BitPerSecond * 8
|
||||
KilobytePerSecond = BytePerSecond * 1e3
|
||||
MegabytePerSecond = BytePerSecond * 1e6
|
||||
GigabytePerSecond = BytePerSecond * 1e9
|
||||
TerabytePerSecond = BytePerSecond * 1e12
|
||||
PetabytePerSecond = BytePerSecond * 1e15
|
||||
ExabytePerSecond = BytePerSecond * 1e18
|
||||
ZettabytePerSecond = BytePerSecond * 1e21
|
||||
YottabytePerSecond = BytePerSecond * 1e24
|
||||
|
||||
// base 2 (IEC prefixes)
|
||||
KibibitPerSecond = BitPerSecond * 1024
|
||||
MebibitPerSecond = KibibitPerSecond * 1024
|
||||
GibibitPerSecond = MebibitPerSecond * 1024
|
||||
TebibitPerSecond = GibibitPerSecond * 1024
|
||||
PebibitPerSecond = TebibitPerSecond * 1024
|
||||
ExbibitPerSecond = PebibitPerSecond * 1024
|
||||
ZebibitPerSecond = ExbibitPerSecond * 1024
|
||||
YobibitPerSecond = ZebibitPerSecond * 1024
|
||||
|
||||
KibibytePerSecond = BytePerSecond * 1024
|
||||
MebibytePerSecond = KibibytePerSecond * 1024
|
||||
GibibytePerSecond = MebibytePerSecond * 1024
|
||||
TebibytePerSecond = GibibytePerSecond * 1024
|
||||
PebibytePerSecond = TebibytePerSecond * 1024
|
||||
ExbibytePerSecond = PebibytePerSecond * 1024
|
||||
ZebibytePerSecond = ExbibytePerSecond * 1024
|
||||
YobibytePerSecond = ZebibytePerSecond * 1024
|
||||
)
|
||||
|
||||
// dataRateConverter is a Converter implementation for data rates
|
||||
type dataRateConverter struct {
|
||||
}
|
||||
|
||||
func NewDataRateConverter() Converter {
|
||||
return &dataRateConverter{}
|
||||
}
|
||||
|
||||
func FromDataRateUnit(u Unit) float64 {
|
||||
// See https://github.com/SigNoz/signoz/blob/5a81f5f90b34845f5b4b3bdd46acf29d04bf3987/frontend/src/container/NewWidget/RightContainer/dataFormatCategories.ts#L62-L85
|
||||
switch u {
|
||||
case "binBps": // bytes/sec(IEC)
|
||||
return BytePerSecond
|
||||
case "Bps": // bytes/sec(SI)
|
||||
return BytePerSecond
|
||||
case "binbps": // bits/sec(IEC)
|
||||
return BitPerSecond
|
||||
case "bps": // bits/sec(SI)
|
||||
return BitPerSecond
|
||||
case "KiBs": // kibibytes/sec
|
||||
return KibibytePerSecond
|
||||
case "Kibits": // kibibits/sec
|
||||
return KibibitPerSecond
|
||||
case "KBs": // kilobytes/sec
|
||||
return KilobytePerSecond
|
||||
case "Kbits": // kilobits/sec
|
||||
return KilobitPerSecond
|
||||
case "MiBs": // mebibytes/sec
|
||||
return MebibytePerSecond
|
||||
case "Mibits": // mebibits/sec
|
||||
return MebibitPerSecond
|
||||
case "MBs": // megabytes/sec
|
||||
return MegabytePerSecond
|
||||
case "Mbits": // megabits/sec
|
||||
return MegabitPerSecond
|
||||
case "GiBs": // gibibytes/sec
|
||||
return GibibytePerSecond
|
||||
case "Gibits": // gibibits/sec
|
||||
return GibibitPerSecond
|
||||
case "GBs": // gigabytes/sec
|
||||
return GigabytePerSecond
|
||||
case "Gbits": // gigabits/sec
|
||||
return GigabitPerSecond
|
||||
case "TiBs": // tebibytes/sec
|
||||
return TebibytePerSecond
|
||||
case "Tibits": // tebibits/sec
|
||||
return TebibitPerSecond
|
||||
case "TBs": // terabytes/sec
|
||||
return TerabytePerSecond
|
||||
case "Tbits": // terabits/sec
|
||||
return TerabitPerSecond
|
||||
case "PiBs": // pebibytes/sec
|
||||
return PebibytePerSecond
|
||||
case "Pibits": // pebibits/sec
|
||||
return PebibitPerSecond
|
||||
case "PBs": // petabytes/sec
|
||||
return PetabytePerSecond
|
||||
case "Pbits": // petabits/sec
|
||||
return PetabitPerSecond
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func (c *dataRateConverter) Convert(v Value, to Unit) Value {
|
||||
return Value{
|
||||
F: v.F * FromDataRateUnit(v.U) / FromDataRateUnit(to),
|
||||
U: to,
|
||||
}
|
||||
}
|
67
pkg/query-service/converter/data_rate_test.go
Normal file
67
pkg/query-service/converter/data_rate_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDataRate(t *testing.T) {
|
||||
dataRateConverter := NewDataRateConverter()
|
||||
// names and ids for data rate units
|
||||
// { name: 'bytes/sec(IEC)', id: 'binBps' },
|
||||
// { name: 'bytes/sec(SI)', id: 'Bps' },
|
||||
// { name: 'bits/sec(IEC)', id: 'binbps' },
|
||||
// { name: 'bits/sec(SI)', id: 'bps' },
|
||||
// { name: 'kibibytes/sec', id: 'KiBs' },
|
||||
// { name: 'kibibits/sec', id: 'Kibits' },
|
||||
// { name: 'kilobytes/sec', id: 'KBs' },
|
||||
// { name: 'kilobits/sec', id: 'Kbits' },
|
||||
// { name: 'mebibytes/sec', id: 'MiBs' },
|
||||
// { name: 'mebibits/sec', id: 'Mibits' },
|
||||
// { name: 'megabytes/sec', id: 'MBs' },
|
||||
// { name: 'megabits/sec', id: 'Mbits' },
|
||||
// { name: 'gibibytes/sec', id: 'GiBs' },
|
||||
// { name: 'gibibits/sec', id: 'Gibits' },
|
||||
// { name: 'gigabytes/sec', id: 'GBs' },
|
||||
// { name: 'gigabits/sec', id: 'Gbits' },
|
||||
// { name: 'tebibytes/sec', id: 'TiBs' },
|
||||
// { name: 'tebibits/sec', id: 'Tibits' },
|
||||
// { name: 'terabytes/sec', id: 'TBs' },
|
||||
// { name: 'terabits/sec', id: 'Tbits' },
|
||||
// { name: 'pebibytes/sec', id: 'PiBs' },
|
||||
// { name: 'pebibits/sec', id: 'Pibits' },
|
||||
// { name: 'petabytes/sec', id: 'PBs' },
|
||||
// { name: 'petabits/sec', id: 'Pbits' },
|
||||
|
||||
// 8 bits = 1 byte
|
||||
assert.Equal(t, Value{F: 1, U: "binBps"}, dataRateConverter.Convert(Value{F: 8, U: "binbps"}, "binBps"))
|
||||
// 1024 bytes = 1 kbytes
|
||||
assert.Equal(t, Value{F: 1, U: "KiBs"}, dataRateConverter.Convert(Value{F: 1024, U: "binBps"}, "KiBs"))
|
||||
// 1 byte = 8 bits
|
||||
assert.Equal(t, Value{F: 8, U: "binbps"}, dataRateConverter.Convert(Value{F: 1, U: "binBps"}, "binbps"))
|
||||
// 1 mbytes = 1024 kbytes
|
||||
assert.Equal(t, Value{F: 1, U: "MiBs"}, dataRateConverter.Convert(Value{F: 1024, U: "KiBs"}, "MiBs"))
|
||||
// 1 kbytes = 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024, U: "binBps"}, dataRateConverter.Convert(Value{F: 1, U: "KiBs"}, "binBps"))
|
||||
// 1024 kbytes = 1 mbytes
|
||||
assert.Equal(t, Value{F: 1, U: "MiBs"}, dataRateConverter.Convert(Value{F: 1024, U: "KiBs"}, "MiBs"))
|
||||
// 1 mbytes = 1024 * 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024, U: "binBps"}, dataRateConverter.Convert(Value{F: 1, U: "MiBs"}, "binBps"))
|
||||
// 1024 mbytes = 1 gbytes
|
||||
assert.Equal(t, Value{F: 1, U: "GiBs"}, dataRateConverter.Convert(Value{F: 1024, U: "MiBs"}, "GiBs"))
|
||||
// 2048 mbytes = 2 gbytes
|
||||
assert.Equal(t, Value{F: 2, U: "GiBs"}, dataRateConverter.Convert(Value{F: 2048, U: "MiBs"}, "GiBs"))
|
||||
// 1 gbytes = 1024 mbytes
|
||||
assert.Equal(t, Value{F: 1024, U: "MiBs"}, dataRateConverter.Convert(Value{F: 1, U: "GiBs"}, "MiBs"))
|
||||
// 1 gbytes = 1024 * 1024 kbytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024, U: "KiBs"}, dataRateConverter.Convert(Value{F: 1, U: "GiBs"}, "KiBs"))
|
||||
// 1 gbytes = 1024 * 1024 * 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024 * 1024, U: "binBps"}, dataRateConverter.Convert(Value{F: 1, U: "GiBs"}, "binBps"))
|
||||
// 1024 * 1024 bytes = 1 mbytes
|
||||
assert.Equal(t, Value{F: 1, U: "MiBs"}, dataRateConverter.Convert(Value{F: 1024 * 1024, U: "binBps"}, "MiBs"))
|
||||
// 1024 * 1024 kbytes = 1 gbytes
|
||||
assert.Equal(t, Value{F: 1, U: "GiBs"}, dataRateConverter.Convert(Value{F: 1024 * 1024, U: "KiBs"}, "GiBs"))
|
||||
// 1024 * 1024 * 1024 bytes = 1 gbytes
|
||||
assert.Equal(t, Value{F: 1, U: "GiBs"}, dataRateConverter.Convert(Value{F: 1024 * 1024 * 1024, U: "binBps"}, "GiBs"))
|
||||
}
|
47
pkg/query-service/converter/data_test.go
Normal file
47
pkg/query-service/converter/data_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestData(t *testing.T) {
|
||||
dataConverter := NewDataConverter()
|
||||
// 8 bits = 1 byte
|
||||
assert.Equal(t, Value{F: 1, U: "bytes"}, dataConverter.Convert(Value{F: 8, U: "bits"}, "bytes"))
|
||||
// 1024 bytes = 1 kbytes
|
||||
assert.Equal(t, Value{F: 1, U: "kbytes"}, dataConverter.Convert(Value{F: 1024, U: "bytes"}, "kbytes"))
|
||||
// 1 byte = 8 bits
|
||||
assert.Equal(t, Value{F: 8, U: "bits"}, dataConverter.Convert(Value{F: 1, U: "bytes"}, "bits"))
|
||||
// 1 mbytes = 1024 kbytes
|
||||
assert.Equal(t, Value{F: 1024, U: "kbytes"}, dataConverter.Convert(Value{F: 1, U: "mbytes"}, "kbytes"))
|
||||
// 1 kbytes = 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024, U: "bytes"}, dataConverter.Convert(Value{F: 1, U: "kbytes"}, "bytes"))
|
||||
// 1024 kbytes = 1 mbytes
|
||||
assert.Equal(t, Value{F: 1, U: "mbytes"}, dataConverter.Convert(Value{F: 1024, U: "kbytes"}, "mbytes"))
|
||||
// 1 mbytes = 1024 * 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024, U: "bytes"}, dataConverter.Convert(Value{F: 1, U: "mbytes"}, "bytes"))
|
||||
// 1024 mbytes = 1 gbytes
|
||||
assert.Equal(t, Value{F: 1, U: "gbytes"}, dataConverter.Convert(Value{F: 1024, U: "mbytes"}, "gbytes"))
|
||||
// 1 gbytes = 1024 mbytes
|
||||
assert.Equal(t, Value{F: 1024, U: "mbytes"}, dataConverter.Convert(Value{F: 1, U: "gbytes"}, "mbytes"))
|
||||
// 1 gbytes = 1024 * 1024 kbytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024, U: "kbytes"}, dataConverter.Convert(Value{F: 1, U: "gbytes"}, "kbytes"))
|
||||
// 1 gbytes = 1024 * 1024 * 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024 * 1024, U: "bytes"}, dataConverter.Convert(Value{F: 1, U: "gbytes"}, "bytes"))
|
||||
// 1024 gbytes = 1 tbytes
|
||||
assert.Equal(t, Value{F: 1, U: "tbytes"}, dataConverter.Convert(Value{F: 1024, U: "gbytes"}, "tbytes"))
|
||||
// 1 tbytes = 1024 gbytes
|
||||
assert.Equal(t, Value{F: 1024, U: "gbytes"}, dataConverter.Convert(Value{F: 1, U: "tbytes"}, "gbytes"))
|
||||
// 1 tbytes = 1024 * 1024 mbytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024, U: "mbytes"}, dataConverter.Convert(Value{F: 1, U: "tbytes"}, "mbytes"))
|
||||
// 1 tbytes = 1024 * 1024 * 1024 kbytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024 * 1024, U: "kbytes"}, dataConverter.Convert(Value{F: 1, U: "tbytes"}, "kbytes"))
|
||||
// 1 tbytes = 1024 * 1024 * 1024 * 1024 bytes
|
||||
assert.Equal(t, Value{F: 1024 * 1024 * 1024 * 1024, U: "bytes"}, dataConverter.Convert(Value{F: 1, U: "tbytes"}, "bytes"))
|
||||
// 1024 tbytes = 1 pbytes
|
||||
assert.Equal(t, Value{F: 1, U: "pbytes"}, dataConverter.Convert(Value{F: 1024, U: "tbytes"}, "pbytes"))
|
||||
// 1 pbytes = 1024 tbytes
|
||||
assert.Equal(t, Value{F: 1024, U: "tbytes"}, dataConverter.Convert(Value{F: 1, U: "pbytes"}, "tbytes"))
|
||||
}
|
26
pkg/query-service/converter/percent_converter.go
Normal file
26
pkg/query-service/converter/percent_converter.go
Normal file
@ -0,0 +1,26 @@
|
||||
package converter
|
||||
|
||||
// percentConverter is a converter for percent unit
|
||||
type percentConverter struct{}
|
||||
|
||||
func NewPercentConverter() Converter {
|
||||
return &percentConverter{}
|
||||
}
|
||||
|
||||
func FromPercentUnit(u Unit) float64 {
|
||||
switch u {
|
||||
case "percent":
|
||||
return 1
|
||||
case "percentunit":
|
||||
return 100
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func (c *percentConverter) Convert(v Value, to Unit) Value {
|
||||
return Value{
|
||||
F: v.F * FromPercentUnit(v.U) / FromPercentUnit(to),
|
||||
U: to,
|
||||
}
|
||||
}
|
16
pkg/query-service/converter/percent_converter_test.go
Normal file
16
pkg/query-service/converter/percent_converter_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPercentConverter(t *testing.T) {
|
||||
percentConverter := NewPercentConverter()
|
||||
|
||||
assert.Equal(t, Value{F: 1, U: "percent"}, percentConverter.Convert(Value{F: 1, U: "percent"}, "percent"))
|
||||
assert.Equal(t, Value{F: 100, U: "percent"}, percentConverter.Convert(Value{F: 1, U: "percentunit"}, "percent"))
|
||||
assert.Equal(t, Value{F: 1, U: "percentunit"}, percentConverter.Convert(Value{F: 100, U: "percent"}, "percentunit"))
|
||||
assert.Equal(t, Value{F: 0.01, U: "percentunit"}, percentConverter.Convert(Value{F: 1, U: "percent"}, "percentunit"))
|
||||
}
|
17
pkg/query-service/converter/throughput.go
Normal file
17
pkg/query-service/converter/throughput.go
Normal file
@ -0,0 +1,17 @@
|
||||
package converter
|
||||
|
||||
// throughputConverter is an implementation of Converter that converts throughput
|
||||
type throughputConverter struct {
|
||||
}
|
||||
|
||||
func NewThroughputConverter() Converter {
|
||||
return &throughputConverter{}
|
||||
}
|
||||
|
||||
func (c *throughputConverter) Convert(v Value, to Unit) Value {
|
||||
// There is no conversion to be done for throughput
|
||||
return Value{
|
||||
F: v.F,
|
||||
U: to,
|
||||
}
|
||||
}
|
58
pkg/query-service/converter/time.go
Normal file
58
pkg/query-service/converter/time.go
Normal file
@ -0,0 +1,58 @@
|
||||
package converter
|
||||
|
||||
type Duration float64
|
||||
|
||||
const (
|
||||
Nanosecond = Second * 1e-9
|
||||
Microsecond = Second * 1e-6
|
||||
Millisecond = Second * 1e-3
|
||||
Centisecond = Second * 1e-2
|
||||
Decisecond = Second * 1e-1
|
||||
Second Duration = 1e0
|
||||
Minute = Second * 60
|
||||
Hour = Minute * 60
|
||||
Day = Hour * 24
|
||||
Week = Day * 7
|
||||
)
|
||||
|
||||
// durationConverter is an implementation of Converter for durations.
|
||||
type durationConverter struct {
|
||||
}
|
||||
|
||||
func NewDurationConverter() Converter {
|
||||
return &durationConverter{}
|
||||
}
|
||||
|
||||
func FromTimeUnit(u Unit) Duration {
|
||||
switch u {
|
||||
case "ns":
|
||||
return Nanosecond
|
||||
case "us":
|
||||
return Microsecond
|
||||
case "ms":
|
||||
return Millisecond
|
||||
case "cs":
|
||||
return Centisecond
|
||||
case "ds":
|
||||
return Decisecond
|
||||
case "s":
|
||||
return Second
|
||||
case "m":
|
||||
return Minute
|
||||
case "h":
|
||||
return Hour
|
||||
case "d":
|
||||
return Day
|
||||
case "w":
|
||||
return Week
|
||||
default:
|
||||
return Second
|
||||
}
|
||||
}
|
||||
|
||||
func (c *durationConverter) Convert(v Value, to Unit) Value {
|
||||
return Value{
|
||||
F: v.F * float64(FromTimeUnit(v.U)) / float64(FromTimeUnit(to)),
|
||||
U: to,
|
||||
}
|
||||
}
|
55
pkg/query-service/converter/time_test.go
Normal file
55
pkg/query-service/converter/time_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDurationConvert(t *testing.T) {
|
||||
timeConverter := NewDurationConverter()
|
||||
// 1000 ms = 1 s
|
||||
assert.Equal(t, Value{F: 1, U: "s"}, timeConverter.Convert(Value{F: 1000, U: "ms"}, "s"))
|
||||
// 1000000 us = 1 s
|
||||
assert.Equal(t, Value{F: 1, U: "s"}, timeConverter.Convert(Value{F: 1000000, U: "us"}, "s"))
|
||||
// 100000 ms = 100 s
|
||||
assert.Equal(t, Value{F: 100, U: "s"}, timeConverter.Convert(Value{F: 100000, U: "ms"}, "s"))
|
||||
// 1 s = 1000 ms
|
||||
assert.Equal(t, Value{F: 1000, U: "ms"}, timeConverter.Convert(Value{F: 1, U: "s"}, "ms"))
|
||||
// 60 s = 1 m
|
||||
assert.Equal(t, Value{F: 1, U: "m"}, timeConverter.Convert(Value{F: 60, U: "s"}, "m"))
|
||||
// 604800000000000 ns = 1 w
|
||||
assert.Equal(t, Value{F: 1, U: "w"}, timeConverter.Convert(Value{F: 604800000000000, U: "ns"}, "w"))
|
||||
// 1 m = 60 s
|
||||
assert.Equal(t, Value{F: 60, U: "s"}, timeConverter.Convert(Value{F: 1, U: "m"}, "s"))
|
||||
// 60 m = 1 h
|
||||
assert.Equal(t, Value{F: 1, U: "h"}, timeConverter.Convert(Value{F: 60, U: "m"}, "h"))
|
||||
// 168 h = 1 w
|
||||
assert.Equal(t, Value{F: 1, U: "w"}, timeConverter.Convert(Value{F: 168, U: "h"}, "w"))
|
||||
// 1 h = 60 m
|
||||
assert.Equal(t, Value{F: 60, U: "m"}, timeConverter.Convert(Value{F: 1, U: "h"}, "m"))
|
||||
// 24 h = 1 d
|
||||
assert.Equal(t, Value{F: 1, U: "d"}, timeConverter.Convert(Value{F: 24, U: "h"}, "d"))
|
||||
// 10080 m = 1 w
|
||||
assert.Equal(t, Value{F: 1, U: "w"}, timeConverter.Convert(Value{F: 10080, U: "m"}, "w"))
|
||||
// 1 d = 24 h
|
||||
assert.Equal(t, Value{F: 24, U: "h"}, timeConverter.Convert(Value{F: 1, U: "d"}, "h"))
|
||||
// 7 d = 1 w
|
||||
assert.Equal(t, Value{F: 1, U: "w"}, timeConverter.Convert(Value{F: 7, U: "d"}, "w"))
|
||||
// 1 w = 7 d
|
||||
assert.Equal(t, Value{F: 7, U: "d"}, timeConverter.Convert(Value{F: 1, U: "w"}, "d"))
|
||||
// 1 w = 168 h
|
||||
assert.Equal(t, Value{F: 168, U: "h"}, timeConverter.Convert(Value{F: 1, U: "w"}, "h"))
|
||||
// 1 w = 10080 m
|
||||
assert.Equal(t, Value{F: 10080, U: "m"}, timeConverter.Convert(Value{F: 1, U: "w"}, "m"))
|
||||
// 604800 s = 1 w
|
||||
assert.Equal(t, Value{F: 1, U: "w"}, timeConverter.Convert(Value{F: 604800, U: "s"}, "w"))
|
||||
// 1 w = 604800 s
|
||||
assert.Equal(t, Value{F: 604800, U: "s"}, timeConverter.Convert(Value{F: 1, U: "w"}, "s"))
|
||||
// 1 w = 604800000000000 ns
|
||||
assert.Equal(t, Value{F: 604800000000000, U: "ns"}, timeConverter.Convert(Value{F: 1, U: "w"}, "ns"))
|
||||
// 1000 us = 1 ms
|
||||
assert.Equal(t, Value{F: 1, U: "ms"}, timeConverter.Convert(Value{F: 1000, U: "us"}, "ms"))
|
||||
// 1000000000 ns = 1 s
|
||||
assert.Equal(t, Value{F: 1, U: "s"}, timeConverter.Convert(Value{F: 1000000000, U: "ns"}, "s"))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user