diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 603a0fb74..4064c9765 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -31,7 +31,7 @@ import ( type ActionTrigger struct { Id string // for visual identification ThresholdType string //*min_counter, *max_counter, *min_balance, *max_balance - // stats: *min_asr, *max_asr, *min_acd, *max_acd, *min_acc, *max_acc, *min_tcc, *max_tcc + // stats: *min_asr, *max_asr, *min_acd, *max_acd, *min_tcd, *max_tcd, *min_acc, *max_acc, *min_tcc, *max_tcc ThresholdValue float64 Recurrent bool // reset eexcuted flag each run MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers diff --git a/engine/stats_metrics.go b/engine/stats_metrics.go index 84cefd4df..824e8ce78 100644 --- a/engine/stats_metrics.go +++ b/engine/stats_metrics.go @@ -32,6 +32,7 @@ type Metric interface { const ASR = "ASR" const ACD = "ACD" +const TCD = "TCD" const ACC = "ACC" const TCC = "TCC" const STATS_NA = -1 @@ -42,6 +43,8 @@ func CreateMetric(metric string) Metric { return &ASRMetric{} case ACD: return &ACDMetric{} + case TCD: + return &TCDMetric{} case ACC: return &ACCMetric{} case TCC: @@ -108,6 +111,34 @@ func (acd *ACDMetric) GetValue() float64 { return utils.Round(val, globalRoundingDecimals, utils.ROUNDING_MIDDLE) } +// TCD – Total Call Duration +// the sum of billable seconds (billsec) of answered calls +type TCDMetric struct { + sum time.Duration + count float64 +} + +func (tcd *TCDMetric) AddCdr(cdr *QCdr) { + if !cdr.AnswerTime.IsZero() { + tcd.sum += cdr.Usage + tcd.count += 1 + } +} + +func (tcd *TCDMetric) RemoveCdr(cdr *QCdr) { + if !cdr.AnswerTime.IsZero() { + tcd.sum -= cdr.Usage + tcd.count -= 1 + } +} + +func (tcd *TCDMetric) GetValue() float64 { + if tcd.count == 0 { + return STATS_NA + } + return utils.Round(tcd.sum.Seconds(), globalRoundingDecimals, utils.ROUNDING_MIDDLE) +} + // ACC – Average Call Cost // the sum of cost of answered calls divided by the number of these answered calls. type ACCMetric struct { diff --git a/engine/stats_queue.go b/engine/stats_queue.go index bfd8130c7..979d355db 100644 --- a/engine/stats_queue.go +++ b/engine/stats_queue.go @@ -36,6 +36,8 @@ var METRIC_TRIGGER_MAP = map[string]string{ "*max_asr": ASR, "*min_acd": ACD, "*max_acd": ACD, + "*min_tcd": TCD, + "*max_tcd": TCD, "*min_acc": ACC, "*max_acc": ACC, "*min_tcc": ACC, diff --git a/engine/stats_test.go b/engine/stats_test.go index a7ed23e0e..198e1200f 100644 --- a/engine/stats_test.go +++ b/engine/stats_test.go @@ -33,7 +33,7 @@ func TestStatsQueueInit(t *testing.T) { } func TestStatsValue(t *testing.T) { - sq := NewStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, ACC, TCC}}) + sq := NewStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}}) cdr := &StoredCdr{ AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), Usage: 10 * time.Second, @@ -47,6 +47,7 @@ func TestStatsValue(t *testing.T) { s := sq.GetStats() if s[ASR] != 100 || s[ACD] != 10 || + s[TCD] != 30 || s[ACC] != 2 || s[TCC] != 6 { t.Errorf("Error getting stats: %+v", s)