diff --git a/apier/v1/tptrends_it_test.go b/apier/v1/tptrends_it_test.go index 7dcd4ae4e..6799eb075 100644 --- a/apier/v1/tptrends_it_test.go +++ b/apier/v1/tptrends_it_test.go @@ -125,11 +125,8 @@ func testTPTrendsSetTPTrend(t *testing.T) { Tenant: "cgrates.org", TPid: "TPS1", ID: "Trend1", + StatID: "STS1", ThresholdIDs: []string{"ThreshValue", "ThreshValueTwo"}, - Metrics: []utils.MetricWithSettings{ - {MetricID: "Metric"}, - }, - Trend: "*average", } sort.Strings(tpTrend.ThresholdIDs) var result string @@ -154,6 +151,7 @@ func testTPTrendsGetTPTrendAfterSet(t *testing.T) { func testTPTrendsUpdateTPTrend(t *testing.T) { var result string + tpTrend.StatID = "Stats2" if err := tpTrendRPC.Call(context.Background(), utils.APIerSv1SetTPTrend, tpTrend, &result); err != nil { t.Error(err) } else if result != utils.OK { diff --git a/apier/v1/trends_it_test.go b/apier/v1/trends_it_test.go index 775420db0..5e8951838 100644 --- a/apier/v1/trends_it_test.go +++ b/apier/v1/trends_it_test.go @@ -23,6 +23,7 @@ package v1 import ( "path" "testing" + "time" "github.com/cgrates/birpc" "github.com/cgrates/birpc/context" @@ -37,7 +38,6 @@ var ( trendCfgPath string trendCfg *config.CGRConfig trendRPC *birpc.Client - trendProfile *engine.TrendProfileWithAPIOpts trendProfile2 *engine.TrendProfileWithAPIOpts trendConfigDIR string @@ -47,7 +47,7 @@ var ( testTrendSResetStorDb, testTrendSStartEngine, testTrendSRPCConn, - testTrendSLoadAdd, + testTrendSFromFolder, testTrendSetTrendProfile, testTrendSGetTrendProfileIDs, testTrendSGetTrendProfiles, @@ -112,22 +112,13 @@ func testTrendSRPCConn(t *testing.T) { t.Fatal(err) } } -func testTrendSLoadAdd(t *testing.T) { - trendProfile = &engine.TrendProfileWithAPIOpts{ - TrendProfile: &engine.TrendProfile{ - Tenant: "cgrates.org", - ID: "TR_AVG", - StatID: "Stat1", - }, - } - - var result string - if err := trendRPC.Call(context.Background(), utils.APIerSv1SetTrendProfile, trendProfile, &result); err != nil { +func testTrendSFromFolder(t *testing.T) { + var reply string + attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "oldtutorial")} + if err := trendRPC.Call(context.Background(), utils.APIerSv1LoadTariffPlanFromFolder, attrs, &reply); err != nil { t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) } - + time.Sleep(100 * time.Millisecond) } func testTrendSetTrendProfile(t *testing.T) { @@ -158,7 +149,7 @@ func testTrendSetTrendProfile(t *testing.T) { } } func testTrendSGetTrendProfileIDs(t *testing.T) { - expected := []string{"Trend1", "TR_AVG"} + expected := []string{"Trend1", "TR_1"} var result []string if err := trendRPC.Call(context.Background(), utils.APIerSv1GetTrendProfileIDs, utils.PaginatorWithTenant{}, &result); err != nil { t.Error(err) @@ -181,9 +172,22 @@ func testTrendSGetTrendProfiles(t *testing.T) { } else if result != utils.OK { t.Errorf("Expected: %v,Received: %v", utils.OK, result) } + tpTr := &engine.TrendProfile{ + Tenant: "cgrates.org", + ID: "TR_1", + StatID: "Stats1", + Schedule: "0 1 * * *", + Metrics: []string{"*acc"}, + QueueLength: -1, + MinItems: 1, + CorrelationType: "*last", + Tolerance: 5, + Stored: false, + ThresholdIDs: []string{"TD1"}, + } expRes := []*engine.TrendProfile{ trendPrf.TrendProfile, - trendProfile.TrendProfile, + tpTr, trendProfile2.TrendProfile, } var tResult []*engine.TrendProfile @@ -196,7 +200,7 @@ func testTrendSGetTrendProfiles(t *testing.T) { } expRes = []*engine.TrendProfile{ - trendProfile.TrendProfile, + tpTr, trendProfile2.TrendProfile, } @@ -224,7 +228,7 @@ func testTrendSUpdateTrendProfile(t *testing.T) { reply *engine.TrendProfileWithAPIOpts result string ) - if err := trendRPC.Call(context.Background(), utils.APIerSv1SetTrendProfile, trendProfile, &result); err != nil { + if err := trendRPC.Call(context.Background(), utils.APIerSv1SetTrendProfile, trendProfile2, &result); err != nil { t.Error(err) } if err := trendRPC.Call(context.Background(), utils.APIerSv1GetTrendProfile, &utils.TenantID{Tenant: "cgrates.org", ID: "Trend1"}, &reply); err != nil { diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index d3062ca17..81aa73c88 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -330,11 +330,12 @@ CREATE TABLE tp_trends( `schedule` varchar(64) NOT NULL, `stat_id` varchar(64) NOT NULL, `metrics` varchar(128) NOT NULL, - `trend_swing_margin` decimal(8,2) NOT NULL, `queue_length` int(11) NOT NULL, `ttl` varchar(32) NOT NULL, - `trend` varchar(64) NOT NULL, - `trend_type` varchar(64) NOT NULL, + `min_items` int(11) NOT NULL, + `correlation_type` varchar(64) NOT NULL, + `tolerance` decimal(8,2) NOT NULL, + `stored` BOOLEAN NOT NULL, `threshold_ids` varchar(64) NOT NULL, `created_at` TIMESTAMP, PRIMARY KEY (`pk`), diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index 060c2f227..b19efb7ba 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -323,11 +323,12 @@ CREATE TABLE tp_trends( "schedule" varchar(64) NOT NULL, "stat_id" varchar(64) NOT NULL, "metrics" varchar(128) NOT NULL, - "trend_swing_margin" decimal(8,2) NOT NULL, "queue_length" INTEGER NOT NULL, "ttl" varchar(32) NOT NULL, - "trend" varchar(32) NOT NULL, - "trend_type" varchar(64) NOT NULL, + "min_items" INTEGER NOT NULL, + "correlation_type" varchar(64) NOT NULL, + "tolerance" decimal(8,2) NOT NULL, + "stored" BOOLEAN NOT NULL, "threshold_ids" varchar(64) NOT NULL, "created_at" TIMESTAMP ); diff --git a/data/tariffplans/oldtutorial/Trends.csv b/data/tariffplans/oldtutorial/Trends.csv new file mode 100644 index 000000000..043703a36 --- /dev/null +++ b/data/tariffplans/oldtutorial/Trends.csv @@ -0,0 +1,2 @@ +#Tenant[0],Id[1],Schedule[2],StatID[3],Metrics[4],QueueLength[5],TTL[6],MinItems[7],CorrelationType[8],Tolerance[9],Stored[10],ThresholdIDs[11] +cgrates.org,TR_1,0 1 * * *,Stats1,*acc,-1,0,1,*last,5,false,TD1 diff --git a/data/tariffplans/testtp/Trends.csv b/data/tariffplans/testtp/Trends.csv new file mode 100644 index 000000000..1015d915b --- /dev/null +++ b/data/tariffplans/testtp/Trends.csv @@ -0,0 +1,2 @@ +#Tenant[0],Id[1],Schedule[2],StatID[3],Metrics[4],QueueLength[5],TTL[6],MinItems[7],CorrelationType[8],Tolerance[9],Stored[10],ThresholdIDs[11] +cgrates.org,TREND1,0 12 * * *,Stats2,*acc;*tcc,-1,-1,1,*average,2.1,true,TD1;TD2 diff --git a/engine/libtest.go b/engine/libtest.go index 5878adf32..36b50e013 100644 --- a/engine/libtest.go +++ b/engine/libtest.go @@ -247,8 +247,8 @@ cgrates.org,TestStats2,,,,,2,*sum#~*req.Cost;*average#~*req.Cost,,true,true,20, cgrates.org,Ranking1,15m,Stats2;Stats3;Stats4,Metric1;Metric3,*asc,,THD1;THD2 ` TrendsCSVContent = ` -#Tenant[0],Id[1],QueryInterval[2],StatID[3],QueueLength[4],TTL[5],PurgeFilterIDs[6],Trend[7],ThresholdIDs[7] -cgrates.org,TREND1,5m,Stats2,-1,-1,,*average,TD1;THD2 +#Tenant[0],Id[1],Schedule[2],StatID[3],Metrics[4],QueueLength[5],TTL[6],MinItems[7],CorrelationType[8],Tolerance[9],Stored[10],ThresholdIDs[11] +cgrates.org,TREND1,0 12 * * *,Stats2,*acc;*tcc,-1,-1,1,*average,2.1,true,TD1;TD2 ` ThresholdsCSVContent = ` #Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 964288c11..5fab48f05 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -93,6 +93,9 @@ func init() { if err := csvr.LoadRankings(); err != nil { log.Print("error in LoadRankings:", err) } + if err := csvr.LoadTrends(); err != nil { + log.Print("error in LoadTrends:", err) + } if err := csvr.LoadThresholds(); err != nil { log.Print("error in LoadThresholds:", err) } @@ -1102,6 +1105,34 @@ func TestLoadRankingProfiles(t *testing.T) { } } +func TestTrendProfiles(t *testing.T) { + eTrends := map[utils.TenantID]*utils.TPTrendsProfile{ + {Tenant: "cgrates.org", ID: "TREND1"}: { + TPid: testTPID, + Tenant: "cgrates.org", + ID: "TREND1", + Schedule: "0 12 * * *", + StatID: "Stats2", + Metrics: []string{"*acc", "*tcc"}, + QueueLength: -1, + TTL: "-1", + MinItems: 1, + CorrelationType: "*average", + Tolerance: 2.1, + Stored: true, + ThresholdIDs: []string{"TD1", "TD2"}, + }, + } + rgkey := utils.TenantID{Tenant: "cgrates.org", ID: "TREND1"} + if len(eTrends) != len(csvr.trProfiles) { + t.Errorf("Failed to load TrendProfiles: %+v", csvr.trProfiles) + } else if diff := cmp.Diff(eTrends[rgkey], csvr.trProfiles[rgkey], cmpopts.SortSlices(func(a, b string) bool { + return a < b + })); diff != "" { + t.Errorf("Wrong TrendProfiles (-expected +got):\n%s", diff) + } +} + func TestLoadThresholdProfiles(t *testing.T) { eThresholds := map[utils.TenantID]*utils.TPThresholdProfile{ {Tenant: "cgrates.org", ID: "Threshold1"}: { diff --git a/engine/model_helpers.go b/engine/model_helpers.go index c276c1706..cac8baca3 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -1644,27 +1644,29 @@ type TrendsMdls []*TrendsMdl func (tps TrendsMdls) CSVHeader() (result []string) { return []string{"#" + utils.Tenant, utils.ID, utils.Schedule, utils.StatID, - utils.Metrics, utils.QueueLength, utils.TTL, utils.TrendType, utils.ThresholdIDs} + utils.Metrics, utils.QueueLength, utils.TTL, utils.MinItems, utils.CorrelationType, utils.Tolerance, utils.Stored, utils.ThresholdIDs} } func (models TrendsMdls) AsTPTrends() (result []*utils.TPTrendsProfile) { thresholdsMap := make(map[string]utils.StringSet) - trendMetricsMap := make(map[string]map[string]*utils.MetricWithSettings) + trendMetricsMap := make(map[string]utils.StringSet) mtr := make(map[string]*utils.TPTrendsProfile) for _, model := range models { key := &utils.TenantID{Tenant: model.Tenant, ID: model.ID} tr, found := mtr[key.TenantID()] if !found { tr = &utils.TPTrendsProfile{ - Tenant: model.Tenant, - TPid: model.Tpid, - ID: model.ID, - Schedule: model.Schedule, - StatID: model.StatID, - TTL: model.TTL, - Trend: model.Trend, - TrendType: model.TrendType, - QueueLength: model.QueueLength, + Tenant: model.Tenant, + TPid: model.Tpid, + ID: model.ID, + Schedule: model.Schedule, + StatID: model.StatID, + TTL: model.TTL, + QueueLength: model.QueueLength, + MinItems: model.MinItems, + Tolerance: model.Tolerance, + Stored: model.Stored, + CorrelationType: model.CorrelationType, } } if model.Schedule != utils.EmptyString { @@ -1676,15 +1678,21 @@ func (models TrendsMdls) AsTPTrends() (result []*utils.TPTrendsProfile) { if model.TTL != utils.EmptyString { tr.TTL = model.TTL } - if model.Trend != utils.EmptyString { - tr.Trend = model.Trend - } - if model.TrendType != utils.EmptyString { - tr.TrendType = model.TrendType - } if model.QueueLength != 0 { tr.QueueLength = model.QueueLength } + if model.MinItems != 0 { + tr.MinItems = model.MinItems + } + if model.CorrelationType != utils.EmptyString { + tr.CorrelationType = model.CorrelationType + } + if model.Tolerance != 0 { + tr.Tolerance = model.Tolerance + } + if model.Stored { + tr.Stored = true + } if model.ThresholdIDs != utils.EmptyString { if _, has := thresholdsMap[key.TenantID()]; !has { thresholdsMap[key.TenantID()] = make(utils.StringSet) @@ -1693,21 +1701,9 @@ func (models TrendsMdls) AsTPTrends() (result []*utils.TPTrendsProfile) { } if model.Metrics != utils.EmptyString { if _, has := trendMetricsMap[key.TenantID()]; !has { - trendMetricsMap[key.TenantID()] = make(map[string]*utils.MetricWithSettings) - } - metricsSplit := strings.Split(model.Metrics, utils.InfieldSep) - for _, metricID := range metricsSplit { - trMetric, found := trendMetricsMap[key.TenantID()][metricID] - if !found { - trMetric = &utils.MetricWithSettings{ - MetricID: metricID, - } - } - if model.TrendSwingMargin != 0 { - trMetric.TrendSwingMargin = model.TrendSwingMargin - } - trendMetricsMap[key.TenantID()][metricID] = trMetric + trendMetricsMap[key.TenantID()] = make(utils.StringSet) } + trendMetricsMap[key.TenantID()].AddSlice(strings.Split(model.Metrics, utils.InfieldSep)) } mtr[key.TenantID()] = tr } @@ -1716,93 +1712,87 @@ func (models TrendsMdls) AsTPTrends() (result []*utils.TPTrendsProfile) { for tntId, sr := range mtr { result[i] = sr result[i].ThresholdIDs = thresholdsMap[tntId].AsSlice() - for _, metric := range trendMetricsMap[tntId] { - result[i].Metrics = append(result[i].Metrics, *metric) - } + result[i].Metrics = trendMetricsMap[tntId].AsSlice() i++ } return } func APItoModelTrends(tr *utils.TPTrendsProfile) (mdls TrendsMdls) { - if tr != nil && len(tr.Metrics) != 0 { - for i, metric := range tr.Metrics { - mdl := &TrendsMdl{ - Tpid: tr.TPid, - Tenant: tr.Tenant, - ID: tr.ID, - } - if i == 0 { - for i, threshold := range tr.ThresholdIDs { - if i != 0 { - mdl.ThresholdIDs += utils.InfieldSep - } - mdl.ThresholdIDs += threshold - } - mdl.Schedule = tr.Schedule - mdl.QueueLength = tr.QueueLength - mdl.StatID = tr.StatID - mdl.Trend = tr.Trend - mdl.TrendType = tr.TrendType - mdl.TTL = tr.TTL - } - mdl.TrendSwingMargin = metric.TrendSwingMargin - mdl.Metrics = metric.MetricID - mdls = append(mdls, mdl) + if tr != nil { + mdl := &TrendsMdl{ + Tpid: tr.TPid, + Tenant: tr.Tenant, + ID: tr.ID, } + mdl.Schedule = tr.Schedule + mdl.QueueLength = tr.QueueLength + mdl.StatID = tr.StatID + mdl.TTL = tr.TTL + mdl.MinItems = tr.MinItems + mdl.CorrelationType = tr.CorrelationType + mdl.Tolerance = tr.Tolerance + mdl.Stored = tr.Stored + for i, val := range tr.ThresholdIDs { + if i != 0 { + mdl.ThresholdIDs += utils.InfieldSep + } + mdl.ThresholdIDs += val + } + for i, val := range tr.Metrics { + if i != 0 { + mdl.Metrics += utils.InfieldSep + } + mdl.Metrics += val + } + mdls = append(mdls, mdl) } return } -func APItoTrends(tr *utils.TPTrendsProfile) (sr *TrendProfile, err error) { - sr = &TrendProfile{ - Tenant: tr.Tenant, - ID: tr.ID, - StatID: tr.StatID, - Schedule: tr.Schedule, - QueueLength: tr.QueueLength, - //Metrics: make([]*MetricWithSettings, len(tr.Metrics)), - //TrendType: tr.TrendType, - ThresholdIDs: make([]string, len(tr.ThresholdIDs)), +func APItoTrends(tpTR *utils.TPTrendsProfile) (tr *TrendProfile, err error) { + tr = &TrendProfile{ + Tenant: tpTR.Tenant, + ID: tpTR.ID, + StatID: tpTR.StatID, + Schedule: tpTR.Schedule, + QueueLength: tpTR.QueueLength, + ThresholdIDs: make([]string, len(tpTR.ThresholdIDs)), + Metrics: make([]string, len(tpTR.Metrics)), + MinItems: tpTR.MinItems, + CorrelationType: tpTR.CorrelationType, + Tolerance: tpTR.Tolerance, } - if tr.TTL != utils.EmptyString { - if sr.TTL, err = utils.ParseDurationWithNanosecs(tr.TTL); err != nil { + if tpTR.TTL != utils.EmptyString { + if tr.TTL, err = utils.ParseDurationWithNanosecs(tpTR.TTL); err != nil { return } } - copy(sr.ThresholdIDs, tr.ThresholdIDs) - /*for i, metric := range sr.Metrics { - tr.Metrics[i] = utils.MetricWithSettings{ - MetricID: metric.MetricID, - TrendSwingMargin: metric.TrendSwingMargin, - } - } - */ + copy(tr.ThresholdIDs, tpTR.ThresholdIDs) + copy(tr.Metrics, tpTR.Metrics) + return } -func TrendProfileToAPI(tr *TrendProfile) (tpSR *utils.TPTrendsProfile) { - tpSR = &utils.TPTrendsProfile{ - Tenant: tr.Tenant, - ID: tr.ID, - Schedule: tr.Schedule, - StatID: tr.StatID, - ThresholdIDs: make([]string, len(tr.ThresholdIDs)), - Metrics: make([]utils.MetricWithSettings, len(tr.Metrics)), - QueueLength: tr.QueueLength, - // TrendType: tr.TrendType, +func TrendProfileToAPI(tr *TrendProfile) (tpTR *utils.TPTrendsProfile) { + tpTR = &utils.TPTrendsProfile{ + Tenant: tr.Tenant, + ID: tr.ID, + Schedule: tr.Schedule, + StatID: tr.StatID, + ThresholdIDs: make([]string, len(tr.ThresholdIDs)), + Metrics: make([]string, len(tr.Metrics)), + QueueLength: tr.QueueLength, + MinItems: tr.MinItems, + CorrelationType: tr.CorrelationType, + Tolerance: tr.Tolerance, + Stored: tr.Stored, } if tr.TTL != time.Duration(0) { - tpSR.TTL = tr.TTL.String() + tpTR.TTL = tr.TTL.String() } - copy(tpSR.ThresholdIDs, tr.ThresholdIDs) - /*for i, metric := range tr.Metrics { - tpSR.Metrics[i] = utils.MetricWithSettings{ - MetricID: metric.MetricID, - TrendSwingMargin: metric.TrendSwingMargin, - } - } - */ + copy(tpTR.ThresholdIDs, tr.ThresholdIDs) + copy(tpTR.Metrics, tr.Metrics) return } diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index af6ece71d..4231c9866 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -5977,7 +5977,10 @@ func TestTrendsMdlCSVHeader(t *testing.T) { utils.Metrics, utils.QueueLength, utils.TTL, - utils.TrendType, + utils.MinItems, + utils.CorrelationType, + utils.Tolerance, + utils.Stored, utils.ThresholdIDs, } var tps TrendsMdls diff --git a/engine/models.go b/engine/models.go index 3e4884816..0ab714998 100644 --- a/engine/models.go +++ b/engine/models.go @@ -302,20 +302,21 @@ func (RankingsMdl) TableName() string { } type TrendsMdl struct { - PK uint `gorm:"primary_key"` - Tpid string - Tenant string `index:"0" re:".*"` - ID string `index:"1" re:".*"` - Schedule string `index:"2" re:".*"` - StatID string `index:"3" re:".*"` - Metrics string `index:"4" re:".*"` - TrendSwingMargin float64 `index:"5" re:".*"` - QueueLength int `index:"6" re:".*"` - TTL string `index:"7" re:".*"` - Trend string `index:"8" re:".*"` - TrendType string `index:"9" re:".*"` - ThresholdIDs string `index:"10" re:".*"` - CreatedAt time.Time + PK uint `gorm:"primary_key"` + Tpid string + Tenant string `index:"0" re:".*"` + ID string `index:"1" re:".*"` + Schedule string `index:"2" re:".*"` + StatID string `index:"3" re:".*"` + Metrics string `index:"4" re:".*"` + QueueLength int `index:"5" re:".*"` + TTL string `index:"6" re:".*"` + MinItems int `index:"7" re:".*"` + CorrelationType string `index:"8" re:".*"` + Tolerance float64 `index:"9" re:".*"` + Stored bool `index:"10" re:".*"` + ThresholdIDs string `index:"11" re:".*"` + CreatedAt time.Time } func (TrendsMdl) TableName() string { diff --git a/engine/storage_sql.go b/engine/storage_sql.go index 0a8d9430c..77ceb0daa 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -598,17 +598,17 @@ func (sqls *SQLStorage) SetTPRankings(rgs []*utils.TPRankingProfile) error { return nil } -func (sqls *SQLStorage) SetTPTrends(srs []*utils.TPTrendsProfile) error { - if len(srs) == 0 { +func (sqls *SQLStorage) SetTPTrends(trs []*utils.TPTrendsProfile) error { + if len(trs) == 0 { return nil } tx := sqls.db.Begin() - for _, sg := range srs { - if err := tx.Where(&TrendsMdl{Tpid: sg.TPid, ID: sg.ID}).Delete(TrendsMdl{}).Error; err != nil { + for _, t := range trs { + if err := tx.Where(&TrendsMdl{Tpid: t.TPid, ID: t.ID}).Delete(TrendsMdl{}).Error; err != nil { tx.Rollback() return err } - for _, msg := range APItoModelTrends(sg) { + for _, msg := range APItoModelTrends(t) { if err := tx.Create(&msg).Error; err != nil { tx.Rollback() return err diff --git a/engine/tpreader.go b/engine/tpreader.go index c9b3d1ce1..70f77cd26 100644 --- a/engine/tpreader.go +++ b/engine/tpreader.go @@ -1142,11 +1142,11 @@ func (tpr *TpReader) LoadTrendsFiltered(tag string) error { if err != nil { return err } - mapSrs := make(map[utils.TenantID]*utils.TPTrendsProfile) - for _, sr := range tps { - mapSrs[utils.TenantID{Tenant: sr.Tenant, ID: sr.ID}] = sr + mapTrs := make(map[utils.TenantID]*utils.TPTrendsProfile) + for _, tr := range tps { + mapTrs[utils.TenantID{Tenant: tr.Tenant, ID: tr.ID}] = tr } - tpr.trProfiles = mapSrs + tpr.trProfiles = mapTrs return nil } diff --git a/engine/z_loader_it_test.go b/engine/z_loader_it_test.go index d049b094d..c635e3e8c 100644 --- a/engine/z_loader_it_test.go +++ b/engine/z_loader_it_test.go @@ -195,6 +195,9 @@ func testLoaderITRemoveLoad(t *testing.T) { if err = loader.LoadThresholds(); err != nil { t.Error("Failed loading thresholds: ", err.Error()) } + if err = loader.LoadTrends(); err != nil { + t.Error("Failed loading trends: ", err.Error()) + } if err = loader.LoadRouteProfiles(); err != nil { t.Error("Failed loading Route profiles: ", err.Error()) } @@ -274,6 +277,9 @@ func testLoaderITLoadFromCSV(t *testing.T) { if err = loader.LoadStats(); err != nil { t.Error("Failed loading stats: ", err.Error()) } + if err = loader.LoadTrends(); err != nil { + t.Error("Failed loading trends: ", err.Error()) + } if err = loader.LoadThresholds(); err != nil { t.Error("Failed loading thresholds: ", err.Error()) } @@ -438,6 +444,21 @@ func testLoaderITWriteToDatabase(t *testing.T) { t.Errorf("Expecting: %v, received: %v", sgs, rcv) } } + + for tenatid, tr := range loader.trProfiles { + rcv, err := loader.dm.GetTrendProfile(tenatid.Tenant, tenatid.ID, false, false, utils.NonTransactional) + if err != nil { + t.Errorf("Failed GetTrendProfile, tenant: %s, id: %s, error: %s ", tr.Tenant, tr.ID, err.Error()) + } + trs, err := APItoTrends(tr) + if err != nil { + t.Error(err) + } + if !reflect.DeepEqual(trs, rcv) { + t.Errorf("Expecting: %v, received: %v", utils.ToJSON(trs), utils.ToJSON(rcv)) + } + } + for tenatid, th := range loader.thProfiles { rcv, err := loader.dm.GetThresholdProfile(tenatid.Tenant, tenatid.ID, false, false, utils.NonTransactional) if err != nil { @@ -574,6 +595,9 @@ func testLoaderITLoadFromStorDb(t *testing.T) { if err := loader.LoadAccountActions(); err != nil && err.Error() != utils.NotFoundCaps { t.Error("Failed loading account actions: ", err.Error()) } + if err := loader.LoadTrends(); err != nil && err.Error() != utils.NotFoundCaps { + t.Error("Failed loading trends: ", err.Error()) + } } func testLoaderITLoadIndividualProfiles(t *testing.T) { @@ -617,6 +641,17 @@ func testLoaderITLoadIndividualProfiles(t *testing.T) { } } } + + // Load trend profiles + if trp, err := storDb.GetTPTrends(utils.TestSQL, "cgrates.org", ""); err != nil { + t.Fatal("Could not retrieve trends") + } else { + for _, r := range trp { + if _, err := loader.lr.GetTPTrends(utils.TestSQL, "cgrates.org", r.ID); err != nil { + t.Fatalf("Could not load trendProfile for id: %s, error: %s", r.ID, err.Error()) + } + } + } } /* diff --git a/utils/apitpdata.go b/utils/apitpdata.go index bf87b97fc..cf2de09d5 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1060,17 +1060,19 @@ type MetricWithSettings struct { // TPTrendProfile is used in APIs to manage remotely offline TrendProfile type TPTrendsProfile struct { - TPid string - Tenant string - ID string - Schedule string - StatID string - Metrics []MetricWithSettings - QueueLength int - TTL string - Trend string - TrendType string - ThresholdIDs []string + TPid string + Tenant string + ID string + Schedule string + StatID string + Metrics []string + QueueLength int + TTL string + MinItems int + CorrelationType string + Tolerance float64 + Stored bool + ThresholdIDs []string } // TPThresholdProfile is used in APIs to manage remotely offline ThresholdProfile diff --git a/utils/consts.go b/utils/consts.go index d2a766b29..6252d519a 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -634,7 +634,8 @@ const ( RouteFilterIDs = "RouteFilterIDs" AttributeFilterIDs = "AttributeFilterIDs" QueueLength = "QueueLength" - TrendType = "TrendType" + CorrelationType = "CorrelationType" + Tolerance = "Tolerance" TTL = "TTL" MinItems = "MinItems" MetricIDs = "MetricIDs"