Update reply to include metrics per exporter

This commit is contained in:
TeoV
2020-09-03 17:38:09 +03:00
committed by Dan Christian Bogos
parent 8cc0af4981
commit 25933e9922
6 changed files with 87 additions and 141 deletions

View File

@@ -29,8 +29,6 @@ import (
"strings"
"time"
"github.com/cgrates/cgrates/ees"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/guardian"
@@ -1886,8 +1884,11 @@ func (apierSv1 *APIerSv1) ExportCDRs(args *utils.ArgExportCDRs, reply *map[strin
for exporterID := range rplyCdr {
(*reply)[utils.ExporterIDs] = append((*reply)[utils.ExporterIDs].([]string), exporterID)
}
} else if *reply, err = ees.MergeEEMetrics(rplyCdr); err != nil {
return
} else {
for exporterID, metrics := range rplyCdr {
(*reply)[exporterID] = metrics
}
}
return
}

View File

@@ -193,14 +193,31 @@ func testEEsExportCDRs(t *testing.T) {
t.Error("Unexpected error: ", err.Error())
}
time.Sleep(2 * time.Second)
if rply["FirstExpOrderID"] != 1.0 {
t.Errorf("Expected %+v, received: %+v", 1.0, rply["FirstExpOrderID"])
} else if rply["LastExpOrderID"] != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, rply["LastExpOrderID"])
} else if rply["NumberOfEvents"] != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, rply["NumberOfEvents"])
} else if rply["TotalCost"] != 4.04 {
t.Errorf("Expected %+v, received: %+v", 4.04, rply["TotalCost"])
if len(rply) != 1 {
t.Errorf("Expected %+v, received: %+v", 1, len(rply))
} else {
val, _ := rply["CSVExporter"]
for k, v := range val.(map[string]interface{}) {
switch k {
case utils.FirstExpOrderID:
if v != 1.0 {
t.Errorf("Expected %+v, received: %+v", 1.0, v)
}
case utils.LastExpOrderID:
if v != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, v)
}
case utils.NumberOfEvents:
if v != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, v)
}
case utils.TotalCost:
if v != 4.04 {
t.Errorf("Expected %+v, received: %+v", 4.04, v)
}
}
}
}
}
@@ -218,9 +235,9 @@ func testEEsVerifyExports(t *testing.T) {
if len(files) != 1 {
t.Errorf("Expected %+v, received: %+v", 1, len(files))
}
eCnt := "Cdr1,*raw,*voice,OriginCDR1,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,10000000000,1.01\n" +
"Cdr2,*raw,*voice,OriginCDR2,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,5000000000,1.01\n" +
"Cdr3,*raw,*voice,OriginCDR3,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,30000000000,1.01\n" +
eCnt := "Cdr1,*raw,*voice,OriginCDR1,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,10,1.01\n" +
"Cdr2,*raw,*voice,OriginCDR2,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,5,1.01\n" +
"Cdr3,*raw,*voice,OriginCDR3,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,30,1.01\n" +
"Cdr4,*raw,*voice,OriginCDR4,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,0,1.01\n"
if outContent1, err := ioutil.ReadFile(files[0]); err != nil {
t.Error(err)
@@ -240,14 +257,33 @@ func testEEsExportCDRsMultipleExporters(t *testing.T) {
t.Error("Unexpected error: ", err.Error())
}
time.Sleep(2 * time.Second)
if rply["FirstExpOrderID"] != 1.0 {
t.Errorf("Expected %+v, received: %+v", 1.0, rply["FirstExpOrderID"])
} else if rply["LastExpOrderID"] != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, rply["LastExpOrderID"])
} else if rply["NumberOfEvents"] != 8.0 {
t.Errorf("Expected %+v, received: %+v", 8.0, rply["NumberOfEvents"])
} else if rply["TotalCost"] != 8.08 {
t.Errorf("Expected %+v, received: %+v", 8.08, rply["TotalCost"])
if len(rply) != 2 {
t.Errorf("Expected %+v, received: %+v", 1, len(rply))
} else {
for _, expID := range []string{"CSVExporter", "CSVExporter2"} {
val, _ := rply[expID]
for k, v := range val.(map[string]interface{}) {
switch k {
case utils.FirstExpOrderID:
if v != 1.0 {
t.Errorf("Expected %+v, received: %+v", 1.0, v)
}
case utils.LastExpOrderID:
if v != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, v)
}
case utils.NumberOfEvents:
if v != 4.0 {
t.Errorf("Expected %+v, received: %+v", 4.0, v)
}
case utils.TotalCost:
if v != 4.04 {
t.Errorf("Expected %+v, received: %+v", 4.04, v)
}
}
}
}
}
}
@@ -265,9 +301,9 @@ func testEEsVerifyExportsMultipleExporters(t *testing.T) {
if len(files) != 1 {
t.Errorf("Expected %+v, received: %+v", 1, len(files))
}
eCnt := "Cdr1,*raw,*voice,OriginCDR1,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,10000000000,1.01\n" +
"Cdr2,*raw,*voice,OriginCDR2,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,5000000000,1.01\n" +
"Cdr3,*raw,*voice,OriginCDR3,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,30000000000,1.01\n" +
eCnt := "Cdr1,*raw,*voice,OriginCDR1,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,10,1.01\n" +
"Cdr2,*raw,*voice,OriginCDR2,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,5,1.01\n" +
"Cdr3,*raw,*voice,OriginCDR3,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,30,1.01\n" +
"Cdr4,*raw,*voice,OriginCDR4,*none,cgrates.org,call,1001,1001,+4986517174963,2018-10-04T15:03:10Z,2018-10-04T15:03:10Z,0,1.01\n"
if outContent1, err := ioutil.ReadFile(files[0]); err != nil {
t.Error(err)

View File

@@ -81,7 +81,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
},
@@ -107,7 +107,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
},
@@ -133,7 +133,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
}

