diff --git a/data/conf/samples/dispatchers/all/cgrates.json b/data/conf/samples/dispatchers/all/cgrates.json index d7304b433..7150d04c9 100644 --- a/data/conf/samples/dispatchers/all/cgrates.json +++ b/data/conf/samples/dispatchers/all/cgrates.json @@ -46,9 +46,14 @@ "suppliers": { "enabled": true, - // "stats_conns": [ - // {"address": "*internal"}, - // ], +}, + +"stats": { + "enabled": true, + "store_interval": "1s", + "thresholds_conns": [ + {"address": "*internal"} + ], }, } diff --git a/data/conf/samples/dispatchers/all2/cgrates.json b/data/conf/samples/dispatchers/all2/cgrates.json index 43fca6467..1b45f6d76 100644 --- a/data/conf/samples/dispatchers/all2/cgrates.json +++ b/data/conf/samples/dispatchers/all2/cgrates.json @@ -46,9 +46,14 @@ "suppliers": { "enabled": true, - // "stats_conns": [ - // {"address": "*internal"}, - // ], +}, + +"stats": { + "enabled": true, + "store_interval": "1s", + "thresholds_conns": [ + {"address": "*internal"} + ], }, } diff --git a/data/tariffplans/dispatchers/Attributes.csv b/data/tariffplans/dispatchers/Attributes.csv index e7bcd34d2..66e5b50d7 100644 --- a/data/tariffplans/dispatchers/Attributes.csv +++ b/data/tariffplans/dispatchers/Attributes.csv @@ -5,5 +5,6 @@ cgrates.org,ATTR_API_ATTR_AUTH,*auth,*string:APIKey:attr12345,,APIMethods,*any,A cgrates.org,ATTR_API_CHRG_AUTH,*auth,*string:APIKey:chrg12345,,APIMethods,*any,ChargerSv1.Ping&ChargerSv1.GetChargersForEvent&ChargerSv1.ProcessEvent,true,false,20 cgrates.org,ATTR_API_THR_AUTH,*auth,*string:APIKey:thr12345,,APIMethods,*any,ThresholdSv1.Ping&ThresholdSv1.GetThresholdsForEvent&ThresholdSv1.ProcessEvent,true,false,20 cgrates.org,ATTR_API_SUP_AUTH,*auth,*string:APIKey:sup12345,,APIMethods,*any,SupplierSv1.Ping&SupplierSv1.GetSuppliers,true,false,20 +cgrates.org,ATTR_API_STAT_AUTH,*auth,*string:APIKey:stat12345,,APIMethods,*any,StatSv1.Ping&StatSv1.GetStatQueuesForEvent&StatSv1.GetQueueStringMetrics&StatSv1.ProcessEvent,true,false,20 diff --git a/dispatchers/stats_it_test.go b/dispatchers/stats_it_test.go index 02e473847..6aa5b80e3 100755 --- a/dispatchers/stats_it_test.go +++ b/dispatchers/stats_it_test.go @@ -22,7 +22,6 @@ package dispatchers import ( "net/rpc" - "net/rpc/jsonrpc" "path" "reflect" "testing" @@ -43,143 +42,134 @@ var ( ) var sTestsDspSts = []func(t *testing.T){ - testDspStsInitCfg, - testDspStsInitDataDb, - testDspStsResetStorDb, - testDspStsStartEngine, - testDspStsRPCConn, + testDspStsPingFailover, + testDspStsGetStatFailover, + testDspStsPing, - testDspStsLoadData, - testDspStsAddStsibutesWithPermision, testDspStsTestAuthKey, - testDspStsAddStsibutesWithPermision2, testDspStsTestAuthKey2, - testDspStsKillEngine, } //Test start here func TestDspStatS(t *testing.T) { + allEngine = newTestEngine(t, path.Join(dspDataDir, "conf", "samples", "dispatchers", "all"), true, true) + allEngine2 = newTestEngine(t, path.Join(dspDataDir, "conf", "samples", "dispatchers", "all2"), true, true) + attrEngine = newTestEngine(t, path.Join(dspDataDir, "conf", "samples", "dispatchers", "attributes"), true, true) + dispEngine = newTestEngine(t, path.Join(dspDataDir, "conf", "samples", "dispatchers", "dispatchers"), true, true) + allEngine.loadData(t, path.Join(dspDataDir, "tariffplans", "tutorial")) + allEngine2.loadData(t, path.Join(dspDataDir, "tariffplans", "oldtutorial")) + attrEngine.loadData(t, path.Join(dspDataDir, "tariffplans", "dispatchers")) + time.Sleep(500 * time.Millisecond) for _, stest := range sTestsDspSts { t.Run("", stest) } + attrEngine.stopEngine(t) + dispEngine.stopEngine(t) + allEngine.stopEngine(t) + allEngine2.stopEngine(t) } -func testDspStsInitCfg(t *testing.T) { - var err error - dspStsCfgPath = path.Join(dspDataDir, "conf", "samples", "dispatcher") - dspStsCfg, err = config.NewCGRConfigFromFolder(dspStsCfgPath) - if err != nil { +func testDspStsPingFailover(t *testing.T) { + var reply string + if err := allEngine.RCP.Call(utils.StatSv1Ping, &utils.CGREvent{}, &reply); err != nil { + t.Error(err) + } else if reply != utils.Pong { + t.Errorf("Received: %s", reply) + } + ev := CGREvWithApiKey{ + CGREvent: utils.CGREvent{ + Tenant: "cgrates.org", + }, + APIKey: "stat12345", + } + if err := dispEngine.RCP.Call(utils.StatSv1Ping, &ev, &reply); err != nil { + t.Error(err) + } else if reply != utils.Pong { + t.Errorf("Received: %s", reply) + } + allEngine.stopEngine(t) + if err := dispEngine.RCP.Call(utils.StatSv1Ping, &ev, &reply); err != nil { + t.Error(err) + } else if reply != utils.Pong { + t.Errorf("Received: %s", reply) + } + allEngine2.stopEngine(t) + if err := dispEngine.RCP.Call(utils.StatSv1Ping, &ev, &reply); err == nil { + t.Errorf("Expected error but recived %v and reply %v\n", err, reply) + } + allEngine.startEngine(t) + allEngine2.startEngine(t) +} + +func testDspStsGetStatFailover(t *testing.T) { + var reply []string + var metrics map[string]string + expected := []string{"Stats1"} + args := ArgsStatProcessEventWithApiKey{ + APIKey: "stat12345", + StatsArgsProcessEvent: engine.StatsArgsProcessEvent{ + CGREvent: utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.EVENT_NAME: "Event1", + utils.Account: "1001", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: time.Duration(135 * time.Second), + utils.COST: 123.0, + utils.RunID: utils.DEFAULT_RUNID, + utils.Destination: "1002"}, + }, + }, + } + if err := dispEngine.RCP.Call(utils.StatSv1ProcessEvent, args, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + args2 := TntIDWithApiKey{ + APIKey: "stat12345", + TenantID: utils.TenantID{ + Tenant: "cgrates.org", + ID: "Stats1", + }, + } + allEngine.stopEngine(t) + if err := dispEngine.RCP.Call(utils.StatSv1GetQueueStringMetrics, + args2, &metrics); err != nil { t.Error(err) } - dspStsCfg.DataFolderPath = dspDataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(dspStsCfg) - instStsCfgPath = path.Join(dspDataDir, "conf", "samples", "tutmysql") - instStsCfg, err = config.NewCGRConfigFromFolder(instStsCfgPath) - if err != nil { - t.Error(err) - } - instStsCfg.DataFolderPath = dspDataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(instStsCfg) -} -func testDspStsInitDataDb(t *testing.T) { - if err := engine.InitDataDb(instStsCfg); err != nil { - t.Fatal(err) - } -} + allEngine.startEngine(t) + allEngine2.stopEngine(t) -// Wipe out the cdr database -func testDspStsResetStorDb(t *testing.T) { - if err := engine.InitStorDb(instStsCfg); err != nil { - t.Fatal(err) + if err := dispEngine.RCP.Call(utils.StatSv1GetQueueStringMetrics, + args2, &metrics); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Errorf("Expected error NOT_FOUND but recived %v and reply %v\n", err, reply) } -} - -// Start CGR Engine -func testDspStsStartEngine(t *testing.T) { - if _, err := engine.StartEngine(instStsCfgPath, dspDelay); err != nil { - t.Fatal(err) - } - if _, err := engine.StartEngine(dspStsCfgPath, dspDelay); err != nil { - t.Fatal(err) - } -} - -// Connect rpc client to rater -func testDspStsRPCConn(t *testing.T) { - var err error - instStsRPC, err = jsonrpc.Dial("tcp", instStsCfg.ListenCfg().RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } - dspStsRPC, err = jsonrpc.Dial("tcp", dspStsCfg.ListenCfg().RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } - + allEngine2.startEngine(t) } func testDspStsPing(t *testing.T) { var reply string - if err := instStsRPC.Call(utils.StatSv1Ping, "", &reply); err != nil { + if err := allEngine.RCP.Call(utils.StatSv1Ping, &utils.CGREvent{}, &reply); err != nil { t.Error(err) } else if reply != utils.Pong { t.Errorf("Received: %s", reply) } - if err := dspStsRPC.Call(utils.StatSv1Ping, "", &reply); err != nil { + if err := dispEngine.RCP.Call(utils.StatSv1Ping, &CGREvWithApiKey{ + CGREvent: utils.CGREvent{ + Tenant: "cgrates.org", + }, + APIKey: "stat12345", + }, &reply); err != nil { t.Error(err) } else if reply != utils.Pong { t.Errorf("Received: %s", reply) } } -func testDspStsLoadData(t *testing.T) { - var reply string - Stss := &utils.AttrLoadTpFromFolder{ - FolderPath: path.Join(dspDataDir, "tariffplans", "tutorial")} - if err := instStsRPC.Call("ApierV1.LoadTariffPlanFromFolder", Stss, &reply); err != nil { - t.Error(err) - } - time.Sleep(500 * time.Millisecond) -} - -func testDspStsAddStsibutesWithPermision(t *testing.T) { - alsPrf := &engine.AttributeProfile{ - Tenant: "cgrates.org", - ID: "AuthKey", - Contexts: []string{utils.MetaAuth}, - FilterIDs: []string{"*string:APIKey:12345"}, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), - }, - Attributes: []*engine.Attribute{ - { - FieldName: utils.APIMethods, - Initial: utils.META_ANY, - Substitute: config.NewRSRParsersMustCompile("ThresholdSv1.GetThSessionholdsForEvent", true, utils.INFIELD_SEP), - Append: true, - }, - }, - Weight: 20, - } - var result string - if err := instStsRPC.Call("ApierV1.SetAttributeProfile", alsPrf, &result); err != nil { - t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) - } - alsPrf.Compile() - var reply *engine.AttributeProfile - if err := instStsRPC.Call("ApierV1.GetAttributeProfile", - &utils.TenantID{Tenant: "cgrates.org", ID: "AuthKey"}, &reply); err != nil { - t.Error(err) - } - reply.Compile() - if !reflect.DeepEqual(alsPrf, reply) { - t.Errorf("Expecting : %+v, received: %+v", alsPrf, reply) - } -} - func testDspStsTestAuthKey(t *testing.T) { var reply []string args := ArgsStatProcessEventWithApiKey{ @@ -195,7 +185,7 @@ func testDspStsTestAuthKey(t *testing.T) { utils.COST: 123.0, utils.PDD: time.Duration(12 * time.Second)}}, }} - if err := dspStsRPC.Call(utils.StatSv1ProcessEvent, + if err := dispEngine.RCP.Call(utils.StatSv1ProcessEvent, args, &reply); err == nil || err.Error() != utils.ErrUnauthorizedApi.Error() { t.Error(err) } @@ -209,55 +199,18 @@ func testDspStsTestAuthKey(t *testing.T) { } var metrics map[string]string - if err := dspStsRPC.Call(utils.StatSv1GetQueueStringMetrics, + if err := dispEngine.RCP.Call(utils.StatSv1GetQueueStringMetrics, args2, &metrics); err == nil || err.Error() != utils.ErrUnauthorizedApi.Error() { t.Error(err) } } -func testDspStsAddStsibutesWithPermision2(t *testing.T) { - alsPrf := &engine.AttributeProfile{ - Tenant: "cgrates.org", - ID: "AuthKey", - Contexts: []string{utils.MetaAuth}, - FilterIDs: []string{"*string:APIKey:12345"}, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), - }, - Attributes: []*engine.Attribute{ - { - FieldName: utils.APIMethods, - Initial: utils.META_ANY, - Substitute: config.NewRSRParsersMustCompile("StatSv1.ProcessEvent&StatSv1.GetQueueStringMetrics", true, utils.INFIELD_SEP), - Append: true, - }, - }, - Weight: 20, - } - var result string - if err := instStsRPC.Call("ApierV1.SetAttributeProfile", alsPrf, &result); err != nil { - t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) - } - alsPrf.Compile() - var reply *engine.AttributeProfile - if err := instStsRPC.Call("ApierV1.GetAttributeProfile", - &utils.TenantID{Tenant: "cgrates.org", ID: "AuthKey"}, &reply); err != nil { - t.Error(err) - } - reply.Compile() - if !reflect.DeepEqual(alsPrf, reply) { - t.Errorf("Expecting : %+v, received: %+v", alsPrf, reply) - } -} - func testDspStsTestAuthKey2(t *testing.T) { var reply []string var metrics map[string]string expected := []string{"Stats2"} args := ArgsStatProcessEventWithApiKey{ - APIKey: "12345", + APIKey: "stat12345", StatsArgsProcessEvent: engine.StatsArgsProcessEvent{ CGREvent: utils.CGREvent{ Tenant: "cgrates.org", @@ -272,14 +225,14 @@ func testDspStsTestAuthKey2(t *testing.T) { }, }, } - if err := dspStsRPC.Call(utils.StatSv1ProcessEvent, args, &reply); err != nil { + if err := dispEngine.RCP.Call(utils.StatSv1ProcessEvent, args, &reply); err != nil { t.Error(err) } else if !reflect.DeepEqual(reply, expected) { t.Errorf("Expecting: %+v, received: %+v", expected, reply) } args2 := TntIDWithApiKey{ - APIKey: "12345", + APIKey: "stat12345", TenantID: utils.TenantID{ Tenant: "cgrates.org", ID: "Stats2", @@ -290,7 +243,7 @@ func testDspStsTestAuthKey2(t *testing.T) { utils.MetaTCD: "2m15s", } - if err := dspStsRPC.Call(utils.StatSv1GetQueueStringMetrics, + if err := dispEngine.RCP.Call(utils.StatSv1GetQueueStringMetrics, args2, &metrics); err != nil { t.Error(err) } else if !reflect.DeepEqual(expectedMetrics, metrics) { @@ -298,7 +251,7 @@ func testDspStsTestAuthKey2(t *testing.T) { } args = ArgsStatProcessEventWithApiKey{ - APIKey: "12345", + APIKey: "stat12345", StatsArgsProcessEvent: engine.StatsArgsProcessEvent{ CGREvent: utils.CGREvent{ Tenant: "cgrates.org", @@ -314,7 +267,7 @@ func testDspStsTestAuthKey2(t *testing.T) { }, }, } - if err := dspStsRPC.Call(utils.StatSv1ProcessEvent, args, &reply); err != nil { + if err := dispEngine.RCP.Call(utils.StatSv1ProcessEvent, args, &reply); err != nil { t.Error(err) } else if !reflect.DeepEqual(reply, expected) { t.Errorf("Expecting: %+v, received: %+v", expected, reply) @@ -324,19 +277,10 @@ func testDspStsTestAuthKey2(t *testing.T) { utils.MetaTCC: "133", utils.MetaTCD: "3m0s", } - if err := dspStsRPC.Call(utils.StatSv1GetQueueStringMetrics, + if err := dispEngine.RCP.Call(utils.StatSv1GetQueueStringMetrics, args2, &metrics); err != nil { t.Error(err) } else if !reflect.DeepEqual(expectedMetrics, metrics) { t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) } } - -func testDspStsKillEngine(t *testing.T) { - if err := engine.KillEngine(dspDelay); err != nil { - t.Error(err) - } - if err := engine.KillEngine(dspDelay); err != nil { - t.Error(err) - } -}