Updated stats metrics

This commit is contained in:
Trial97
2020-11-03 17:11:40 +02:00
committed by Dan Christian Bogos
parent 0b55bc7899
commit eb57017632
8 changed files with 539 additions and 476 deletions

View File

@@ -68,12 +68,13 @@ type MetricWithFilters struct {
// NewStoredStatQueue initiates a StoredStatQueue out of StatQueue
func NewStoredStatQueue(sq *StatQueue, ms Marshaler) (sSQ *StoredStatQueue, err error) {
sSQ = &StoredStatQueue{
Tenant: sq.Tenant,
ID: sq.ID,
Compressed: sq.Compress(int64(config.CgrConfig().StatSCfg().StoreUncompressedLimit)),
SQItems: make([]SQItem, len(sq.SQItems)),
SQMetrics: make(map[string][]byte, len(sq.SQMetrics)),
MinItems: sq.MinItems,
Tenant: sq.Tenant,
ID: sq.ID,
Compressed: sq.Compress(int64(config.CgrConfig().StatSCfg().StoreUncompressedLimit),
config.CgrConfig().GeneralCfg().RoundingDecimals),
SQItems: make([]SQItem, len(sq.SQItems)),
SQMetrics: make(map[string][]byte, len(sq.SQMetrics)),
MinItems: sq.MinItems,
}
for i, sqItm := range sq.SQItems {
sSQ.SQItems[i] = sqItm
@@ -263,7 +264,7 @@ func (sq *StatQueue) addStatEvent(tnt, evID string, filterS *FilterS, evNm utils
return
}
func (sq *StatQueue) Compress(maxQL int64) bool {
func (sq *StatQueue) Compress(maxQL int64, roundDec int) bool {
if int64(len(sq.SQItems)) < maxQL || maxQL == 0 {
return false
}
@@ -278,7 +279,7 @@ func (sq *StatQueue) Compress(maxQL int64) bool {
}
for _, m := range sq.SQMetrics {
for _, id := range m.Compress(maxQL, defaultCompressID) {
for _, id := range m.Compress(maxQL, defaultCompressID, roundDec) {
idMap[id] = struct{}{}
}
}

View File

@@ -22,6 +22,7 @@ import (
"testing"
"time"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
@@ -60,29 +61,29 @@ func TestStatRemEventWithID(t *testing.T) {
},
}
asrMetric := sq.SQMetrics[utils.MetaASR].(*StatASR)
if asr := asrMetric.GetFloat64Value(); asr != 50 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 50 {
t.Errorf("received asrMetric: %v", asrMetric)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_1")
if asr := asrMetric.GetFloat64Value(); asr != 0 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 0 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 1 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_5") // non existent
if asr := asrMetric.GetFloat64Value(); asr != 0 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 0 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 1 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_2")
if asr := asrMetric.GetFloat64Value(); asr != -1 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != -1 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 0 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_2")
if asr := asrMetric.GetFloat64Value(); asr != -1 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != -1 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 0 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
@@ -103,31 +104,31 @@ func TestStatRemEventWithID2(t *testing.T) {
},
}
asrMetric := sq.SQMetrics[utils.MetaASR].(*StatASR)
if asr := asrMetric.GetFloat64Value(); asr != 50 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 50 {
t.Errorf("received asrMetric: %v", asrMetric)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_1")
sq.remEventWithID("cgrates.org:TestRemEventWithID_2")
if asr := asrMetric.GetFloat64Value(); asr != 50 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 50 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 2 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_5") // non existent
if asr := asrMetric.GetFloat64Value(); asr != 50 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 50 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 2 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_2")
sq.remEventWithID("cgrates.org:TestRemEventWithID_1")
if asr := asrMetric.GetFloat64Value(); asr != -1 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != -1 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 0 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
}
sq.remEventWithID("cgrates.org:TestRemEventWithID_2")
if asr := asrMetric.GetFloat64Value(); asr != -1 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != -1 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 0 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
@@ -154,11 +155,11 @@ func TestStatRemExpired(t *testing.T) {
},
}
asrMetric := sq.SQMetrics[utils.MetaASR].(*StatASR)
if asr := asrMetric.GetFloat64Value(); asr != 66.66667 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 66.66667 {
t.Errorf("received asrMetric: %v", asrMetric)
}
sq.remExpired()
if asr := asrMetric.GetFloat64Value(); asr != 100 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 100 {
t.Errorf("received asrMetric: %v", asrMetric)
} else if len(asrMetric.Events) != 1 {
t.Errorf("unexpected Events in asrMetric: %+v", asrMetric.Events)
@@ -216,12 +217,12 @@ func TestStatAddStatEvent(t *testing.T) {
},
}
asrMetric := sq.SQMetrics[utils.MetaASR].(*StatASR)
if asr := asrMetric.GetFloat64Value(); asr != 100 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 100 {
t.Errorf("received ASR: %v", asr)
}
ev1 := &utils.CGREvent{Tenant: "cgrates.org", ID: "TestStatAddStatEvent_1"}
sq.addStatEvent(ev1.Tenant, ev1.ID, nil, utils.MapStorage{utils.MetaReq: ev1.Event})
if asr := asrMetric.GetFloat64Value(); asr != 50 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 50 {
t.Errorf("received ASR: %v", asr)
} else if asrMetric.Answered != 1 || asrMetric.Count != 2 {
t.Errorf("ASR: %v", asrMetric)
@@ -229,7 +230,7 @@ func TestStatAddStatEvent(t *testing.T) {
ev1.Event = map[string]interface{}{
utils.AnswerTime: time.Now()}
sq.addStatEvent(ev1.Tenant, ev1.ID, nil, utils.MapStorage{utils.MetaReq: ev1.Event})
if asr := asrMetric.GetFloat64Value(); asr != 66.66667 {
if asr := asrMetric.GetFloat64Value(config.CgrConfig().GeneralCfg().RoundingDecimals); asr != 66.66667 {
t.Errorf("received ASR: %v", asr)
} else if asrMetric.Answered != 2 || asrMetric.Count != 3 {
t.Errorf("ASR: %v", asrMetric)
@@ -300,10 +301,10 @@ func TestStatCompress(t *testing.T) {
utils.MetaASR: asr,
},
}
if sq.Compress(int64(100)) {
if sq.Compress(int64(100), config.CgrConfig().GeneralCfg().RoundingDecimals) {
t.Errorf("StatQueue compressed: %s", utils.ToJSON(sq))
}
if !sq.Compress(int64(2)) {
if !sq.Compress(int64(2), config.CgrConfig().GeneralCfg().RoundingDecimals) {
t.Errorf("StatQueue not compressed: %s", utils.ToJSON(sq))
}
if !reflect.DeepEqual(sq.SQItems, expectedSqItems) {
@@ -364,10 +365,10 @@ func TestStatCompress2(t *testing.T) {
utils.MetaTCD: tcd,
},
}
if sq.Compress(int64(100)) {
if sq.Compress(int64(100), config.CgrConfig().GeneralCfg().RoundingDecimals) {
t.Errorf("StatQueue compressed: %s", utils.ToJSON(sq))
}
if !sq.Compress(int64(2)) {
if !sq.Compress(int64(2), config.CgrConfig().GeneralCfg().RoundingDecimals) {
t.Errorf("StatQueue not compressed: %s", utils.ToJSON(sq))
}
if !reflect.DeepEqual(sq.SQItems, expectedSqItems) {
@@ -435,10 +436,10 @@ func TestStatCompress3(t *testing.T) {
utils.MetaTCD: tcd,
},
}
if sq.Compress(int64(100)) {
if sq.Compress(int64(100), config.CgrConfig().GeneralCfg().RoundingDecimals) {
t.Errorf("StatQueue compressed: %s", utils.ToJSON(sq))
}
if !sq.Compress(int64(3)) {
if !sq.Compress(int64(3), config.CgrConfig().GeneralCfg().RoundingDecimals) {
t.Errorf("StatQueue not compressed: %s", utils.ToJSON(sq))
}
if !reflect.DeepEqual(sq.SQItems, expectedSqItems) {

View File

@@ -28,9 +28,6 @@ import (
"github.com/cgrates/cgrates/utils"
)
//to be moved in utils
const STATS_NA = -1.0
// ACDHelper structure
type DurationWithCompress struct {
Duration time.Duration
@@ -73,15 +70,15 @@ func NewStatMetric(metricID string, minItems int, filterIDs []string) (sm StatMe
// StatMetric is the interface which a metric should implement
type StatMetric interface {
GetValue() interface{}
GetStringValue(fmtOpts string) (val string)
GetFloat64Value() (val float64)
GetValue(roundingDecimal int) interface{}
GetStringValue(roundingDecimal int) (val string)
GetFloat64Value(roundingDecimal int) (val float64)
AddEvent(evID string, ev utils.DataProvider) error
RemEvent(evTenantID string) error
Marshal(ms Marshaler) (marshaled []byte, err error)
LoadMarshaled(ms Marshaler, marshaled []byte) (err error)
GetFilterIDs() (filterIDs []string)
Compress(queueLen int64, defaultID string) (eventIDs []string)
Compress(queueLen int64, defaultID string, roundingDec int) (eventIDs []string)
GetCompressFactor(events map[string]int) map[string]int
}
@@ -101,35 +98,35 @@ type StatASR struct {
}
// getValue returns asr.val
func (asr *StatASR) getValue() float64 {
func (asr *StatASR) getValue(roundingDecimal int) float64 {
if asr.val == nil {
if (asr.MinItems > 0 && asr.Count < int64(asr.MinItems)) || (asr.Count == 0) {
asr.val = utils.Float64Pointer(STATS_NA)
asr.val = utils.Float64Pointer(utils.StatsNA)
} else {
asr.val = utils.Float64Pointer(utils.Round((asr.Answered / float64(asr.Count) * 100.0),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE))
roundingDecimal, utils.ROUNDING_MIDDLE))
}
}
return *asr.val
}
// GetValue returns the ASR value as part of StatMetric interface
func (asr *StatASR) GetValue() (v interface{}) {
return asr.getValue()
func (asr *StatASR) GetValue(roundingDecimal int) (v interface{}) {
return asr.getValue(roundingDecimal)
}
func (asr *StatASR) GetStringValue(fmtOpts string) (valStr string) {
if val := asr.getValue(); val == STATS_NA {
func (asr *StatASR) GetStringValue(roundingDecimal int) (valStr string) {
if val := asr.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = fmt.Sprintf("%v%%", asr.getValue())
valStr = fmt.Sprintf("%v%%", asr.getValue(roundingDecimal))
}
return
}
// GetFloat64Value is part of StatMetric interface
func (asr *StatASR) GetFloat64Value() (val float64) {
return asr.getValue()
func (asr *StatASR) GetFloat64Value(roundingDecimal int) (val float64) {
return asr.getValue(roundingDecimal)
}
// AddEvent is part of StatMetric interface
@@ -197,7 +194,7 @@ func (asr *StatASR) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (asr *StatASR) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (asr *StatASR) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if asr.Count < queueLen {
for id := range asr.Events {
eventIDs = append(eventIDs, id)
@@ -206,7 +203,7 @@ func (asr *StatASR) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &StatWithCompress{
Stat: utils.Round(asr.Answered/float64(asr.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE),
roundingDecimal, utils.ROUNDING_MIDDLE),
CompressFactor: int(asr.Count),
}
asr.Events = map[string]*StatWithCompress{defaultID: stat}
@@ -241,37 +238,37 @@ type StatACD struct {
}
// getValue returns acd.val
func (acd *StatACD) getValue() time.Duration {
func (acd *StatACD) getValue(roundingDecimal int) time.Duration {
if acd.val == nil {
if (acd.MinItems > 0 && acd.Count < int64(acd.MinItems)) || (acd.Count == 0) {
acd.val = utils.DurationPointer(-time.Nanosecond)
} else {
acd.val = utils.DurationPointer(utils.RoundStatDuration(
time.Duration(acd.Sum.Nanoseconds()/acd.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals))
roundingDecimal))
}
}
return *acd.val
}
func (acd *StatACD) GetStringValue(fmtOpts string) (valStr string) {
if val := acd.getValue(); val == -time.Nanosecond {
func (acd *StatACD) GetStringValue(roundingDecimal int) (valStr string) {
if val := acd.getValue(roundingDecimal); val == -time.Nanosecond {
valStr = utils.NOT_AVAILABLE
} else {
valStr = fmt.Sprintf("%+v", acd.getValue())
valStr = fmt.Sprintf("%+v", acd.getValue(roundingDecimal))
}
return
}
func (acd *StatACD) GetValue() (v interface{}) {
return acd.getValue()
func (acd *StatACD) GetValue(roundingDecimal int) (v interface{}) {
return acd.getValue(roundingDecimal)
}
func (acd *StatACD) GetFloat64Value() (v float64) {
if val := acd.getValue(); val == -time.Nanosecond {
v = -1.0
func (acd *StatACD) GetFloat64Value(roundingDecimal int) (v float64) {
if val := acd.getValue(roundingDecimal); val == -time.Nanosecond {
v = utils.StatsNA
} else {
v = acd.getValue().Seconds()
v = acd.getValue(roundingDecimal).Seconds()
}
return
}
@@ -330,7 +327,7 @@ func (acd *StatACD) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (acd *StatACD) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (acd *StatACD) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if acd.Count < queueLen {
for id := range acd.Events {
eventIDs = append(eventIDs, id)
@@ -339,7 +336,7 @@ func (acd *StatACD) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &DurationWithCompress{
Duration: utils.RoundStatDuration(time.Duration(acd.Sum.Nanoseconds()/acd.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals),
roundingDecimal),
CompressFactor: int(acd.Count),
}
acd.Events = map[string]*DurationWithCompress{defaultID: stat}
@@ -374,38 +371,38 @@ type StatTCD struct {
}
// getValue returns tcd.val
func (tcd *StatTCD) getValue() time.Duration {
func (tcd *StatTCD) getValue(roundingDecimal int) time.Duration {
if tcd.val == nil {
if (tcd.MinItems > 0 && tcd.Count < int64(tcd.MinItems)) || (tcd.Count == 0) {
tcd.val = utils.DurationPointer(time.Duration((-1) * time.Nanosecond))
tcd.val = utils.DurationPointer(-time.Nanosecond)
} else {
tcd.val = utils.DurationPointer(utils.RoundStatDuration(
time.Duration(tcd.Sum.Nanoseconds()),
config.CgrConfig().GeneralCfg().RoundingDecimals))
roundingDecimal))
}
}
return *tcd.val
}
func (tcd *StatTCD) GetStringValue(fmtOpts string) (valStr string) {
if val := tcd.getValue(); val == time.Duration((-1)*time.Nanosecond) {
func (tcd *StatTCD) GetStringValue(roundingDecimal int) (valStr string) {
if val := tcd.getValue(roundingDecimal); val == -time.Nanosecond {
valStr = utils.NOT_AVAILABLE
} else {
valStr = fmt.Sprintf("%+v", tcd.getValue())
valStr = fmt.Sprintf("%+v", tcd.getValue(roundingDecimal))
}
return
}
func (tcd *StatTCD) GetValue() (v interface{}) {
return tcd.getValue()
func (tcd *StatTCD) GetValue(roundingDecimal int) (v interface{}) {
return tcd.getValue(roundingDecimal)
}
func (tcd *StatTCD) GetFloat64Value() (v float64) {
if val := tcd.getValue(); val == time.Duration((-1)*time.Nanosecond) {
v = -1.0
func (tcd *StatTCD) GetFloat64Value(roundingDecimal int) (v float64) {
if val := tcd.getValue(roundingDecimal); val == -time.Nanosecond {
v = utils.StatsNA
} else {
v = tcd.getValue().Seconds()
v = tcd.getValue(roundingDecimal).Seconds()
}
return
}
@@ -465,7 +462,7 @@ func (tcd *StatTCD) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (tcd *StatTCD) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (tcd *StatTCD) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if tcd.Count < queueLen {
for id := range tcd.Events {
eventIDs = append(eventIDs, id)
@@ -474,7 +471,7 @@ func (tcd *StatTCD) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &DurationWithCompress{
Duration: utils.RoundStatDuration(time.Duration(tcd.Sum.Nanoseconds()/tcd.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals),
roundingDecimal),
CompressFactor: int(tcd.Count),
}
tcd.Events = map[string]*DurationWithCompress{defaultID: stat}
@@ -509,34 +506,34 @@ type StatACC struct {
}
// getValue returns tcd.val
func (acc *StatACC) getValue() float64 {
func (acc *StatACC) getValue(roundingDecimal int) float64 {
if acc.val == nil {
if (acc.MinItems > 0 && acc.Count < int64(acc.MinItems)) || (acc.Count == 0) {
acc.val = utils.Float64Pointer(STATS_NA)
acc.val = utils.Float64Pointer(utils.StatsNA)
} else {
acc.val = utils.Float64Pointer(utils.Round(acc.Sum/float64(acc.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE))
roundingDecimal, utils.ROUNDING_MIDDLE))
}
}
return *acc.val
}
func (acc *StatACC) GetStringValue(fmtOpts string) (valStr string) {
if val := acc.getValue(); val == STATS_NA {
func (acc *StatACC) GetStringValue(roundingDecimal int) (valStr string) {
if val := acc.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = strconv.FormatFloat(acc.getValue(), 'f', -1, 64)
valStr = strconv.FormatFloat(acc.getValue(roundingDecimal), 'f', -1, 64)
}
return
}
func (acc *StatACC) GetValue() (v interface{}) {
return acc.getValue()
func (acc *StatACC) GetValue(roundingDecimal int) (v interface{}) {
return acc.getValue(roundingDecimal)
}
func (acc *StatACC) GetFloat64Value() (v float64) {
return acc.getValue()
func (acc *StatACC) GetFloat64Value(roundingDecimal int) (v float64) {
return acc.getValue(roundingDecimal)
}
func (acc *StatACC) AddEvent(evID string, ev utils.DataProvider) (err error) {
@@ -592,7 +589,7 @@ func (acc *StatACC) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (acc *StatACC) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (acc *StatACC) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if acc.Count < queueLen {
for id := range acc.Events {
eventIDs = append(eventIDs, id)
@@ -601,7 +598,7 @@ func (acc *StatACC) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &StatWithCompress{
Stat: utils.Round(acc.Sum/float64(acc.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE),
roundingDecimal, utils.ROUNDING_MIDDLE),
CompressFactor: int(acc.Count),
}
acc.Events = map[string]*StatWithCompress{defaultID: stat}
@@ -636,34 +633,34 @@ type StatTCC struct {
}
// getValue returns tcd.val
func (tcc *StatTCC) getValue() float64 {
func (tcc *StatTCC) getValue(roundingDecimal int) float64 {
if tcc.val == nil {
if (tcc.MinItems > 0 && tcc.Count < int64(tcc.MinItems)) || (tcc.Count == 0) {
tcc.val = utils.Float64Pointer(STATS_NA)
tcc.val = utils.Float64Pointer(utils.StatsNA)
} else {
tcc.val = utils.Float64Pointer(utils.Round(tcc.Sum,
config.CgrConfig().GeneralCfg().RoundingDecimals,
roundingDecimal,
utils.ROUNDING_MIDDLE))
}
}
return *tcc.val
}
func (tcc *StatTCC) GetStringValue(fmtOpts string) (valStr string) {
if val := tcc.getValue(); val == STATS_NA {
func (tcc *StatTCC) GetStringValue(roundingDecimal int) (valStr string) {
if val := tcc.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = strconv.FormatFloat(tcc.getValue(), 'f', -1, 64)
valStr = strconv.FormatFloat(tcc.getValue(roundingDecimal), 'f', -1, 64)
}
return
}
func (tcc *StatTCC) GetValue() (v interface{}) {
return tcc.getValue()
func (tcc *StatTCC) GetValue(roundingDecimal int) (v interface{}) {
return tcc.getValue(roundingDecimal)
}
func (tcc *StatTCC) GetFloat64Value() (v float64) {
return tcc.getValue()
func (tcc *StatTCC) GetFloat64Value(roundingDecimal int) (v float64) {
return tcc.getValue(roundingDecimal)
}
func (tcc *StatTCC) AddEvent(evID string, ev utils.DataProvider) (err error) {
@@ -721,7 +718,7 @@ func (tcc *StatTCC) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (tcc *StatTCC) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (tcc *StatTCC) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if tcc.Count < queueLen {
for id := range tcc.Events {
eventIDs = append(eventIDs, id)
@@ -730,7 +727,7 @@ func (tcc *StatTCC) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &StatWithCompress{
Stat: utils.Round((tcc.Sum / float64(tcc.Count)),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE),
roundingDecimal, utils.ROUNDING_MIDDLE),
CompressFactor: int(tcc.Count),
}
tcc.Events = map[string]*StatWithCompress{defaultID: stat}
@@ -765,37 +762,37 @@ type StatPDD struct {
}
// getValue returns pdd.val
func (pdd *StatPDD) getValue() time.Duration {
func (pdd *StatPDD) getValue(roundingDecimal int) time.Duration {
if pdd.val == nil {
if (pdd.MinItems > 0 && pdd.Count < int64(pdd.MinItems)) || (pdd.Count == 0) {
pdd.val = utils.DurationPointer(time.Duration((-1) * time.Nanosecond))
pdd.val = utils.DurationPointer(-time.Nanosecond)
} else {
pdd.val = utils.DurationPointer(utils.RoundStatDuration(
time.Duration(pdd.Sum.Nanoseconds()/pdd.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals))
roundingDecimal))
}
}
return *pdd.val
}
func (pdd *StatPDD) GetStringValue(fmtOpts string) (valStr string) {
if val := pdd.getValue(); val == time.Duration((-1)*time.Nanosecond) {
func (pdd *StatPDD) GetStringValue(roundingDecimal int) (valStr string) {
if val := pdd.getValue(roundingDecimal); val == -time.Nanosecond {
valStr = utils.NOT_AVAILABLE
} else {
valStr = fmt.Sprintf("%+v", pdd.getValue())
valStr = fmt.Sprintf("%+v", pdd.getValue(roundingDecimal))
}
return
}
func (pdd *StatPDD) GetValue() (v interface{}) {
return pdd.getValue()
func (pdd *StatPDD) GetValue(roundingDecimal int) (v interface{}) {
return pdd.getValue(roundingDecimal)
}
func (pdd *StatPDD) GetFloat64Value() (v float64) {
if val := pdd.getValue(); val == time.Duration((-1)*time.Nanosecond) {
v = -1.0
func (pdd *StatPDD) GetFloat64Value(roundingDecimal int) (v float64) {
if val := pdd.getValue(roundingDecimal); val == -time.Nanosecond {
v = utils.StatsNA
} else {
v = pdd.getValue().Seconds()
v = pdd.getValue(roundingDecimal).Seconds()
}
return
}
@@ -854,7 +851,7 @@ func (pdd *StatPDD) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (pdd *StatPDD) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (pdd *StatPDD) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if pdd.Count < queueLen {
for id := range pdd.Events {
eventIDs = append(eventIDs, id)
@@ -863,7 +860,7 @@ func (pdd *StatPDD) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &DurationWithCompress{
Duration: utils.RoundStatDuration(time.Duration(pdd.Sum.Nanoseconds()/pdd.Count),
config.CgrConfig().GeneralCfg().RoundingDecimals),
roundingDecimal),
CompressFactor: int(pdd.Count),
}
pdd.Events = map[string]*DurationWithCompress{defaultID: stat}
@@ -897,28 +894,28 @@ type StatDDC struct {
}
// getValue returns tcd.val
func (ddc *StatDDC) getValue() float64 {
func (ddc *StatDDC) getValue(roundingDecimal int) float64 {
if ddc.Count == 0 || ddc.Count < int64(ddc.MinItems) {
return STATS_NA
return utils.StatsNA
}
return float64(len(ddc.FieldValues))
}
func (ddc *StatDDC) GetStringValue(fmtOpts string) (valStr string) {
if val := ddc.getValue(); val == STATS_NA {
func (ddc *StatDDC) GetStringValue(roundingDecimal int) (valStr string) {
if val := ddc.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = strconv.FormatFloat(ddc.getValue(), 'f', -1, 64)
valStr = strconv.FormatFloat(ddc.getValue(roundingDecimal), 'f', -1, 64)
}
return
}
func (ddc *StatDDC) GetValue() (v interface{}) {
return ddc.getValue()
func (ddc *StatDDC) GetValue(roundingDecimal int) (v interface{}) {
return ddc.getValue(roundingDecimal)
}
func (ddc *StatDDC) GetFloat64Value() (v float64) {
return ddc.getValue()
func (ddc *StatDDC) GetFloat64Value(roundingDecimal int) (v float64) {
return ddc.getValue(roundingDecimal)
}
func (ddc *StatDDC) AddEvent(evID string, ev utils.DataProvider) (err error) {
@@ -996,7 +993,7 @@ func (ddc *StatDDC) GetFilterIDs() []string {
return ddc.FilterIDs
}
func (ddc *StatDDC) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (ddc *StatDDC) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
for id := range ddc.Events {
eventIDs = append(eventIDs, id)
}
@@ -1036,34 +1033,34 @@ type StatSum struct {
}
// getValue returns tcd.val
func (sum *StatSum) getValue() float64 {
func (sum *StatSum) getValue(roundingDecimal int) float64 {
if sum.val == nil {
if len(sum.Events) == 0 || sum.Count < int64(sum.MinItems) {
sum.val = utils.Float64Pointer(STATS_NA)
sum.val = utils.Float64Pointer(utils.StatsNA)
} else {
sum.val = utils.Float64Pointer(utils.Round(sum.Sum,
config.CgrConfig().GeneralCfg().RoundingDecimals,
roundingDecimal,
utils.ROUNDING_MIDDLE))
}
}
return *sum.val
}
func (sum *StatSum) GetStringValue(fmtOpts string) (valStr string) {
if val := sum.getValue(); val == STATS_NA {
func (sum *StatSum) GetStringValue(roundingDecimal int) (valStr string) {
if val := sum.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = strconv.FormatFloat(sum.getValue(), 'f', -1, 64)
valStr = strconv.FormatFloat(sum.getValue(roundingDecimal), 'f', -1, 64)
}
return
}
func (sum *StatSum) GetValue() (v interface{}) {
return sum.getValue()
func (sum *StatSum) GetValue(roundingDecimal int) (v interface{}) {
return sum.getValue(roundingDecimal)
}
func (sum *StatSum) GetFloat64Value() (v float64) {
return sum.getValue()
func (sum *StatSum) GetFloat64Value(roundingDecimal int) (v float64) {
return sum.getValue(roundingDecimal)
}
func (sum *StatSum) AddEvent(evID string, ev utils.DataProvider) (err error) {
@@ -1121,7 +1118,7 @@ func (sum *StatSum) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (sum *StatSum) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (sum *StatSum) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if sum.Count < queueLen {
for id := range sum.Events {
eventIDs = append(eventIDs, id)
@@ -1130,7 +1127,7 @@ func (sum *StatSum) Compress(queueLen int64, defaultID string) (eventIDs []strin
}
stat := &StatWithCompress{
Stat: utils.Round((sum.Sum / float64(sum.Count)),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE),
roundingDecimal, utils.ROUNDING_MIDDLE),
CompressFactor: int(sum.Count),
}
sum.Events = map[string]*StatWithCompress{defaultID: stat}
@@ -1167,34 +1164,34 @@ type StatAverage struct {
}
// getValue returns tcd.val
func (avg *StatAverage) getValue() float64 {
func (avg *StatAverage) getValue(roundingDecimal int) float64 {
if avg.val == nil {
if (avg.MinItems > 0 && avg.Count < int64(avg.MinItems)) || (avg.Count == 0) {
avg.val = utils.Float64Pointer(STATS_NA)
avg.val = utils.Float64Pointer(utils.StatsNA)
} else {
avg.val = utils.Float64Pointer(utils.Round((avg.Sum / float64(avg.Count)),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE))
roundingDecimal, utils.ROUNDING_MIDDLE))
}
}
return *avg.val
}
func (avg *StatAverage) GetStringValue(fmtOpts string) (valStr string) {
if val := avg.getValue(); val == STATS_NA {
func (avg *StatAverage) GetStringValue(roundingDecimal int) (valStr string) {
if val := avg.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = strconv.FormatFloat(avg.getValue(), 'f', -1, 64)
valStr = strconv.FormatFloat(avg.getValue(roundingDecimal), 'f', -1, 64)
}
return
}
func (avg *StatAverage) GetValue() (v interface{}) {
return avg.getValue()
func (avg *StatAverage) GetValue(roundingDecimal int) (v interface{}) {
return avg.getValue(roundingDecimal)
}
func (avg *StatAverage) GetFloat64Value() (v float64) {
return avg.getValue()
func (avg *StatAverage) GetFloat64Value(roundingDecimal int) (v float64) {
return avg.getValue(roundingDecimal)
}
func (avg *StatAverage) AddEvent(evID string, ev utils.DataProvider) (err error) {
@@ -1252,7 +1249,7 @@ func (avg *StatAverage) GetFilterIDs() []string {
}
// Compress is part of StatMetric interface
func (avg *StatAverage) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (avg *StatAverage) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
if avg.Count < queueLen {
for id := range avg.Events {
eventIDs = append(eventIDs, id)
@@ -1261,7 +1258,7 @@ func (avg *StatAverage) Compress(queueLen int64, defaultID string) (eventIDs []s
}
stat := &StatWithCompress{
Stat: utils.Round((avg.Sum / float64(avg.Count)),
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE),
roundingDecimal, utils.ROUNDING_MIDDLE),
CompressFactor: int(avg.Count),
}
avg.Events = map[string]*StatWithCompress{defaultID: stat}
@@ -1296,28 +1293,28 @@ type StatDistinct struct {
}
// getValue returns tcd.val
func (dst *StatDistinct) getValue() float64 {
func (dst *StatDistinct) getValue(roundingDecimal int) float64 {
if dst.Count == 0 || dst.Count < int64(dst.MinItems) {
return STATS_NA
return utils.StatsNA
}
return float64(len(dst.FieldValues))
}
func (dst *StatDistinct) GetStringValue(fmtOpts string) (valStr string) {
if val := dst.getValue(); val == STATS_NA {
func (dst *StatDistinct) GetStringValue(roundingDecimal int) (valStr string) {
if val := dst.getValue(roundingDecimal); val == utils.StatsNA {
valStr = utils.NOT_AVAILABLE
} else {
valStr = strconv.FormatFloat(dst.getValue(), 'f', -1, 64)
valStr = strconv.FormatFloat(dst.getValue(roundingDecimal), 'f', -1, 64)
}
return
}
func (dst *StatDistinct) GetValue() (v interface{}) {
return dst.getValue()
func (dst *StatDistinct) GetValue(roundingDecimal int) (v interface{}) {
return dst.getValue(roundingDecimal)
}
func (dst *StatDistinct) GetFloat64Value() (v float64) {
return dst.getValue()
func (dst *StatDistinct) GetFloat64Value(roundingDecimal int) (v float64) {
return dst.getValue(roundingDecimal)
}
func (dst *StatDistinct) AddEvent(evID string, ev utils.DataProvider) (err error) {
@@ -1400,7 +1397,7 @@ func (dst *StatDistinct) GetFilterIDs() []string {
return dst.FilterIDs
}
func (dst *StatDistinct) Compress(queueLen int64, defaultID string) (eventIDs []string) {
func (dst *StatDistinct) Compress(queueLen int64, defaultID string, roundingDecimal int) (eventIDs []string) {
for id := range dst.Events {
eventIDs = append(eventIDs, id)
}

File diff suppressed because it is too large Load Diff

View File

@@ -341,7 +341,7 @@ func (sS *StatService) processEvent(tnt string, args *StatsArgsProcessEvent) (st
},
}
for metricID, metric := range sq.SQMetrics {
thEv.Event[metricID] = metric.GetValue()
thEv.Event[metricID] = metric.GetValue(sS.cgrcfg.GeneralCfg().RoundingDecimals)
}
var tIDs []string
if err := sS.connMgr.Call(sS.cgrcfg.StatSCfg().ThresholdSConns, nil,
@@ -457,7 +457,7 @@ func (sS *StatService) V1GetQueueStringMetrics(args *utils.TenantID, reply *map[
sq.RLock()
metrics := make(map[string]string, len(sq.SQMetrics))
for metricID, metric := range sq.SQMetrics {
metrics[metricID] = metric.GetStringValue("")
metrics[metricID] = metric.GetStringValue(sS.cgrcfg.GeneralCfg().RoundingDecimals)
}
sq.RUnlock()
*reply = metrics
@@ -486,7 +486,7 @@ func (sS *StatService) V1GetQueueFloatMetrics(args *utils.TenantID, reply *map[s
sq.RLock()
metrics := make(map[string]float64, len(sq.SQMetrics))
for metricID, metric := range sq.SQMetrics {
metrics[metricID] = metric.GetFloat64Value()
metrics[metricID] = metric.GetFloat64Value(sS.cgrcfg.GeneralCfg().RoundingDecimals)
}
sq.RUnlock()
*reply = metrics