View File

@@ -85,7 +85,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
},
@@ -111,7 +111,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
},
@@ -137,7 +137,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
}

View File

@@ -83,7 +83,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
},
@@ -109,7 +109,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
},
@@ -135,7 +135,7 @@
{"tag": "Destination", "path": "*exp.Destination", "type": "*variable", "value": "~*req.Destination"},
{"tag": "SetupTime", "path": "*exp.SetupTime", "type": "*variable", "value": "~*req.SetupTime{*time_string}" },
{"tag": "AnswerTime", "path": "*exp.AnswerTime", "type": "*variable", "value": "~*req.AnswerTime{*time_string}"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage"},
{"tag": "Usage", "path": "*exp.Usage", "type": "*variable", "value": "~*req.Usage{*duration_seconds}"},
{"tag": "Cost", "path": "*exp.Cost", "type": "*variable", "value": "~*req.Cost{*round:4}"},
],
}

View File

@@ -245,8 +245,21 @@ func (eeS *EventExporterS) V1ProcessEvent(cgrEv *utils.CGREventWithIDs, rply *ma
*rply = make(map[string]map[string]interface{})
metricMapLock.Lock()
for k, v := range metricsMap {
(*rply)[k] = v
for exporterID, metrics := range metricsMap {
(*rply)[exporterID] = make(map[string]interface{})
for key, val := range metrics {
switch key {
case utils.PositiveExports, utils.NegativeExports:
slsVal, canCast := val.(utils.StringSet)
if !canCast {
return fmt.Errorf("cannot cast to map[string]interface{} %+v for positive exports", val)
}
(*rply)[exporterID][key] = slsVal.AsSlice()
default:
(*rply)[exporterID][key] = val
}
}
}
metricMapLock.Unlock()
return
@@ -330,107 +343,3 @@ func updateEEMetrics(dc utils.MapStorage, ev engine.MapEvent, timezone string) {
}
}
}
func MergeEEMetrics(dc map[string]map[string]interface{}) (reply map[string]interface{}, err error) {
positiveExp := make(utils.StringSet)
negativeExp := make(utils.StringSet)
reply = map[string]interface{}{
utils.PositiveExports: positiveExp,
utils.NegativeExports: negativeExp,
}
for _, metrics := range dc {
for k, v := range metrics {
switch k {
case utils.NumberOfEvents:
val, err := utils.IfaceAsTInt64(v)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else {
reply[k] = reply[k].(int64) + val
}
case utils.PositiveExports:
val, canCast := v.(map[string]interface{})
if !canCast {
return nil, fmt.Errorf("cannot cast to map[string]interface{} %+v for positive exports", v)
}
for pos := range val {
positiveExp.Add(pos)
}
case utils.NegativeExports:
val, canCast := v.(map[string]interface{})
if !canCast {
return nil, fmt.Errorf("cannot cast to map[string]interface{} %+v for negative exports", v)
}
for neg := range val {
negativeExp.Add(neg)
}
case utils.FirstEventATime:
val, err := utils.IfaceAsTime(v, config.CgrConfig().GeneralCfg().DefaultTimezone)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else if val.Before(reply[k].(time.Time)) {
reply[k] = val
}
case utils.LastEventATime:
val, err := utils.IfaceAsTime(v, config.CgrConfig().GeneralCfg().DefaultTimezone)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else if val.After(reply[k].(time.Time)) {
reply[k] = val
}
case utils.FirstExpOrderID:
val, err := utils.IfaceAsTInt64(v)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else if reply[k].(int64) > val {
reply[k] = val
}
case utils.LastExpOrderID:
val, err := utils.IfaceAsTInt64(v)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else if reply[k].(int64) < val {
reply[k] = val
}
case utils.TotalCost:
val, err := utils.IfaceAsFloat64(v)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else {
reply[k] = reply[k].(float64) + val
}
case utils.TotalDuration, utils.TotalSMSUsage,
utils.TotalMMSUsage, utils.TotalGenericUsage,
utils.TotalDataUsage:
val, err := utils.IfaceAsDuration(v)
if err != nil {
return nil, err
}
if _, has := reply[k]; !has {
reply[k] = val
} else {
reply[k] = reply[k].(time.Duration) + val
}
}
}
}
return
}