From e9cca2f3f30e4e5bae4d6485a09cdfd7aea467c0 Mon Sep 17 00:00:00 2001 From: TeoV Date: Tue, 26 Sep 2017 09:52:29 +0300 Subject: [PATCH] Test metrics with more events and (statmetrics_test.go) --- engine/statmetrics.go | 32 ++-- engine/statmetrics_test.go | 297 ++++++++++++++++++++++++++++++++----- 2 files changed, 279 insertions(+), 50 deletions(-) diff --git a/engine/statmetrics.go b/engine/statmetrics.go index 32a23379f..5cdd664bb 100644 --- a/engine/statmetrics.go +++ b/engine/statmetrics.go @@ -141,19 +141,18 @@ func NewACD() (StatMetric, error) { // ACD implements AverageCallDuration metric type StatACD struct { Sum time.Duration - Count float64 + Count int64 Events map[string]time.Duration // map[EventTenantID]Duration - val *float64 // cached ACD value + val *time.Duration // cached ACD value } // getValue returns acr.val -func (acd *StatACD) getValue() float64 { +func (acd *StatACD) getValue() time.Duration { if acd.val == nil { if acd.Count == 0 { - acd.val = utils.Float64Pointer(float64(STATS_NA)) + acd.val = utils.DurationPointer(time.Duration((-1) * time.Nanosecond)) } else { - acd.val = utils.Float64Pointer(utils.Round(acd.Sum.Seconds()/acd.Count, - config.CgrConfig().RoundingDecimals, utils.ROUNDING_MIDDLE)) + acd.val = utils.DurationPointer(time.Duration(acd.Sum.Nanoseconds() / acd.Count)) } } return *acd.val @@ -171,7 +170,10 @@ func (acd *StatACD) GetValue() (v interface{}) { } func (acd *StatACD) GetFloat64Value() (v float64) { - return acd.getValue() + if acd.Count == 0 { + return -1.0 + } + return acd.getValue().Seconds() } func (acd *StatACD) AddEvent(ev *StatEvent) (err error) { @@ -222,19 +224,18 @@ func NewTCD() (StatMetric, error) { // TCD implements TotalCallDuration metric type StatTCD struct { Sum time.Duration - Count float64 + Count int64 Events map[string]time.Duration // map[EventTenantID]Duration - val *float64 // cached TCD value + val *time.Duration // cached TCD value } // getValue returns tcd.val -func (tcd *StatTCD) getValue() float64 { +func (tcd *StatTCD) getValue() time.Duration { if tcd.val == nil { if tcd.Count == 0 { - tcd.val = utils.Float64Pointer(float64(STATS_NA)) + tcd.val = utils.DurationPointer(time.Duration((-1) * time.Nanosecond)) } else { - tcd.val = utils.Float64Pointer(utils.Round(tcd.Sum.Seconds(), - config.CgrConfig().RoundingDecimals, utils.ROUNDING_MIDDLE)) + tcd.val = utils.DurationPointer(time.Duration(tcd.Sum.Nanoseconds())) } } return *tcd.val @@ -252,7 +253,10 @@ func (tcd *StatTCD) GetValue() (v interface{}) { } func (tcd *StatTCD) GetFloat64Value() (v float64) { - return tcd.getValue() + if tcd.Count == 0 { + return -1.0 + } + return tcd.getValue().Seconds() } func (tcd *StatTCD) AddEvent(ev *StatEvent) (err error) { diff --git a/engine/statmetrics_test.go b/engine/statmetrics_test.go index 32845ca8c..3e9e33162 100644 --- a/engine/statmetrics_test.go +++ b/engine/statmetrics_test.go @@ -46,15 +46,27 @@ func TestASRGetStringValue(t *testing.T) { if strVal := asr.GetStringValue(""); strVal != "50%" { t.Errorf("wrong asr value: %s", strVal) } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC)}} + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC)}} + asr.AddEvent(ev4) + asr.AddEvent(ev5) asr.RemEvent(ev.TenantID()) - if strVal := asr.GetStringValue(""); strVal != "0%" { + if strVal := asr.GetStringValue(""); strVal != "66.66667%" { t.Errorf("wrong asr value: %s", strVal) } asr.RemEvent(ev2.TenantID()) + if strVal := asr.GetStringValue(""); strVal != "100%" { + t.Errorf("wrong asr value: %s", strVal) + } + asr.RemEvent(ev4.TenantID()) + asr.RemEvent(ev5.TenantID()) if strVal := asr.GetStringValue(""); strVal != utils.NOT_AVAILABLE { t.Errorf("wrong asr value: %s", strVal) } - } func TestASRGetValue(t *testing.T) { @@ -77,11 +89,27 @@ func TestASRGetValue(t *testing.T) { if v := asr.GetValue(); v != 50.0 { t.Errorf("wrong asr value: %f", v) } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC)}} + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC)}} + asr.AddEvent(ev4) + asr.AddEvent(ev5) asr.RemEvent(ev.TenantID()) - if v := asr.GetValue(); v != 0.0 { + if v := asr.GetValue(); v != 66.666670 { t.Errorf("wrong asr value: %f", v) } asr.RemEvent(ev2.TenantID()) + if v := asr.GetValue(); v != 100.0 { + t.Errorf("wrong asr value: %f", v) + } + asr.RemEvent(ev4.TenantID()) + if v := asr.GetValue(); v != 100.0 { + t.Errorf("wrong asr value: %f", v) + } + asr.RemEvent(ev5.TenantID()) if v := asr.GetValue(); v != -1.0 { t.Errorf("wrong asr value: %f", v) } @@ -98,29 +126,107 @@ func TestACDGetStringValue(t *testing.T) { t.Errorf("wrong acd value: %s", strVal) } acd.AddEvent(ev) - if strVal := acd.GetStringValue(""); strVal != "10" { + if strVal := acd.GetStringValue(""); strVal != "10s" { t.Errorf("wrong acd value: %s", strVal) } ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2"} ev3 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_3"} acd.AddEvent(ev2) acd.AddEvent(ev3) - if strVal := acd.GetStringValue(""); strVal != "3.33333" { + if strVal := acd.GetStringValue(""); strVal != "3.333333333s" { t.Errorf("wrong acd value: %s", strVal) } acd.RemEvent(ev3.TenantID()) - if strVal := acd.GetStringValue(""); strVal != "5" { + if strVal := acd.GetStringValue(""); strVal != "5s" { t.Errorf("wrong acd value: %s", strVal) } acd.RemEvent(ev.TenantID()) - if strVal := acd.GetStringValue(""); strVal != "0" { + if strVal := acd.GetStringValue(""); strVal != "0s" { + t.Errorf("wrong acd value: %s", strVal) + } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "Usage": time.Duration(1 * time.Minute), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "Usage": time.Duration(1*time.Minute + 30*time.Second), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + acd.AddEvent(ev4) + if strVal := acd.GetStringValue(""); strVal != "30s" { + t.Errorf("wrong acd value: %s", strVal) + } + acd.AddEvent(ev5) + if strVal := acd.GetStringValue(""); strVal != "50s" { t.Errorf("wrong acd value: %s", strVal) } acd.RemEvent(ev2.TenantID()) + if strVal := acd.GetStringValue(""); strVal != "1m15s" { + t.Errorf("wrong acd value: %s", strVal) + } + acd.RemEvent(ev5.TenantID()) + acd.RemEvent(ev4.TenantID()) + acd.RemEvent(ev5.TenantID()) if strVal := acd.GetStringValue(""); strVal != utils.NOT_AVAILABLE { t.Errorf("wrong acd value: %s", strVal) } +} +func TestACDGetFloat64Value(t *testing.T) { + acd, _ := NewACD() + ev := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_1", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + "Usage": time.Duration(10 * time.Second)}} + acd.AddEvent(ev) + if v := acd.GetFloat64Value(); v != 10.0 { + t.Errorf("wrong acd value: %f", v) + } + ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2"} + acd.AddEvent(ev2) + if v := acd.GetFloat64Value(); v != 5.0 { + t.Errorf("wrong acd value: %f", v) + } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "Usage": time.Duration(1 * time.Minute), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "Usage": time.Duration(1*time.Minute + 30*time.Second), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + acd.AddEvent(ev4) + if strVal := acd.GetFloat64Value(); strVal != 23.333333333 { + t.Errorf("wrong acd value: %f", strVal) + } + acd.AddEvent(ev5) + if strVal := acd.GetFloat64Value(); strVal != 40.0 { + t.Errorf("wrong acd value: %f", strVal) + } + acd.RemEvent(ev2.TenantID()) + if strVal := acd.GetFloat64Value(); strVal != 53.333333333 { + t.Errorf("wrong acd value: %f", strVal) + } + acd.RemEvent(ev4.TenantID()) + if strVal := acd.GetFloat64Value(); strVal != 50.0 { + t.Errorf("wrong acd value: %f", strVal) + } + acd.RemEvent(ev.TenantID()) + if strVal := acd.GetFloat64Value(); strVal != 90.0 { + t.Errorf("wrong acd value: %f", strVal) + } + acd.RemEvent(ev5.TenantID()) + if strVal := acd.GetFloat64Value(); strVal != -1.0 { + t.Errorf("wrong acd value: %f", strVal) + } } func TestACDGetValue(t *testing.T) { @@ -130,29 +236,53 @@ func TestACDGetValue(t *testing.T) { "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), "Usage": time.Duration(10 * time.Second)}} acd.AddEvent(ev) - if v := acd.GetValue(); v != 10.0 { - t.Errorf("wrong acd value: %f", v) + if v := acd.GetValue(); v != time.Duration(10*time.Second) { + t.Errorf("wrong acd value: %+v", v) } - ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2"} + ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + "Usage": time.Duration(8 * time.Second)}} ev3 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_3"} acd.AddEvent(ev2) acd.AddEvent(ev3) - if v := acd.GetValue(); v != 3.33333 { - t.Errorf("wrong acd value: %f", v) - } - acd.RemEvent(ev3.TenantID()) - if v := acd.GetValue(); v != 5.0 { - t.Errorf("wrong acd value: %f", v) + if v := acd.GetValue(); v != time.Duration(6*time.Second) { + t.Errorf("wrong acd value: %+v", v) } acd.RemEvent(ev.TenantID()) - if v := acd.GetValue(); v != 0.0 { - t.Errorf("wrong acd value: %f", v) + if v := acd.GetValue(); v != time.Duration(4*time.Second) { + t.Errorf("wrong acd value: %+v", v) } acd.RemEvent(ev2.TenantID()) - if v := acd.GetValue(); v != -1.0 { - t.Errorf("wrong acd value: %f", v) + if v := acd.GetValue(); v != time.Duration(0*time.Second) { + t.Errorf("wrong acd value: %+v", v) + } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "Usage": time.Duration(1 * time.Minute), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "Usage": time.Duration(4*time.Minute + 30*time.Second), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + acd.AddEvent(ev4) + acd.AddEvent(ev5) + if v := acd.GetValue(); v != time.Duration(1*time.Minute+50*time.Second) { + t.Errorf("wrong acd value: %+v", v) + } + acd.RemEvent(ev5.TenantID()) + acd.RemEvent(ev4.TenantID()) + if v := acd.GetValue(); v != time.Duration(0*time.Second) { + t.Errorf("wrong acd value: %+v", v) + } + acd.RemEvent(ev3.TenantID()) + if v := acd.GetValue(); v != time.Duration((-1)*time.Nanosecond) { + t.Errorf("wrong acd value: %+v", v) } - } func TestTCDGetStringValue(t *testing.T) { @@ -166,7 +296,7 @@ func TestTCDGetStringValue(t *testing.T) { t.Errorf("wrong tcd value: %s", strVal) } tcd.AddEvent(ev) - if strVal := tcd.GetStringValue(""); strVal != "10" { + if strVal := tcd.GetStringValue(""); strVal != "10s" { t.Errorf("wrong tcd value: %s", strVal) } ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2", @@ -177,22 +307,96 @@ func TestTCDGetStringValue(t *testing.T) { ev3 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_3"} tcd.AddEvent(ev2) tcd.AddEvent(ev3) - if strVal := tcd.GetStringValue(""); strVal != "20" { + if strVal := tcd.GetStringValue(""); strVal != "20s" { t.Errorf("wrong tcd value: %s", strVal) } tcd.RemEvent(ev2.TenantID()) - if strVal := tcd.GetStringValue(""); strVal != "10" { + if strVal := tcd.GetStringValue(""); strVal != "10s" { t.Errorf("wrong tcd value: %s", strVal) } tcd.RemEvent(ev.TenantID()) - if strVal := tcd.GetStringValue(""); strVal != "0" { + if strVal := tcd.GetStringValue(""); strVal != "0s" { t.Errorf("wrong tcd value: %s", strVal) } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "Usage": time.Duration(1 * time.Minute), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "Usage": time.Duration(1*time.Minute + 30*time.Second), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + tcd.AddEvent(ev4) + tcd.AddEvent(ev5) + if strVal := tcd.GetStringValue(""); strVal != "2m30s" { + t.Errorf("wrong tcd value: %s", strVal) + } + tcd.RemEvent(ev4.TenantID()) + if strVal := tcd.GetStringValue(""); strVal != "1m30s" { + t.Errorf("wrong tcd value: %s", strVal) + } + tcd.RemEvent(ev5.TenantID()) tcd.RemEvent(ev3.TenantID()) if strVal := tcd.GetStringValue(""); strVal != utils.NOT_AVAILABLE { t.Errorf("wrong tcd value: %s", strVal) } +} +func TestTCDGetFloat64Value(t *testing.T) { + tcd, _ := NewTCD() + ev := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_1", + Fields: map[string]interface{}{ + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + "Usage": time.Duration(10 * time.Second)}} + tcd.AddEvent(ev) + if v := tcd.GetFloat64Value(); v != 10.0 { + t.Errorf("wrong tcd value: %f", v) + } + ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2"} + tcd.AddEvent(ev2) + if v := tcd.GetFloat64Value(); v != 10.0 { + t.Errorf("wrong tcd value: %f", v) + } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "Usage": time.Duration(1 * time.Minute), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "Usage": time.Duration(1*time.Minute + 30*time.Second), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + tcd.AddEvent(ev4) + if strVal := tcd.GetFloat64Value(); strVal != 70.0 { + t.Errorf("wrong tcd value: %f", strVal) + } + tcd.AddEvent(ev5) + if strVal := tcd.GetFloat64Value(); strVal != 160.0 { + t.Errorf("wrong tcd value: %f", strVal) + } + tcd.RemEvent(ev2.TenantID()) + if strVal := tcd.GetFloat64Value(); strVal != 160.0 { + t.Errorf("wrong tcd value: %f", strVal) + } + tcd.RemEvent(ev4.TenantID()) + if strVal := tcd.GetFloat64Value(); strVal != 100.0 { + t.Errorf("wrong tcd value: %f", strVal) + } + tcd.RemEvent(ev.TenantID()) + if strVal := tcd.GetFloat64Value(); strVal != 90.0 { + t.Errorf("wrong tcd value: %f", strVal) + } + tcd.RemEvent(ev5.TenantID()) + if strVal := tcd.GetFloat64Value(); strVal != -1.0 { + t.Errorf("wrong tcd value: %f", strVal) + } } func TestTCDGetValue(t *testing.T) { @@ -202,8 +406,8 @@ func TestTCDGetValue(t *testing.T) { "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), "Usage": time.Duration(10 * time.Second)}} tcd.AddEvent(ev) - if v := tcd.GetValue(); v != 10.0 { - t.Errorf("wrong tcd value: %f", v) + if v := tcd.GetValue(); v != time.Duration(10*time.Second) { + t.Errorf("wrong tcd value: %+v", v) } ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2", Fields: map[string]interface{}{ @@ -212,20 +416,41 @@ func TestTCDGetValue(t *testing.T) { ev3 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_3"} tcd.AddEvent(ev2) tcd.AddEvent(ev3) - if v := tcd.GetValue(); v != 15.000000 { - t.Errorf("wrong tcd value: %f", v) + if v := tcd.GetValue(); v != time.Duration(15*time.Second) { + t.Errorf("wrong tcd value: %+v", v) } tcd.RemEvent(ev.TenantID()) - if v := tcd.GetValue(); v != 5.000000 { - t.Errorf("wrong tcd value: %f", v) + if v := tcd.GetValue(); v != time.Duration(5*time.Second) { + t.Errorf("wrong tcd value: %+v", v) } tcd.RemEvent(ev2.TenantID()) - if v := tcd.GetValue(); v != 0.0 { - t.Errorf("wrong tcd value: %f", v) + if v := tcd.GetValue(); v != time.Duration(0*time.Second) { + t.Errorf("wrong tcd value: %+v", v) + } + ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4", + Fields: map[string]interface{}{ + "Usage": time.Duration(1 * time.Minute), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5", + Fields: map[string]interface{}{ + "Usage": time.Duration(1*time.Minute + 30*time.Second), + "AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + } + tcd.AddEvent(ev4) + tcd.AddEvent(ev5) + if v := tcd.GetValue(); v != time.Duration(2*time.Minute+30*time.Second) { + t.Errorf("wrong tcd value: %+v", v) + } + tcd.RemEvent(ev5.TenantID()) + tcd.RemEvent(ev4.TenantID()) + if v := tcd.GetValue(); v != time.Duration(0*time.Second) { + t.Errorf("wrong tcd value: %+v", v) } tcd.RemEvent(ev3.TenantID()) - if v := tcd.GetValue(); v != -1.0 { - t.Errorf("wrong tcd value: %f", v) + if v := tcd.GetValue(); v != time.Duration((-1)*time.Nanosecond) { + t.Errorf("wrong tcd value: %+v", v) } - }