diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 6e731a612..78b9114d3 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -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 } diff --git a/apier/v1/ees_it_test.go b/apier/v1/ees_it_test.go index 8ca5fb29b..9fb32f899 100644 --- a/apier/v1/ees_it_test.go +++ b/apier/v1/ees_it_test.go @@ -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) diff --git a/data/conf/samples/ees_internal/cgrates.json b/data/conf/samples/ees_internal/cgrates.json index 358c02ae8..1d68a5853 100644 --- a/data/conf/samples/ees_internal/cgrates.json +++ b/data/conf/samples/ees_internal/cgrates.json @@ -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}"}, ], } diff --git a/data/conf/samples/ees_mongo/cgrates.json b/data/conf/samples/ees_mongo/cgrates.json index 784e156c5..11727688a 100644 --- a/data/conf/samples/ees_mongo/cgrates.json +++ b/data/conf/samples/ees_mongo/cgrates.json @@ -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}"}, ], } diff --git a/data/conf/samples/ees_mysql/cgrates.json b/data/conf/samples/ees_mysql/cgrates.json index f254a1fd5..8a42b059e 100644 --- a/data/conf/samples/ees_mysql/cgrates.json +++ b/data/conf/samples/ees_mysql/cgrates.json @@ -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}"}, ], } diff --git a/ees/ees.go b/ees/ees.go index 97f064bc6..7986af5a4 100644 --- a/ees/ees.go +++ b/ees/ees.go @@ -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 -}