diff --git a/cdrstats/metrics.go b/cdrstats/metrics.go index f15752bad..2f37b6bdb 100644 --- a/cdrstats/metrics.go +++ b/cdrstats/metrics.go @@ -26,13 +26,17 @@ type Metric interface { GetValue() float64 } +const ASR = "ASR" +const ACD = "ACD" +const ACC = "ACC" + func CreateMetric(metric string) Metric { switch metric { - case "ASR": + case ASR: return &ASRMetric{} - case "ACD": + case ACD: return &ACDMetric{} - case "ACC": + case ACC: return &ACCMetric{} } return nil diff --git a/cdrstats/stats.go b/cdrstats/stats.go index e5d99a212..c4c61b372 100644 --- a/cdrstats/stats.go +++ b/cdrstats/stats.go @@ -41,6 +41,9 @@ type QCDR struct { } func NewStatsQueue(conf *config.CdrStatsConfig) *StatsQueue { + if conf == nil { + return &StatsQueue{metrics: make(map[string]Metric)} + } sq := &StatsQueue{ conf: conf, metrics: make(map[string]Metric, len(conf.Metrics)), @@ -58,17 +61,17 @@ func (sq *StatsQueue) AppendCDR(cdr *utils.StoredCdr) { if sq.AcceptCDR(cdr) { qcdr := sq.SimplifyCDR(cdr) sq.cdrs = append(sq.cdrs, qcdr) - sq.AddToMetrics(qcdr) + sq.addToMetrics(qcdr) } } -func (sq *StatsQueue) AddToMetrics(cdr *QCDR) { +func (sq *StatsQueue) addToMetrics(cdr *QCDR) { for _, metric := range sq.metrics { metric.AddCDR(cdr) } } -func (sq *StatsQueue) RemoveFromMetrics(cdr *QCDR) { +func (sq *StatsQueue) removeFromMetrics(cdr *QCDR) { for _, metric := range sq.metrics { metric.RemoveCDR(cdr) } @@ -87,13 +90,13 @@ func (sq *StatsQueue) PurgeObsoleteCDRs() { currentLength := len(sq.cdrs) if currentLength > sq.conf.QueuedItems { for _, cdr := range sq.cdrs[:currentLength-sq.conf.QueuedItems] { - sq.RemoveFromMetrics(cdr) + sq.removeFromMetrics(cdr) } sq.cdrs = sq.cdrs[currentLength-sq.conf.QueuedItems:] } for i, cdr := range sq.cdrs { if time.Now().Sub(cdr.SetupTime) > sq.conf.TimeWindow { - sq.RemoveFromMetrics(cdr) + sq.removeFromMetrics(cdr) continue } else { if i > 0 { diff --git a/cdrstats/stats_test.go b/cdrstats/stats_test.go index e5f85cd13..994092ae1 100644 --- a/cdrstats/stats_test.go +++ b/cdrstats/stats_test.go @@ -17,3 +17,159 @@ along with this program. If not, see */ package cdrstats + +import ( + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" +) + +func TestStatsInit(t *testing.T) { + sq := NewStatsQueue(&config.CdrStatsConfig{Metrics: []string{ASR, ACC}}) + if len(sq.metrics) != 2 { + t.Error("Expected 2 metrics got ", len(sq.metrics)) + } +} + +func TestStatsValue(t *testing.T) { + sq := NewStatsQueue(&config.CdrStatsConfig{Metrics: []string{ASR, ACD, ACC}}) + cdr := &utils.StoredCdr{ + AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + Usage: 10 * time.Second, + Cost: 1, + } + sq.AppendCDR(cdr) + cdr.Cost = 2 + sq.AppendCDR(cdr) + cdr.Cost = 3 + sq.AppendCDR(cdr) + s := sq.GetStats() + if s[ASR] != 100 || + s[ACD] != 10 || + s[ACC] != 2 { + t.Errorf("Error getting stats: %+v", s) + } +} + +func TestStatsSimplifyCDR(t *testing.T) { + cdr := &utils.StoredCdr{ + TOR: "tor", + AccId: "accid", + CdrHost: "cdrhost", + CdrSource: "cdrsource", + ReqType: "reqtype", + Direction: "direction", + Tenant: "tenant", + Category: "category", + Account: "account", + Subject: "subject", + Destination: "12345678", + SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC), + Usage: 10 * time.Second, + MediationRunId: "mri", + Cost: 10, + } + sq := &StatsQueue{} + qcdr := sq.SimplifyCDR(cdr) + if cdr.SetupTime != qcdr.SetupTime || + cdr.AnswerTime != qcdr.AnswerTime || + cdr.Usage != qcdr.Usage || + cdr.Cost != qcdr.Cost { + t.Error("Failed to simplify cdr: %+v", qcdr) + } +} + +func TestAcceptCDR(t *testing.T) { + sq := NewStatsQueue(nil) + cdr := &utils.StoredCdr{ + TOR: "tor", + AccId: "accid", + CdrHost: "cdrhost", + CdrSource: "cdrsource", + ReqType: "reqtype", + Direction: "direction", + Tenant: "tenant", + Category: "category", + Account: "account", + Subject: "subject", + Destination: "12345678", + SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC), + Usage: 10 * time.Second, + MediationRunId: "mri", + Cost: 10, + } + sq.conf = &config.CdrStatsConfig{} + if sq.AcceptCDR(cdr) != true { + t.Error("Should have accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{TOR: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{CdrHost: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{CdrSource: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{Direction: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{Tenant: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{Category: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{Account: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{Subject: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{DestinationPrefix: []string{"test"}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{DestinationPrefix: []string{"test", "123"}} + if sq.AcceptCDR(cdr) != true { + t.Error("Should have accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC), time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC)}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC)}} + if sq.AcceptCDR(cdr) != true { + t.Error("Should have accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC), time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)}} + if sq.AcceptCDR(cdr) != true { + t.Error("Should have accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{UsageInterval: []time.Duration{11 * time.Second}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{UsageInterval: []time.Duration{1 * time.Second, 10 * time.Second}} + if sq.AcceptCDR(cdr) == true { + t.Error("Should have NOT accepted thif CDR: %+v", cdr) + } + sq.conf = &config.CdrStatsConfig{UsageInterval: []time.Duration{10 * time.Second, 11 * time.Second}} + if sq.AcceptCDR(cdr) != true { + t.Error("Should have accepted thif CDR: %+v", cdr) + } +}