diff --git a/data/tariffplans/testit/Filters.csv b/data/tariffplans/testit/Filters.csv index 80ed6745e..68292c5dd 100644 --- a/data/tariffplans/testit/Filters.csv +++ b/data/tariffplans/testit/Filters.csv @@ -24,4 +24,5 @@ cgrates.org,FLTR_QOS_SP2,*gte,~*vars.*tcd,11.0, cgrates.org,FLTR_SPP_QOS_2,*string,~*req.DistinctMatch,*qos_filtred2,2014-07-29T15:00:00Z cgrates.org,FLTR_QOS_SP1_2,*gte,~*vars.Cost,0.1,2014-07-29T15:00:00Z cgrates.org,FLTR_QOS_SP2_2,*gte,~*vars.Cost,0.2,2014-07-29T15:00:00Z -cgrates.org,FLTR_TEST,*string,~*req.Subject,TEST,2014-07-29T15:00:00Z \ No newline at end of file +cgrates.org,FLTR_TEST,*string,~*req.Subject,TEST,2014-07-29T15:00:00Z +cgrates.org,FLTR_SPP_LOAD_DIST,*string,~*req.DistinctMatch,LoadDistStrategy,2014-07-29T15:00:00Z \ No newline at end of file diff --git a/data/tariffplans/testit/Stats.csv b/data/tariffplans/testit/Stats.csv index ac5099bee..2944e22d6 100644 --- a/data/tariffplans/testit/Stats.csv +++ b/data/tariffplans/testit/Stats.csv @@ -2,4 +2,7 @@ cgrates.org,Stat_1,FLTR_STAT_1,2014-07-29T15:00:00Z,100,1s,0,*acd;*tcd;*asr,,false,true,30,*none cgrates.org,Stat_1_1,FLTR_STAT_1_1,2014-07-29T15:00:00Z,100,1s,0,*acd;*tcd;*pdd,,false,true,30,*none cgrates.org,Stat_2,FLTR_STAT_2,2014-07-29T15:00:00Z,100,1s,0,*acd;*tcd;*asr,,false,true,30,*none -cgrates.org,Stat_3,FLTR_STAT_3,2014-07-29T15:00:00Z,100,1s,0,*acd;*tcd;*asr,,false,true,30,*none \ No newline at end of file +cgrates.org,Stat_3,FLTR_STAT_3,2014-07-29T15:00:00Z,100,1s,0,*acd;*tcd;*asr,,false,true,30,*none +cgrates.org,Stat_Supplier1,*string:~*req.StatID:Stat_Supplier1,2014-07-29T15:00:00Z,100,1s,0,*sum:~LoadReq,,true,true,30,*none +cgrates.org,Stat_Supplier2,*string:~*req.StatID:Stat_Supplier2,2014-07-29T15:00:00Z,100,1s,0,*sum:~LoadReq,,true,true,30,*none +cgrates.org,Stat_Supplier3,*string:~*req.StatID:Stat_Supplier3,2014-07-29T15:00:00Z,100,1s,0,*sum:~LoadReq,,true,true,30,*none diff --git a/data/tariffplans/testit/Suppliers.csv b/data/tariffplans/testit/Suppliers.csv index 9b27b6888..ec25fb0cc 100644 --- a/data/tariffplans/testit/Suppliers.csv +++ b/data/tariffplans/testit/Suppliers.csv @@ -27,4 +27,7 @@ cgrates.org,SPL_QOS_FILTRED2,FLTR_SPP_QOS_2,2017-11-27T00:00:00Z,*qos,*acd;*tcd; cgrates.org,SPL_QOS_FILTRED2,,,,,supplier2,FLTR_QOS_SP2_2,,RP_RETAIL1,,Stat_2,20,,, cgrates.org,SPL_QOS_FILTRED2,,,,,supplier3,,,,,Stat_3,35,,, cgrates.org,SPL_LCR,FLTR_TEST,2017-11-27T00:00:00Z,*lc,,supplier_1,,,RP_TEST_1,,,10,,,50 -cgrates.org,SPL_LCR,,,,,supplier_2,,,RP_TEST_2,,,,,, \ No newline at end of file +cgrates.org,SPL_LCR,,,,,supplier_2,,,RP_TEST_2,,,,,, +cgrates.org,SPL_LOAD_DIST,FLTR_SPP_LOAD_DIST,,*load,supplier1:2;supplier2:7;*default:5,supplier1,,,,,Stat_Supplier1:*sum:~LoadReq,10,false,,20 +cgrates.org,SPL_LOAD_DIST,,,,,supplier2,,,,,Stat_Supplier2:*sum:~LoadReq,20,,, +cgrates.org,SPL_LOAD_DIST,,,,,supplier3,,,,,Stat_Supplier3:*sum:~LoadReq,35,,, \ No newline at end of file diff --git a/engine/spls_load_distribution.go b/engine/spls_load_distribution.go index 21531b124..6944ced35 100644 --- a/engine/spls_load_distribution.go +++ b/engine/spls_load_distribution.go @@ -52,7 +52,13 @@ func (ws *LoadDistributionSorter) SortSuppliers(prflID string, return nil, err } else if pass && srtSpl != nil { // Add the ratio in SortingData so we can used it later in SortLoadDistribution - srtSpl.SortingData[utils.Ratio] = s.cacheSupplier[utils.MetaRatio].(float64) + floatRatio, err := utils.IfaceAsFloat64(s.cacheSupplier[utils.MetaRatio]) + if err != nil { + utils.Logger.Warning( + fmt.Sprintf("<%s> cannot convert ratio <%s> to float64 supplier: <%s>", + utils.SupplierS, s.cacheSupplier[utils.MetaRatio], s.ID)) + } + srtSpl.SortingData[utils.Ratio] = floatRatio sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl) } } diff --git a/general_tests/supplier_it_test.go b/general_tests/supplier_it_test.go index 95cf8bbfa..eb5f69c26 100644 --- a/general_tests/supplier_it_test.go +++ b/general_tests/supplier_it_test.go @@ -56,6 +56,9 @@ var ( //tests for *reds sorting strategy testV1SplSAddNewSplPrf2, testV1SplSGetSortedSuppliers2, + //tests for *load sorting strategy + testV1SplSPopulateStats, + testV1SplSGetSoredSuppliersWithLoad, testV1SplSStopEngine, } ) @@ -544,6 +547,215 @@ func testV1SplSGetSortedSuppliers2(t *testing.T) { } } +func testV1SplSPopulateStats(t *testing.T) { + // in this test we simulate some Stat Requests + // so we can check the metrics in Suppliers for *load strategy + var reply []string + expected := []string{"Stat_Supplier1"} + ev1 := &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier1", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_Supplier1"} + ev1 = &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event2", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier1", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + var metrics map[string]string + expectedMetrics := map[string]string{ + utils.ConcatenatedKey(utils.MetaSum, utils.DynamicDataPrefix+"LoadReq"): "2", + } + if err := splSv1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithArgDispatcher{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "Stat_Supplier1"}}, + &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } + + expected = []string{"Stat_Supplier2"} + ev1 = &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event3", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier2", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_Supplier2"} + ev1 = &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event4", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier2", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + if err := splSv1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithArgDispatcher{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "Stat_Supplier2"}}, + &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } + + expected = []string{"Stat_Supplier3"} + ev1 = &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event5", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier3", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_Supplier3"} + ev1 = &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event6", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier3", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_Supplier3"} + ev1 = &engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event7", + Event: map[string]interface{}{ + "LoadReq": 1, + "StatID": "Stat_Supplier3", + }, + }, + } + if err := splSv1Rpc.Call(utils.StatSv1ProcessEvent, ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expectedMetrics = map[string]string{ + utils.ConcatenatedKey(utils.MetaSum, utils.DynamicDataPrefix+"LoadReq"): "3", + } + + if err := splSv1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithArgDispatcher{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "Stat_Supplier3"}}, + &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } +} + +func testV1SplSGetSoredSuppliersWithLoad(t *testing.T) { + ev := &engine.ArgsGetSuppliers{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testV1SplSGetSoredSuppliersWithLoad", + Event: map[string]interface{}{ + "DistinctMatch": "LoadDistStrategy", + }, + }, + } + expSuppliers := []*engine.SortedSupplier{ + &engine.SortedSupplier{ + SupplierID: "supplier2", + SupplierParameters: "", + SortingData: map[string]interface{}{ + "Load": 2.0, + "Ratio": 7.0, + "Weight": 20.0}, + }, + &engine.SortedSupplier{ + SupplierID: "supplier3", + SupplierParameters: "", + SortingData: map[string]interface{}{ + "Load": 3.0, + "Ratio": 5.0, + "Weight": 35.0}, + }, + &engine.SortedSupplier{ + SupplierID: "supplier1", + SupplierParameters: "", + SortingData: map[string]interface{}{ + "Load": 2.0, + "Ratio": 2.0, + "Weight": 10.0}, + }, + } + + var suplsReply engine.SortedSuppliers + if err := splSv1Rpc.Call(utils.SupplierSv1GetSuppliers, + ev, &suplsReply); err != nil { + t.Error(err) + } else { + if suplsReply.ProfileID != "SPL_LOAD_DIST" { + t.Errorf("Expecting: SPL_LOAD_DIST, received: %s", + suplsReply.ProfileID) + } + if !reflect.DeepEqual(suplsReply.SortedSuppliers, expSuppliers) { + t.Errorf("Expecting: %+v, \n received: %+v", + utils.ToJSON(expSuppliers), utils.ToJSON(suplsReply.SortedSuppliers)) + } + } +} + func testV1SplSStopEngine(t *testing.T) { if err := engine.KillEngine(100); err != nil { t.Error(err)