diff --git a/agents/diam_prom_it_test.go b/agents/diam_prom_it_test.go new file mode 100644 index 000000000..381d3cd83 --- /dev/null +++ b/agents/diam_prom_it_test.go @@ -0,0 +1,296 @@ +//go:build integration + +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package agents + +import ( + "bytes" + "fmt" + "io" + "net/http" + "testing" + "time" + + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +func TestDiamPrometheus(t *testing.T) { + t.Skip("test by looking at the log output") + switch *utils.DBType { + case utils.MetaInternal: + case utils.MetaMySQL, utils.MetaMongo, utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("unsupported dbtype value") + } + + ng := engine.TestEngine{ + ConfigJSON: `{ +"apiers": { + "enabled": true +}, +"sessions": { + "enabled": true, + "chargers_conns": ["*internal"], + "rals_conns": ["*internal"], + "cdrs_conns": ["*internal"] +}, +"chargers": { + "enabled": true, + "string_indexed_fields": ["*req.Account"] +}, +"cdrs": { + "enabled": true, + "rals_conns": ["*internal"], + "store_cdrs": false +}, +"rals": { + "enabled": true +}, +"prometheus_agent": { + "enabled": true, + "stats_conns": ["*localhost"], + "stat_queue_ids": ["SQ_1"] +}, +"stats": { + "enabled": true, + "store_interval": "-1" +}, +"thresholds": { + "enabled": true, + "store_interval": "-1" +}, +"rpc_conns": { + "async": { + "strategy": "*async", + "conns": [ + { + "address": "*internal" + } + ] + } +}, +"diameter_agent": { + "enabled": true, + "sessions_conns": ["*birpc_internal"], + "stats_conns": ["async"], + "thresholds_conns": ["async"], + "request_processors": [{ + "id": "message", + "filters": [ + "*string:~*vars.*cmd:CCR", + "*prefix:~*req.Service-Context-Id:message", + "*string:~*req.CC-Request-Type:4" + ], + "flags": [ + "*message", + "*accounts", + "*cdrs", + "*daStats:*ids:SQ_1", + "*daThresholds:*ids:TH_1", + ], + "request_fields": [{ + "tag": "ToR", + "path": "*cgreq.ToR", + "type": "*constant", + "value": "*sms" + }, + { + "tag": "OriginID", + "path": "*cgreq.OriginID", + "type": "*variable", + "value": "~*req.Session-Id", + "mandatory": true + }, + { + "tag": "Category", + "path": "*cgreq.Category", + "type": "*constant", + "value": "sms" + }, + { + "tag": "RequestType", + "path": "*cgreq.RequestType", + "type": "*constant", + "value": "*prepaid" + }, + { + "tag": "Account", + "path": "*cgreq.Account", + "type": "*variable", + "mandatory": true, + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(0)]" + }, + { + "tag": "Destination", + "path": "*cgreq.Destination", + "type": "*variable", + "mandatory": true, + "value": "~*req.Service-Information.SMS-Information.Recipient-Address.Address-Data" + }, + { + "tag": "SetupTime", + "path": "*cgreq.SetupTime", + "type": "*variable", + "value": "~*req.Event-Timestamp", + "mandatory": true + }, + { + "tag": "AnswerTime", + "path": "*cgreq.AnswerTime", + "type": "*variable", + "value": "~*req.Event-Timestamp", + "mandatory": true + }, + { + "tag": "Usage", + "path": "*cgreq.Usage", + "type": "*variable", + "value": "~*req.Requested-Service-Unit.CC-Time", + "mandatory": true + } + ], + "reply_fields": [{ + "tag": "CCATemplate", + "type": "*template", + "value": "*cca" + }, + { + "tag": "ResultCode", + "path": "*rep.Result-Code", + "filters": ["*notempty:~*cgrep.Error:"], + "type": "*constant", + "value": "5030", + "blocker": true + } + ] + }] +} +}`, + TpFiles: map[string]string{ + // import Chargers via CSV to avoid cyclic imports (agents->v1->agents) + utils.ChargersCsv: ` +#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight +cgrates.org,DEFAULT,*string:~*req.Account:1001,,*default,*none,10`, + }, + DBCfg: engine.InternalDBCfg, + LogBuffer: &bytes.Buffer{}, + GracefulShutdown: true, + } + t.Cleanup(func() { fmt.Println(ng.LogBuffer) }) + client, cfg := ng.Run(t) + + var reply string + if err := client.Call(context.Background(), utils.APIerSv2SetBalance, + utils.AttrSetBalance{ + Tenant: "cgrates.org", + Account: "1001", + Value: 100, + BalanceType: utils.MetaSMS, + Balance: map[string]any{ + utils.ID: "balance_sms", + }, + }, &reply); err != nil { + t.Fatal(err) + } + + if err := client.Call(context.Background(), utils.APIerSv2SetActions, + utils.AttrSetActions{ + ActionsId: "ACT_LOG_WARNING", + Actions: []*utils.TPAction{ + { + Identifier: utils.MetaLog, + }, + }, + }, &reply); err != nil { + t.Fatal(err) + } + + if err := client.Call(context.Background(), utils.APIerSv1SetStatQueueProfile, + engine.StatQueueProfileWithAPIOpts{ + StatQueueProfile: &engine.StatQueueProfile{ + Tenant: "cgrates.org", + ID: "SQ_1", + FilterIDs: []string{"*string:~*req.Category:sms"}, + QueueLength: -1, + TTL: 5 * time.Second, + Metrics: []*engine.MetricWithFilters{ + { + MetricID: "*average#~*req.ProcessingTime", + }, + { + MetricID: "*sum#~*req.ProcessingTime", + }, + }, + Stored: true, + MinItems: 1, + }, + }, &reply); err != nil { + t.Fatal(err) + } + + if err := client.Call(context.Background(), utils.APIerSv1SetThresholdProfile, + engine.ThresholdProfileWithAPIOpts{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_1", + FilterIDs: []string{"*string:~*req.Category:sms"}, + MaxHits: -1, + MinHits: 8, + MinSleep: time.Second, + ActionIDs: []string{"ACT_LOG_WARNING"}, + }, + }, &reply); err != nil { + t.Fatal(err) + } + + time.Sleep(500 * time.Millisecond) + diamClient, err := NewDiameterClient(cfg.DiameterAgentCfg().Listen, "localhost", + cfg.DiameterAgentCfg().OriginRealm, cfg.DiameterAgentCfg().VendorID, + cfg.DiameterAgentCfg().ProductName, utils.DiameterFirmwareRevision, + cfg.DiameterAgentCfg().DictionariesPath, cfg.DiameterAgentCfg().ListenNet) + if err != nil { + t.Fatal(err) + } + + for range 10 { + time.Sleep(time.Second) + sendDiamCCR(t, diamClient, 5*time.Second, "2001") + scrapePromURL(t) + } +} + +func scrapePromURL(t *testing.T) { + t.Helper() + url := "http://localhost:2080/prometheus" + resp, err := http.Get(url) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + bodyString := string(body) + fmt.Println(bodyString) +}