From ccdf3ef1f10db23b18a53eb103d42657f2422b0e Mon Sep 17 00:00:00 2001 From: gezimbll Date: Mon, 26 May 2025 08:49:42 +0200 Subject: [PATCH] added passing events from thresholds to ees --- cmd/cgr-engine/cgr-engine.go | 2 +- config/config_defaults.go | 2 + config/config_json_test.go | 2 + config/config_test.go | 8 +- config/libconfig_json.go | 2 + config/thresholdscfg.go | 36 ++++++ config/thresholdscfg_test.go | 5 + .../mysql/create_tariffplan_tables.sql | 1 + .../postgres/create_tariffplan_tables.sql | 1 + data/tariffplans/oldtutorial/Thresholds.csv | 16 +-- data/tariffplans/precache/Thresholds.csv | 16 +-- data/tariffplans/testit/Thresholds.csv | 4 +- data/tariffplans/testtp/Thresholds.csv | 4 +- data/tariffplans/tutorial/Thresholds.csv | 6 +- engine/loader_csv_test.go | 4 +- engine/model_helpers.go | 31 ++++- engine/model_helpers_test.go | 32 +++-- engine/models.go | 4 +- engine/thresholds.go | 117 ++++++++++++++++-- engine/thresholds_test.go | 101 +++++---------- services/thresholds.go | 6 +- services/thresholds_test.go | 4 +- utils/apitpdata.go | 1 + utils/consts.go | 4 + 24 files changed, 288 insertions(+), 121 deletions(-) diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 911d1a104..a2e300c62 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -581,7 +581,7 @@ func main() { dspH := services.NewRegistrarCService(cfg, server, connManager, anz, srvDep) chrS := services.NewChargerService(cfg, dmService, cacheS, filterSChan, server, internalChargerSChan, connManager, anz, srvDep) - tS := services.NewThresholdService(cfg, dmService, cacheS, filterSChan, server, internalThresholdSChan, anz, srvDep) + tS := services.NewThresholdService(cfg, dmService, cacheS, filterSChan, server, internalThresholdSChan, connManager, anz, srvDep) stS := services.NewStatService(cfg, dmService, cacheS, filterSChan, server, internalStatSChan, connManager, anz, srvDep) trS := services.NewTrendService(cfg, dmService, cacheS, filterSChan, server, diff --git a/config/config_defaults.go b/config/config_defaults.go index 52acc5f96..ef695e4fd 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -929,6 +929,8 @@ const CGRATES_CFG_JSON = ` "indexed_selects": true, // enable profile matching exclusively on indexes "sessions_conns":[], // connections to SessionS <*internal|$rpc_conns_id> "apiers_conns":[], // connections to ApierS <*internal|$rpc_conns_id> + "ees_conns": [], // connections to EEs <*internal|$rpc_conns_id> + "ees_exporter_ids": [], // list of EventExporter profiles to be used for ThresholdHit events //"string_indexed_fields": [], // query indexes based on these fields for faster processing "prefix_indexed_fields": [], // query indexes based on these fields for faster processing "suffix_indexed_fields": [], // query indexes based on these fields for faster processing diff --git a/config/config_json_test.go b/config/config_json_test.go index d7b3d4f17..bd77c70e6 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -1273,6 +1273,8 @@ func TestDfThresholdSJsonCfg(t *testing.T) { Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, ExistsIndexedFields: &[]string{}, + Ees_conns: &[]string{}, + Ees_exporter_ids: &[]string{}, Nested_fields: utils.BoolPointer(false), Opts: &ThresholdsOptsJson{ ProfileIDs: &[]string{}, diff --git a/config/config_test.go b/config/config_test.go index f95f7f898..9776bee9f 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -774,6 +774,7 @@ func TestCgrCfgJSONDefaultThresholdSCfg(t *testing.T) { PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, ExistsIndexedFields: &[]string{}, + EEsConns: []string{}, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, }, @@ -1923,6 +1924,7 @@ func TestThresholdSConfig(t *testing.T) { SuffixIndexedFields: &[]string{}, ExistsIndexedFields: &[]string{}, NestedFields: false, + EEsConns: []string{}, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, }, @@ -4071,6 +4073,8 @@ func TestV1GetConfigThresholds(t *testing.T) { utils.SuffixIndexedFieldsCfg: []string{}, utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, + utils.EEsConnsCfg: []string{}, + utils.EEsExporterIDsCfg: []string{}, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, utils.MetaProfileIgnoreFiltersCfg: false, @@ -5005,7 +5009,7 @@ func TestV1GetConfigAsJSONStatS(t *testing.T) { func TestV1GetConfigAsJSONThresholdS(t *testing.T) { var reply string - expected := `{"thresholds":{"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]}}` + expected := `{"thresholds":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: THRESHOLDS_JSON}, &reply); err != nil { t.Error(err) @@ -5297,7 +5301,7 @@ func TestV1GetConfigAsJSONAllConfig(t *testing.T) { }` var reply string cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSON) - expected := `{"analyzers":{"cleanup_interval":"1h0m0s","db_path":"/var/spool/cgrates/analyzers","enabled":false,"index_type":"*scorch","ttl":"24h0m0s"},"apiban":{"keys":[]},"apiers":{"attributes_conns":[],"caches_conns":["*internal"],"ees_conns":[],"enabled":false,"scheduler_conns":[]},"asterisk_agent":{"asterisk_conns":[{"address":"127.0.0.1:8088","alias":"","connect_attempts":3,"max_reconnect_interval":"0s","password":"CGRateS.org","reconnects":5,"user":"cgrates"}],"create_cdr":false,"enabled":false,"sessions_conns":["*birpc_internal"]},"attributes":{"any_context":true,"apiers_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*processRuns":1,"*profileIDs":[],"*profileIgnoreFilters":false,"*profileRuns":0},"prefix_indexed_fields":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"caches":{"partitions":{"*account_action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*apiban":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2m0s"},"*attribute_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*caps_events":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*cdr_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10m0s"},"*charger_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*closed_sessions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*diameter_messages":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*dispatcher_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_loads":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_routes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatchers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*event_charges":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*event_resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*radius_packets":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*ranking_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rankings":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*replication_hosts":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_connections":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_responses":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2s"},"*sentrypeer":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":true,"ttl":"24h0m0s"},"*shared_groups":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stir":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*threshold_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*trend_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*trends":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*uch":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"}},"remote_conns":[],"replication_conns":[]},"cdrs":{"attributes_conns":[],"chargers_conns":[],"compress_stored_cost":false,"ees_conns":[],"enabled":false,"extra_fields":[],"online_cdr_exports":[],"rals_conns":[],"scheduler_conns":[],"session_cost_retries":5,"stats_conns":[],"store_cdrs":true,"thresholds_conns":[]},"chargers":{"attributes_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"suffix_indexed_fields":[]},"configs":{"enabled":false,"root_dir":"/var/spool/cgrates/configs","url":"/configs/"},"cores":{"caps":0,"caps_stats_interval":"0","caps_strategy":"*busy","shutdown_timeout":"1s"},"data_db":{"db_host":"127.0.0.1","db_name":"10","db_password":"","db_port":6379,"db_type":"*redis","db_user":"cgrates","items":{"*account_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*accounts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*ranking_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rankings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*sessions_backup":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*trend_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*trends":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"internalDBBackupPath":"/var/lib/cgrates/internal_db/backup/datadb","internalDBDumpInterval":"0s","internalDBDumpPath":"/var/lib/cgrates/internal_db/datadb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":"0s","internalDBStartTimeout":"5m0s","mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisPoolPipelineLimit":0,"redisPoolPipelineWindow":"150µs","redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"remote_conn_id":"","remote_conns":[],"replication_cache":"","replication_conns":[],"replication_failed_dir":"","replication_filtered":false,"replication_interval":"0s"},"diameter_agent":{"asr_template":"","dictionaries_path":"/usr/share/cgrates/diameter/dict/","enabled":false,"forced_disconnect":"*none","listen":"127.0.0.1:3868","listen_net":"tcp","origin_host":"CGR-DA","origin_realm":"cgrates.org","product_name":"CGRateS","rar_template":"","request_processors":[],"sessions_conns":["*birpc_internal"],"synced_conn_requests":false,"vendor_id":0},"dispatchers":{"any_subsystem":true,"attributes_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"prevent_loop":false,"suffix_indexed_fields":[]},"dns_agent":{"enabled":false,"listeners":[{"address":"127.0.0.1:53","network":"udp"}],"request_processors":[],"sessions_conns":["*internal"],"timezone":""},"ees":{"attributes_conns":[],"cache":{"*amqp_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*amqpv1_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*els":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*file_csv":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"5s"},"*kafka_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*nats_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*s3_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*sql":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*sqs_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false}},"enabled":false,"exporters":[{"attempts":1,"attribute_context":"","attribute_ids":[],"concurrent_requests":0,"export_path":"/var/spool/cgrates/ees","failed_posts_dir":"/var/spool/cgrates/failed_posts","fields":[],"filters":[],"flags":[],"id":"*default","metrics_reset_schedule":"","opts":{},"synchronous":false,"timezone":"","type":"*none"}]},"ers":{"concurrent_events":1,"ees_conns":[],"enabled":false,"partial_cache_ttl":"1s","readers":[{"cache_dump_fields":[],"concurrent_requests":1024,"fields":[{"mandatory":true,"path":"*cgreq.ToR","tag":"ToR","type":"*variable","value":"~*req.2"},{"mandatory":true,"path":"*cgreq.OriginID","tag":"OriginID","type":"*variable","value":"~*req.3"},{"mandatory":true,"path":"*cgreq.RequestType","tag":"RequestType","type":"*variable","value":"~*req.4"},{"mandatory":true,"path":"*cgreq.Tenant","tag":"Tenant","type":"*variable","value":"~*req.6"},{"mandatory":true,"path":"*cgreq.Category","tag":"Category","type":"*variable","value":"~*req.7"},{"mandatory":true,"path":"*cgreq.Account","tag":"Account","type":"*variable","value":"~*req.8"},{"mandatory":true,"path":"*cgreq.Subject","tag":"Subject","type":"*variable","value":"~*req.9"},{"mandatory":true,"path":"*cgreq.Destination","tag":"Destination","type":"*variable","value":"~*req.10"},{"mandatory":true,"path":"*cgreq.SetupTime","tag":"SetupTime","type":"*variable","value":"~*req.11"},{"mandatory":true,"path":"*cgreq.AnswerTime","tag":"AnswerTime","type":"*variable","value":"~*req.12"},{"mandatory":true,"path":"*cgreq.Usage","tag":"Usage","type":"*variable","value":"~*req.13"}],"filters":[],"flags":[],"id":"*default","max_reconnect_interval":"5m0s","opts":{"csvFieldSeparator":",","csvHeaderDefineChar":":","csvRowLength":0,"natsSubject":"cgrates_cdrs","partialCacheAction":"*none","partialOrderField":"~*req.AnswerTime"},"partial_commit_fields":[],"processed_path":"/var/spool/cgrates/ers/out","reconnects":-1,"run_delay":"0","source_path":"/var/spool/cgrates/ers/in","start_delay":"0","tenant":"","timezone":"","type":"*none"}],"sessions_conns":["*internal"]},"filters":{"apiers_conns":[],"rankings_conns":[],"resources_conns":[],"stats_conns":[],"trends_conns":[]},"freeswitch_agent":{"active_session_delimiter":",","create_cdr":false,"empty_balance_ann_file":"","empty_balance_context":"","enabled":false,"event_socket_conns":[{"address":"127.0.0.1:8021","alias":"127.0.0.1:8021","max_reconnect_interval":"0s","password":"ClueCon","reconnects":5,"reply_timeout":"1m0s"}],"extra_fields":"","low_balance_ann_file":"","max_wait_connection":"2s","sessions_conns":["*birpc_internal"],"subscribe_park":true},"general":{"caching_delay":"0","connect_attempts":5,"connect_timeout":"1s","dbdata_encoding":"*msgpack","default_caching":"*reload","default_category":"call","default_request_type":"*rated","default_tenant":"cgrates.org","default_timezone":"Local","digest_equal":":","digest_separator":",","failed_posts_dir":"/var/spool/cgrates/failed_posts","failed_posts_ttl":"5s","locking_timeout":"0","log_level":6,"logger":"*syslog","max_parallel_conns":100,"max_reconnect_interval":"0","node_id":"ENGINE1","poster_attempts":3,"reconnects":-1,"reply_timeout":"2s","rounding_decimals":5,"rsr_separator":";","tpexport_dir":"/var/spool/cgrates/tpe"},"http":{"auth_users":{},"client_opts":{"dialFallbackDelay":"300ms","dialKeepAlive":"30s","dialTimeout":"30s","disableCompression":false,"disableKeepAlives":false,"expectContinueTimeout":"0s","forceAttemptHttp2":true,"idleConnTimeout":"1m30s","maxConnsPerHost":0,"maxIdleConns":100,"maxIdleConnsPerHost":2,"responseHeaderTimeout":"0s","skipTlsVerify":false,"tlsHandshakeTimeout":"10s"},"freeswitch_cdrs_url":"/freeswitch_json","http_cdrs":"/cdr_http","json_rpc_url":"/jsonrpc","pprof_path":"/debug/pprof/","registrars_url":"/registrar","use_basic_auth":false,"ws_url":"/ws"},"http_agent":[],"kamailio_agent":{"create_cdr":false,"enabled":false,"evapi_conns":[{"address":"127.0.0.1:8448","alias":"","max_reconnect_interval":"0s","reconnects":5}],"sessions_conns":["*birpc_internal"],"timezone":""},"listen":{"http":"127.0.0.1:2080","http_tls":"127.0.0.1:2280","rpc_gob":"127.0.0.1:2013","rpc_gob_tls":"127.0.0.1:2023","rpc_json":"127.0.0.1:2012","rpc_json_tls":"127.0.0.1:2022"},"loader":{"caches_conns":["*localhost"],"data_path":"./","disable_reverse":false,"field_separator":",","gapi_credentials":".gapi/credentials.json","gapi_token":".gapi/token.json","scheduler_conns":["*localhost"],"tpid":""},"loaders":[{"caches_conns":["*internal"],"data":[{"fields":[{"mandatory":true,"path":"Tenant","tag":"TenantID","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ProfileID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"AttributeFilterIDs","tag":"AttributeFilterIDs","type":"*variable","value":"~*req.5"},{"path":"Path","tag":"Path","type":"*variable","value":"~*req.6"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.7"},{"path":"Value","tag":"Value","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.10"}],"file_name":"Attributes.csv","flags":null,"type":"*attributes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.2"},{"path":"Element","tag":"Element","type":"*variable","value":"~*req.3"},{"path":"Values","tag":"Values","type":"*variable","value":"~*req.4"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.5"}],"file_name":"Filters.csv","flags":null,"type":"*filters"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"UsageTTL","tag":"TTL","type":"*variable","value":"~*req.4"},{"path":"Limit","tag":"Limit","type":"*variable","value":"~*req.5"},{"path":"AllocationMessage","tag":"AllocationMessage","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.8"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.9"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.10"}],"file_name":"Resources.csv","flags":null,"type":"*resources"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"QueueLength","tag":"QueueLength","type":"*variable","value":"~*req.4"},{"path":"TTL","tag":"TTL","type":"*variable","value":"~*req.5"},{"path":"MinItems","tag":"MinItems","type":"*variable","value":"~*req.6"},{"path":"MetricIDs","tag":"MetricIDs","type":"*variable","value":"~*req.7"},{"path":"MetricFilterIDs","tag":"MetricFilterIDs","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.10"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.11"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.12"}],"file_name":"Stats.csv","flags":null,"type":"*stats"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"MaxHits","tag":"MaxHits","type":"*variable","value":"~*req.4"},{"path":"MinHits","tag":"MinHits","type":"*variable","value":"~*req.5"},{"path":"MinSleep","tag":"MinSleep","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.8"},{"path":"ActionIDs","tag":"ActionIDs","type":"*variable","value":"~*req.9"},{"path":"Async","tag":"Async","type":"*variable","value":"~*req.10"}],"file_name":"Thresholds.csv","flags":null,"type":"*thresholds"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"Sorting","tag":"Sorting","type":"*variable","value":"~*req.4"},{"path":"SortingParameters","tag":"SortingParameters","type":"*variable","value":"~*req.5"},{"path":"RouteID","tag":"RouteID","type":"*variable","value":"~*req.6"},{"path":"RouteFilterIDs","tag":"RouteFilterIDs","type":"*variable","value":"~*req.7"},{"path":"RouteAccountIDs","tag":"RouteAccountIDs","type":"*variable","value":"~*req.8"},{"path":"RouteRatingPlanIDs","tag":"RouteRatingPlanIDs","type":"*variable","value":"~*req.9"},{"path":"RouteResourceIDs","tag":"RouteResourceIDs","type":"*variable","value":"~*req.10"},{"path":"RouteStatIDs","tag":"RouteStatIDs","type":"*variable","value":"~*req.11"},{"path":"RouteWeight","tag":"RouteWeight","type":"*variable","value":"~*req.12"},{"path":"RouteBlocker","tag":"RouteBlocker","type":"*variable","value":"~*req.13"},{"path":"RouteParameters","tag":"RouteParameters","type":"*variable","value":"~*req.14"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.15"}],"file_name":"Routes.csv","flags":null,"type":"*routes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"RunID","tag":"RunID","type":"*variable","value":"~*req.4"},{"path":"AttributeIDs","tag":"AttributeIDs","type":"*variable","value":"~*req.5"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.6"}],"file_name":"Chargers.csv","flags":null,"type":"*chargers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"Strategy","tag":"Strategy","type":"*variable","value":"~*req.5"},{"path":"StrategyParameters","tag":"StrategyParameters","type":"*variable","value":"~*req.6"},{"path":"ConnID","tag":"ConnID","type":"*variable","value":"~*req.7"},{"path":"ConnFilterIDs","tag":"ConnFilterIDs","type":"*variable","value":"~*req.8"},{"path":"ConnWeight","tag":"ConnWeight","type":"*variable","value":"~*req.9"},{"path":"ConnBlocker","tag":"ConnBlocker","type":"*variable","value":"~*req.10"},{"path":"ConnParameters","tag":"ConnParameters","type":"*variable","value":"~*req.11"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherProfiles.csv","flags":null,"type":"*dispatchers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Address","tag":"Address","type":"*variable","value":"~*req.2"},{"path":"Transport","tag":"Transport","type":"*variable","value":"~*req.3"},{"path":"ConnectAttempts","tag":"ConnectAttempts","type":"*variable","value":"~*req.4"},{"path":"Reconnects","tag":"Reconnects","type":"*variable","value":"~*req.5"},{"path":"MaxReconnectInterval","tag":"MaxReconnectInterval","type":"*variable","value":"~*req.6"},{"path":"ConnectTimeout","tag":"ConnectTimeout","type":"*variable","value":"~*req.7"},{"path":"ReplyTimeout","tag":"ReplyTimeout","type":"*variable","value":"~*req.8"},{"path":"TLS","tag":"TLS","type":"*variable","value":"~*req.9"},{"path":"ClientKey","tag":"ClientKey","type":"*variable","value":"~*req.10"},{"path":"ClientCertificate","tag":"ClientCertificate","type":"*variable","value":"~*req.11"},{"path":"CaCertificate","tag":"CaCertificate","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherHosts.csv","flags":null,"type":"*dispatcher_hosts"}],"dry_run":false,"enabled":false,"field_separator":",","id":"*default","lockfile_path":".cgr.lck","run_delay":"0","tenant":"","tp_in_dir":"/var/spool/cgrates/loader/in","tp_out_dir":"/var/spool/cgrates/loader/out"}],"mailer":{"auth_password":"CGRateS.org","auth_user":"cgrates","from_address":"cgr-mailer@localhost.localdomain","server":"localhost"},"migrator":{"out_datadb_encoding":"msgpack","out_datadb_host":"127.0.0.1","out_datadb_name":"10","out_datadb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisPoolPipelineLimit":0,"redisPoolPipelineWindow":"150µs","redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"out_datadb_password":"","out_datadb_port":"6379","out_datadb_type":"*redis","out_datadb_user":"cgrates","out_stordb_host":"127.0.0.1","out_stordb_name":"cgrates","out_stordb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","mysqlDSNParams":null,"mysqlLocation":"","pgSSLMode":"","sqlConnMaxLifetime":"0s","sqlMaxIdleConns":0,"sqlMaxOpenConns":0},"out_stordb_password":"","out_stordb_port":"3306","out_stordb_type":"*mysql","out_stordb_user":"cgrates","users_filters":null},"prometheus_agent":{"collect_go_metrics":false,"collect_process_metrics":false,"cores_conns":null,"enabled":false,"path":"/prometheus","stat_queue_ids":null,"stats_conns":null},"radius_agent":{"client_dictionaries":{"*default":["/usr/share/cgrates/radius/dict/"]},"client_secrets":{"*default":"CGRateS.org"},"coa_template":"*coa","dmr_template":"*dmr","enabled":false,"listeners":[{"acct_address":"127.0.0.1:1813","auth_address":"127.0.0.1:1812","network":"udp"}],"request_processors":[],"requests_cache_key":"","sessions_conns":["*internal"]},"rals":{"balance_rating_subject":{"*any":"*zero1ns","*voice":"*zero1s"},"enabled":false,"fallback_depth":3,"max_computed_usage":{"*any":"189h0m0s","*data":"107374182400","*mms":"10000","*sms":"10000","*voice":"72h0m0s"},"max_increments":1000000,"remove_expired":true,"rp_subject_prefix_matching":false,"sessions_conns":[],"stats_conns":[],"thresholds_conns":[]},"rankings":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"scheduled_ids":{},"stats_conns":[],"store_interval":"","thresholds_conns":[]},"registrarc":{"dispatchers":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]},"rpc":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]}},"resources":{"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*units":1,"*usageID":""},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[],"thresholds_conns":[]},"routes":{"attributes_conns":[],"default_ratio":1,"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*context":"*routes","*ignoreErrors":false,"*maxCost":""},"prefix_indexed_fields":[],"rals_conns":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"rpc_conns":{"*bijson_localhost":{"conns":[{"address":"127.0.0.1:2014","transport":"*birpc_json"}],"poolSize":0,"strategy":"*first"},"*birpc_internal":{"conns":[{"address":"*birpc_internal","transport":""}],"poolSize":0,"strategy":"*first"},"*internal":{"conns":[{"address":"*internal","transport":""}],"poolSize":0,"strategy":"*first"},"*localhost":{"conns":[{"address":"127.0.0.1:2012","transport":"*json"}],"poolSize":0,"strategy":"*first"}},"schedulers":{"cdrs_conns":[],"dynaprepaid_actionplans":[],"enabled":false,"filters":[],"stats_conns":[],"thresholds_conns":[]},"sentrypeer":{"Audience":"https://sentrypeer.com/api","ClientID":"","ClientSecret":"","GrantType":"client_credentials","IpUrl":"https://sentrypeer.com/api/ip-addresses","NumberUrl":"https://sentrypeer.com/api/phone-numbers","TokenURL":"https://authz.sentrypeer.com/oauth/token"},"sessions":{"alterable_fields":[],"attributes_conns":[],"backup_interval":"0","cdrs_conns":[],"channel_sync_interval":"0","chargers_conns":[],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":false,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":[],"replication_conns":[],"resources_conns":[],"routes_conns":[],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]},"sip_agent":{"enabled":false,"listen":"127.0.0.1:5060","listen_net":"udp","request_processors":[],"retransmission_timer":1000000000,"sessions_conns":["*internal"],"timezone":""},"stats":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","store_uncompressed_limit":0,"suffix_indexed_fields":[],"thresholds_conns":[]},"stor_db":{"db_host":"127.0.0.1","db_name":"cgrates","db_password":"CGRateS.org","db_port":3306,"db_type":"*mysql","db_user":"cgrates","items":{"*cdrs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*session_costs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_account_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_attributes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_chargers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destination_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rankings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_routes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_stats":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_trends":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"internalDBBackupPath":"/var/lib/cgrates/internal_db/backup/stordb","internalDBDumpInterval":"0s","internalDBDumpPath":"/var/lib/cgrates/internal_db/stordb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":"0s","internalDBStartTimeout":"5m0s","mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","mysqlDSNParams":{},"mysqlLocation":"Local","pgSSLMode":"disable","pgSchema":"","sqlConnMaxLifetime":"0s","sqlLogLevel":3,"sqlMaxIdleConns":10,"sqlMaxOpenConns":100},"prefix_indexed_fields":[],"remote_conns":null,"replication_conns":null,"string_indexed_fields":[]},"suretax":{"bill_to_number":"","business_unit":"","client_number":"","client_tracking":"~*req.CGRID","customer_number":"~*req.Subject","include_local_cost":false,"orig_number":"~*req.Subject","p2pplus4":"","p2pzipcode":"","plus4":"","regulatory_code":"03","response_group":"03","response_type":"D4","return_file_code":"0","sales_type_code":"R","tax_exemption_code_list":"","tax_included":"0","tax_situs_rule":"04","term_number":"~*req.Destination","timezone":"UTC","trans_type_code":"010101","unit_type":"00","units":"1","url":"","validation_key":"","zipcode":""},"templates":{"*asr":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"}],"*cca":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"path":"*rep.Result-Code","tag":"ResultCode","type":"*constant","value":"2001"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"},{"mandatory":true,"path":"*rep.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"mandatory":true,"path":"*rep.CC-Request-Type","tag":"CCRequestType","type":"*variable","value":"~*req.CC-Request-Type"},{"mandatory":true,"path":"*rep.CC-Request-Number","tag":"CCRequestNumber","type":"*variable","value":"~*req.CC-Request-Number"}],"*cdrLog":[{"mandatory":true,"path":"*cdr.ToR","tag":"ToR","type":"*variable","value":"~*req.BalanceType"},{"mandatory":true,"path":"*cdr.OriginHost","tag":"OriginHost","type":"*constant","value":"127.0.0.1"},{"mandatory":true,"path":"*cdr.RequestType","tag":"RequestType","type":"*constant","value":"*none"},{"mandatory":true,"path":"*cdr.Tenant","tag":"Tenant","type":"*variable","value":"~*req.Tenant"},{"mandatory":true,"path":"*cdr.Account","tag":"Account","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Subject","tag":"Subject","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Cost","tag":"Cost","type":"*variable","value":"~*req.Cost"},{"mandatory":true,"path":"*cdr.Source","tag":"Source","type":"*constant","value":"*cdrLog"},{"mandatory":true,"path":"*cdr.Usage","tag":"Usage","type":"*constant","value":"1"},{"mandatory":true,"path":"*cdr.RunID","tag":"RunID","type":"*variable","value":"~*req.ActionType"},{"mandatory":true,"path":"*cdr.SetupTime","tag":"SetupTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.AnswerTime","tag":"AnswerTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.PreRated","tag":"PreRated","type":"*constant","value":"true"}],"*coa":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Filter-Id","tag":"Filter-Id","type":"*variable","value":"~*req.CustomFilter"}],"*dmr":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Reply-Message","tag":"Reply-Message","type":"*variable","value":"~*req.DisconnectCause"}],"*err":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"}],"*errSip":[{"mandatory":true,"path":"*rep.Request","tag":"Request","type":"*constant","value":"SIP/2.0 500 Internal Server Error"}],"*rar":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"path":"*diamreq.Re-Auth-Request-Type","tag":"ReAuthRequestType","type":"*constant","value":"0"}]},"thresholds":{"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]},"tls":{"ca_certificate":"","client_certificate":"","client_key":"","server_certificate":"","server_key":"","server_name":"","server_policy":4},"trends":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"scheduled_ids":{},"stats_conns":[],"store_interval":"","store_uncompressed_limit":0,"thresholds_conns":[]}}` + expected := `{"analyzers":{"cleanup_interval":"1h0m0s","db_path":"/var/spool/cgrates/analyzers","enabled":false,"index_type":"*scorch","ttl":"24h0m0s"},"apiban":{"keys":[]},"apiers":{"attributes_conns":[],"caches_conns":["*internal"],"ees_conns":[],"enabled":false,"scheduler_conns":[]},"asterisk_agent":{"asterisk_conns":[{"address":"127.0.0.1:8088","alias":"","connect_attempts":3,"max_reconnect_interval":"0s","password":"CGRateS.org","reconnects":5,"user":"cgrates"}],"create_cdr":false,"enabled":false,"sessions_conns":["*birpc_internal"]},"attributes":{"any_context":true,"apiers_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*processRuns":1,"*profileIDs":[],"*profileIgnoreFilters":false,"*profileRuns":0},"prefix_indexed_fields":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"caches":{"partitions":{"*account_action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*apiban":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2m0s"},"*attribute_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*caps_events":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*cdr_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10m0s"},"*charger_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*closed_sessions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*diameter_messages":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*dispatcher_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_loads":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_routes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatchers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*event_charges":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*event_resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*radius_packets":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*ranking_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rankings":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*replication_hosts":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_connections":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_responses":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2s"},"*sentrypeer":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":true,"ttl":"24h0m0s"},"*shared_groups":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stir":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*threshold_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*trend_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*trends":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*uch":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"}},"remote_conns":[],"replication_conns":[]},"cdrs":{"attributes_conns":[],"chargers_conns":[],"compress_stored_cost":false,"ees_conns":[],"enabled":false,"extra_fields":[],"online_cdr_exports":[],"rals_conns":[],"scheduler_conns":[],"session_cost_retries":5,"stats_conns":[],"store_cdrs":true,"thresholds_conns":[]},"chargers":{"attributes_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"suffix_indexed_fields":[]},"configs":{"enabled":false,"root_dir":"/var/spool/cgrates/configs","url":"/configs/"},"cores":{"caps":0,"caps_stats_interval":"0","caps_strategy":"*busy","shutdown_timeout":"1s"},"data_db":{"db_host":"127.0.0.1","db_name":"10","db_password":"","db_port":6379,"db_type":"*redis","db_user":"cgrates","items":{"*account_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*accounts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*ranking_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rankings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*sessions_backup":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*trend_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*trends":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"internalDBBackupPath":"/var/lib/cgrates/internal_db/backup/datadb","internalDBDumpInterval":"0s","internalDBDumpPath":"/var/lib/cgrates/internal_db/datadb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":"0s","internalDBStartTimeout":"5m0s","mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisPoolPipelineLimit":0,"redisPoolPipelineWindow":"150µs","redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"remote_conn_id":"","remote_conns":[],"replication_cache":"","replication_conns":[],"replication_failed_dir":"","replication_filtered":false,"replication_interval":"0s"},"diameter_agent":{"asr_template":"","dictionaries_path":"/usr/share/cgrates/diameter/dict/","enabled":false,"forced_disconnect":"*none","listen":"127.0.0.1:3868","listen_net":"tcp","origin_host":"CGR-DA","origin_realm":"cgrates.org","product_name":"CGRateS","rar_template":"","request_processors":[],"sessions_conns":["*birpc_internal"],"synced_conn_requests":false,"vendor_id":0},"dispatchers":{"any_subsystem":true,"attributes_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"prevent_loop":false,"suffix_indexed_fields":[]},"dns_agent":{"enabled":false,"listeners":[{"address":"127.0.0.1:53","network":"udp"}],"request_processors":[],"sessions_conns":["*internal"],"timezone":""},"ees":{"attributes_conns":[],"cache":{"*amqp_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*amqpv1_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*els":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*file_csv":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"5s"},"*kafka_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*nats_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*s3_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*sql":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*sqs_json_map":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false}},"enabled":false,"exporters":[{"attempts":1,"attribute_context":"","attribute_ids":[],"concurrent_requests":0,"export_path":"/var/spool/cgrates/ees","failed_posts_dir":"/var/spool/cgrates/failed_posts","fields":[],"filters":[],"flags":[],"id":"*default","metrics_reset_schedule":"","opts":{},"synchronous":false,"timezone":"","type":"*none"}]},"ers":{"concurrent_events":1,"ees_conns":[],"enabled":false,"partial_cache_ttl":"1s","readers":[{"cache_dump_fields":[],"concurrent_requests":1024,"fields":[{"mandatory":true,"path":"*cgreq.ToR","tag":"ToR","type":"*variable","value":"~*req.2"},{"mandatory":true,"path":"*cgreq.OriginID","tag":"OriginID","type":"*variable","value":"~*req.3"},{"mandatory":true,"path":"*cgreq.RequestType","tag":"RequestType","type":"*variable","value":"~*req.4"},{"mandatory":true,"path":"*cgreq.Tenant","tag":"Tenant","type":"*variable","value":"~*req.6"},{"mandatory":true,"path":"*cgreq.Category","tag":"Category","type":"*variable","value":"~*req.7"},{"mandatory":true,"path":"*cgreq.Account","tag":"Account","type":"*variable","value":"~*req.8"},{"mandatory":true,"path":"*cgreq.Subject","tag":"Subject","type":"*variable","value":"~*req.9"},{"mandatory":true,"path":"*cgreq.Destination","tag":"Destination","type":"*variable","value":"~*req.10"},{"mandatory":true,"path":"*cgreq.SetupTime","tag":"SetupTime","type":"*variable","value":"~*req.11"},{"mandatory":true,"path":"*cgreq.AnswerTime","tag":"AnswerTime","type":"*variable","value":"~*req.12"},{"mandatory":true,"path":"*cgreq.Usage","tag":"Usage","type":"*variable","value":"~*req.13"}],"filters":[],"flags":[],"id":"*default","max_reconnect_interval":"5m0s","opts":{"csvFieldSeparator":",","csvHeaderDefineChar":":","csvRowLength":0,"natsSubject":"cgrates_cdrs","partialCacheAction":"*none","partialOrderField":"~*req.AnswerTime"},"partial_commit_fields":[],"processed_path":"/var/spool/cgrates/ers/out","reconnects":-1,"run_delay":"0","source_path":"/var/spool/cgrates/ers/in","start_delay":"0","tenant":"","timezone":"","type":"*none"}],"sessions_conns":["*internal"]},"filters":{"apiers_conns":[],"rankings_conns":[],"resources_conns":[],"stats_conns":[],"trends_conns":[]},"freeswitch_agent":{"active_session_delimiter":",","create_cdr":false,"empty_balance_ann_file":"","empty_balance_context":"","enabled":false,"event_socket_conns":[{"address":"127.0.0.1:8021","alias":"127.0.0.1:8021","max_reconnect_interval":"0s","password":"ClueCon","reconnects":5,"reply_timeout":"1m0s"}],"extra_fields":"","low_balance_ann_file":"","max_wait_connection":"2s","sessions_conns":["*birpc_internal"],"subscribe_park":true},"general":{"caching_delay":"0","connect_attempts":5,"connect_timeout":"1s","dbdata_encoding":"*msgpack","default_caching":"*reload","default_category":"call","default_request_type":"*rated","default_tenant":"cgrates.org","default_timezone":"Local","digest_equal":":","digest_separator":",","failed_posts_dir":"/var/spool/cgrates/failed_posts","failed_posts_ttl":"5s","locking_timeout":"0","log_level":6,"logger":"*syslog","max_parallel_conns":100,"max_reconnect_interval":"0","node_id":"ENGINE1","poster_attempts":3,"reconnects":-1,"reply_timeout":"2s","rounding_decimals":5,"rsr_separator":";","tpexport_dir":"/var/spool/cgrates/tpe"},"http":{"auth_users":{},"client_opts":{"dialFallbackDelay":"300ms","dialKeepAlive":"30s","dialTimeout":"30s","disableCompression":false,"disableKeepAlives":false,"expectContinueTimeout":"0s","forceAttemptHttp2":true,"idleConnTimeout":"1m30s","maxConnsPerHost":0,"maxIdleConns":100,"maxIdleConnsPerHost":2,"responseHeaderTimeout":"0s","skipTlsVerify":false,"tlsHandshakeTimeout":"10s"},"freeswitch_cdrs_url":"/freeswitch_json","http_cdrs":"/cdr_http","json_rpc_url":"/jsonrpc","pprof_path":"/debug/pprof/","registrars_url":"/registrar","use_basic_auth":false,"ws_url":"/ws"},"http_agent":[],"kamailio_agent":{"create_cdr":false,"enabled":false,"evapi_conns":[{"address":"127.0.0.1:8448","alias":"","max_reconnect_interval":"0s","reconnects":5}],"sessions_conns":["*birpc_internal"],"timezone":""},"listen":{"http":"127.0.0.1:2080","http_tls":"127.0.0.1:2280","rpc_gob":"127.0.0.1:2013","rpc_gob_tls":"127.0.0.1:2023","rpc_json":"127.0.0.1:2012","rpc_json_tls":"127.0.0.1:2022"},"loader":{"caches_conns":["*localhost"],"data_path":"./","disable_reverse":false,"field_separator":",","gapi_credentials":".gapi/credentials.json","gapi_token":".gapi/token.json","scheduler_conns":["*localhost"],"tpid":""},"loaders":[{"caches_conns":["*internal"],"data":[{"fields":[{"mandatory":true,"path":"Tenant","tag":"TenantID","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ProfileID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"AttributeFilterIDs","tag":"AttributeFilterIDs","type":"*variable","value":"~*req.5"},{"path":"Path","tag":"Path","type":"*variable","value":"~*req.6"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.7"},{"path":"Value","tag":"Value","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.10"}],"file_name":"Attributes.csv","flags":null,"type":"*attributes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.2"},{"path":"Element","tag":"Element","type":"*variable","value":"~*req.3"},{"path":"Values","tag":"Values","type":"*variable","value":"~*req.4"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.5"}],"file_name":"Filters.csv","flags":null,"type":"*filters"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"UsageTTL","tag":"TTL","type":"*variable","value":"~*req.4"},{"path":"Limit","tag":"Limit","type":"*variable","value":"~*req.5"},{"path":"AllocationMessage","tag":"AllocationMessage","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.8"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.9"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.10"}],"file_name":"Resources.csv","flags":null,"type":"*resources"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"QueueLength","tag":"QueueLength","type":"*variable","value":"~*req.4"},{"path":"TTL","tag":"TTL","type":"*variable","value":"~*req.5"},{"path":"MinItems","tag":"MinItems","type":"*variable","value":"~*req.6"},{"path":"MetricIDs","tag":"MetricIDs","type":"*variable","value":"~*req.7"},{"path":"MetricFilterIDs","tag":"MetricFilterIDs","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.10"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.11"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.12"}],"file_name":"Stats.csv","flags":null,"type":"*stats"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"MaxHits","tag":"MaxHits","type":"*variable","value":"~*req.4"},{"path":"MinHits","tag":"MinHits","type":"*variable","value":"~*req.5"},{"path":"MinSleep","tag":"MinSleep","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.8"},{"path":"ActionIDs","tag":"ActionIDs","type":"*variable","value":"~*req.9"},{"path":"Async","tag":"Async","type":"*variable","value":"~*req.10"}],"file_name":"Thresholds.csv","flags":null,"type":"*thresholds"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"Sorting","tag":"Sorting","type":"*variable","value":"~*req.4"},{"path":"SortingParameters","tag":"SortingParameters","type":"*variable","value":"~*req.5"},{"path":"RouteID","tag":"RouteID","type":"*variable","value":"~*req.6"},{"path":"RouteFilterIDs","tag":"RouteFilterIDs","type":"*variable","value":"~*req.7"},{"path":"RouteAccountIDs","tag":"RouteAccountIDs","type":"*variable","value":"~*req.8"},{"path":"RouteRatingPlanIDs","tag":"RouteRatingPlanIDs","type":"*variable","value":"~*req.9"},{"path":"RouteResourceIDs","tag":"RouteResourceIDs","type":"*variable","value":"~*req.10"},{"path":"RouteStatIDs","tag":"RouteStatIDs","type":"*variable","value":"~*req.11"},{"path":"RouteWeight","tag":"RouteWeight","type":"*variable","value":"~*req.12"},{"path":"RouteBlocker","tag":"RouteBlocker","type":"*variable","value":"~*req.13"},{"path":"RouteParameters","tag":"RouteParameters","type":"*variable","value":"~*req.14"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.15"}],"file_name":"Routes.csv","flags":null,"type":"*routes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"RunID","tag":"RunID","type":"*variable","value":"~*req.4"},{"path":"AttributeIDs","tag":"AttributeIDs","type":"*variable","value":"~*req.5"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.6"}],"file_name":"Chargers.csv","flags":null,"type":"*chargers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"Strategy","tag":"Strategy","type":"*variable","value":"~*req.5"},{"path":"StrategyParameters","tag":"StrategyParameters","type":"*variable","value":"~*req.6"},{"path":"ConnID","tag":"ConnID","type":"*variable","value":"~*req.7"},{"path":"ConnFilterIDs","tag":"ConnFilterIDs","type":"*variable","value":"~*req.8"},{"path":"ConnWeight","tag":"ConnWeight","type":"*variable","value":"~*req.9"},{"path":"ConnBlocker","tag":"ConnBlocker","type":"*variable","value":"~*req.10"},{"path":"ConnParameters","tag":"ConnParameters","type":"*variable","value":"~*req.11"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherProfiles.csv","flags":null,"type":"*dispatchers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Address","tag":"Address","type":"*variable","value":"~*req.2"},{"path":"Transport","tag":"Transport","type":"*variable","value":"~*req.3"},{"path":"ConnectAttempts","tag":"ConnectAttempts","type":"*variable","value":"~*req.4"},{"path":"Reconnects","tag":"Reconnects","type":"*variable","value":"~*req.5"},{"path":"MaxReconnectInterval","tag":"MaxReconnectInterval","type":"*variable","value":"~*req.6"},{"path":"ConnectTimeout","tag":"ConnectTimeout","type":"*variable","value":"~*req.7"},{"path":"ReplyTimeout","tag":"ReplyTimeout","type":"*variable","value":"~*req.8"},{"path":"TLS","tag":"TLS","type":"*variable","value":"~*req.9"},{"path":"ClientKey","tag":"ClientKey","type":"*variable","value":"~*req.10"},{"path":"ClientCertificate","tag":"ClientCertificate","type":"*variable","value":"~*req.11"},{"path":"CaCertificate","tag":"CaCertificate","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherHosts.csv","flags":null,"type":"*dispatcher_hosts"}],"dry_run":false,"enabled":false,"field_separator":",","id":"*default","lockfile_path":".cgr.lck","run_delay":"0","tenant":"","tp_in_dir":"/var/spool/cgrates/loader/in","tp_out_dir":"/var/spool/cgrates/loader/out"}],"mailer":{"auth_password":"CGRateS.org","auth_user":"cgrates","from_address":"cgr-mailer@localhost.localdomain","server":"localhost"},"migrator":{"out_datadb_encoding":"msgpack","out_datadb_host":"127.0.0.1","out_datadb_name":"10","out_datadb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisPoolPipelineLimit":0,"redisPoolPipelineWindow":"150µs","redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"out_datadb_password":"","out_datadb_port":"6379","out_datadb_type":"*redis","out_datadb_user":"cgrates","out_stordb_host":"127.0.0.1","out_stordb_name":"cgrates","out_stordb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","mysqlDSNParams":null,"mysqlLocation":"","pgSSLMode":"","sqlConnMaxLifetime":"0s","sqlMaxIdleConns":0,"sqlMaxOpenConns":0},"out_stordb_password":"","out_stordb_port":"3306","out_stordb_type":"*mysql","out_stordb_user":"cgrates","users_filters":null},"prometheus_agent":{"collect_go_metrics":false,"collect_process_metrics":false,"cores_conns":null,"enabled":false,"path":"/prometheus","stat_queue_ids":null,"stats_conns":null},"radius_agent":{"client_dictionaries":{"*default":["/usr/share/cgrates/radius/dict/"]},"client_secrets":{"*default":"CGRateS.org"},"coa_template":"*coa","dmr_template":"*dmr","enabled":false,"listeners":[{"acct_address":"127.0.0.1:1813","auth_address":"127.0.0.1:1812","network":"udp"}],"request_processors":[],"requests_cache_key":"","sessions_conns":["*internal"]},"rals":{"balance_rating_subject":{"*any":"*zero1ns","*voice":"*zero1s"},"enabled":false,"fallback_depth":3,"max_computed_usage":{"*any":"189h0m0s","*data":"107374182400","*mms":"10000","*sms":"10000","*voice":"72h0m0s"},"max_increments":1000000,"remove_expired":true,"rp_subject_prefix_matching":false,"sessions_conns":[],"stats_conns":[],"thresholds_conns":[]},"rankings":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"scheduled_ids":{},"stats_conns":[],"store_interval":"","thresholds_conns":[]},"registrarc":{"dispatchers":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]},"rpc":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]}},"resources":{"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*units":1,"*usageID":""},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[],"thresholds_conns":[]},"routes":{"attributes_conns":[],"default_ratio":1,"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*context":"*routes","*ignoreErrors":false,"*maxCost":""},"prefix_indexed_fields":[],"rals_conns":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"rpc_conns":{"*bijson_localhost":{"conns":[{"address":"127.0.0.1:2014","transport":"*birpc_json"}],"poolSize":0,"strategy":"*first"},"*birpc_internal":{"conns":[{"address":"*birpc_internal","transport":""}],"poolSize":0,"strategy":"*first"},"*internal":{"conns":[{"address":"*internal","transport":""}],"poolSize":0,"strategy":"*first"},"*localhost":{"conns":[{"address":"127.0.0.1:2012","transport":"*json"}],"poolSize":0,"strategy":"*first"}},"schedulers":{"cdrs_conns":[],"dynaprepaid_actionplans":[],"enabled":false,"filters":[],"stats_conns":[],"thresholds_conns":[]},"sentrypeer":{"Audience":"https://sentrypeer.com/api","ClientID":"","ClientSecret":"","GrantType":"client_credentials","IpUrl":"https://sentrypeer.com/api/ip-addresses","NumberUrl":"https://sentrypeer.com/api/phone-numbers","TokenURL":"https://authz.sentrypeer.com/oauth/token"},"sessions":{"alterable_fields":[],"attributes_conns":[],"backup_interval":"0","cdrs_conns":[],"channel_sync_interval":"0","chargers_conns":[],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":false,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":[],"replication_conns":[],"resources_conns":[],"routes_conns":[],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]},"sip_agent":{"enabled":false,"listen":"127.0.0.1:5060","listen_net":"udp","request_processors":[],"retransmission_timer":1000000000,"sessions_conns":["*internal"],"timezone":""},"stats":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","store_uncompressed_limit":0,"suffix_indexed_fields":[],"thresholds_conns":[]},"stor_db":{"db_host":"127.0.0.1","db_name":"cgrates","db_password":"CGRateS.org","db_port":3306,"db_type":"*mysql","db_user":"cgrates","items":{"*cdrs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*session_costs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_account_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_attributes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_chargers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destination_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rankings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_routes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_stats":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_trends":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"internalDBBackupPath":"/var/lib/cgrates/internal_db/backup/stordb","internalDBDumpInterval":"0s","internalDBDumpPath":"/var/lib/cgrates/internal_db/stordb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":"0s","internalDBStartTimeout":"5m0s","mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","mysqlDSNParams":{},"mysqlLocation":"Local","pgSSLMode":"disable","pgSchema":"","sqlConnMaxLifetime":"0s","sqlLogLevel":3,"sqlMaxIdleConns":10,"sqlMaxOpenConns":100},"prefix_indexed_fields":[],"remote_conns":null,"replication_conns":null,"string_indexed_fields":[]},"suretax":{"bill_to_number":"","business_unit":"","client_number":"","client_tracking":"~*req.CGRID","customer_number":"~*req.Subject","include_local_cost":false,"orig_number":"~*req.Subject","p2pplus4":"","p2pzipcode":"","plus4":"","regulatory_code":"03","response_group":"03","response_type":"D4","return_file_code":"0","sales_type_code":"R","tax_exemption_code_list":"","tax_included":"0","tax_situs_rule":"04","term_number":"~*req.Destination","timezone":"UTC","trans_type_code":"010101","unit_type":"00","units":"1","url":"","validation_key":"","zipcode":""},"templates":{"*asr":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"}],"*cca":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"path":"*rep.Result-Code","tag":"ResultCode","type":"*constant","value":"2001"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"},{"mandatory":true,"path":"*rep.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"mandatory":true,"path":"*rep.CC-Request-Type","tag":"CCRequestType","type":"*variable","value":"~*req.CC-Request-Type"},{"mandatory":true,"path":"*rep.CC-Request-Number","tag":"CCRequestNumber","type":"*variable","value":"~*req.CC-Request-Number"}],"*cdrLog":[{"mandatory":true,"path":"*cdr.ToR","tag":"ToR","type":"*variable","value":"~*req.BalanceType"},{"mandatory":true,"path":"*cdr.OriginHost","tag":"OriginHost","type":"*constant","value":"127.0.0.1"},{"mandatory":true,"path":"*cdr.RequestType","tag":"RequestType","type":"*constant","value":"*none"},{"mandatory":true,"path":"*cdr.Tenant","tag":"Tenant","type":"*variable","value":"~*req.Tenant"},{"mandatory":true,"path":"*cdr.Account","tag":"Account","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Subject","tag":"Subject","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Cost","tag":"Cost","type":"*variable","value":"~*req.Cost"},{"mandatory":true,"path":"*cdr.Source","tag":"Source","type":"*constant","value":"*cdrLog"},{"mandatory":true,"path":"*cdr.Usage","tag":"Usage","type":"*constant","value":"1"},{"mandatory":true,"path":"*cdr.RunID","tag":"RunID","type":"*variable","value":"~*req.ActionType"},{"mandatory":true,"path":"*cdr.SetupTime","tag":"SetupTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.AnswerTime","tag":"AnswerTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.PreRated","tag":"PreRated","type":"*constant","value":"true"}],"*coa":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Filter-Id","tag":"Filter-Id","type":"*variable","value":"~*req.CustomFilter"}],"*dmr":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Reply-Message","tag":"Reply-Message","type":"*variable","value":"~*req.DisconnectCause"}],"*err":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"}],"*errSip":[{"mandatory":true,"path":"*rep.Request","tag":"Request","type":"*constant","value":"SIP/2.0 500 Internal Server Error"}],"*rar":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"path":"*diamreq.Re-Auth-Request-Type","tag":"ReAuthRequestType","type":"*constant","value":"0"}]},"thresholds":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]},"tls":{"ca_certificate":"","client_certificate":"","client_key":"","server_certificate":"","server_key":"","server_name":"","server_policy":4},"trends":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"scheduled_ids":{},"stats_conns":[],"store_interval":"","store_uncompressed_limit":0,"thresholds_conns":[]}}` if err != nil { t.Fatal(err) } diff --git a/config/libconfig_json.go b/config/libconfig_json.go index cedda9bd4..445d777ab 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -732,6 +732,8 @@ type ThresholdSJsonCfg struct { Store_interval *string Sessions_conns []string Apiers_conns []string + Ees_conns *[]string + Ees_exporter_ids *[]string String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string diff --git a/config/thresholdscfg.go b/config/thresholdscfg.go index 169a161c2..88d8b60f5 100644 --- a/config/thresholdscfg.go +++ b/config/thresholdscfg.go @@ -37,6 +37,8 @@ type ThresholdSCfg struct { StoreInterval time.Duration // Dump regularly from cache into dataDB SessionSConns []string ApierSConns []string + EEsExporterIDs []string + EEsConns []string StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string @@ -92,6 +94,19 @@ func (t *ThresholdSCfg) loadFromJSONCfg(jsnCfg *ThresholdSJsonCfg) (err error) { } } } + if jsnCfg.Ees_conns != nil { + t.EEsConns = make([]string, len(*jsnCfg.Ees_conns)) + for idx, connID := range *jsnCfg.Ees_conns { + // if we have the connection internal we change the name so we can have internal rpc for each subsystem + t.EEsConns[idx] = connID + if connID == utils.MetaInternal { + t.EEsConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaEEs) + } + } + } + if jsnCfg.Ees_exporter_ids != nil { + t.EEsExporterIDs = append(t.EEsExporterIDs, *jsnCfg.Ees_exporter_ids...) + } if jsnCfg.String_indexed_fields != nil { sif := make([]string, len(*jsnCfg.String_indexed_fields)) copy(sif, *jsnCfg.String_indexed_fields) @@ -146,6 +161,9 @@ func (t *ThresholdSCfg) AsMapInterface() (initialMP map[string]any) { } initialMP[utils.SessionSConnsCfg] = sessionConns } + eesExporterIDs := make([]string, len(t.EEsExporterIDs)) + copy(eesExporterIDs, t.EEsExporterIDs) + initialMP[utils.EEsExporterIDsCfg] = eesExporterIDs if t.ApierSConns != nil { apiersConns := make([]string, len(t.ApierSConns)) for i, item := range t.ApierSConns { @@ -156,6 +174,16 @@ func (t *ThresholdSCfg) AsMapInterface() (initialMP map[string]any) { } initialMP[utils.ApierSConnsCfg] = apiersConns } + if t.EEsConns != nil { + eesConns := make([]string, len(t.EEsConns)) + for i, item := range t.EEsConns { + eesConns[i] = item + if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaEEs) { + eesConns[i] = utils.MetaInternal + } + } + initialMP[utils.EEsConnsCfg] = eesConns + } if t.StringIndexedFields != nil { stringIndexedFields := make([]string, len(*t.StringIndexedFields)) copy(stringIndexedFields, *t.StringIndexedFields) @@ -202,6 +230,14 @@ func (t ThresholdSCfg) Clone() (cln *ThresholdSCfg) { cln.ApierSConns = make([]string, len(t.ApierSConns)) copy(cln.ApierSConns, t.ApierSConns) } + if t.EEsConns != nil { + cln.EEsConns = make([]string, len(t.EEsConns)) + copy(cln.EEsConns, t.EEsConns) + } + if t.EEsExporterIDs != nil { + cln.EEsExporterIDs = make([]string, len(t.EEsExporterIDs)) + copy(cln.EEsExporterIDs, t.EEsExporterIDs) + } if t.StringIndexedFields != nil { idx := make([]string, len(*t.StringIndexedFields)) copy(idx, *t.StringIndexedFields) diff --git a/config/thresholdscfg_test.go b/config/thresholdscfg_test.go index 6e500c96e..538d6be8a 100644 --- a/config/thresholdscfg_test.go +++ b/config/thresholdscfg_test.go @@ -47,6 +47,7 @@ func TestThresholdSCfgloadFromJsonCfgCase1(t *testing.T) { PrefixIndexedFields: &[]string{"*req.index1"}, SuffixIndexedFields: &[]string{"*req.index1"}, ExistsIndexedFields: &[]string{"*req.index1"}, + EEsConns: []string{}, NestedFields: true, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, @@ -89,6 +90,8 @@ func TestThresholdSCfgAsMapInterfaceCase1(t *testing.T) { utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, utils.ExistsIndexedFieldsCfg: []string{}, + utils.EEsExporterIDsCfg: []string{}, + utils.EEsConnsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, @@ -124,6 +127,8 @@ func TestThresholdSCfgAsMapInterfaceCase2(t *testing.T) { utils.SuffixIndexedFieldsCfg: []string{"*req.suffix_indexed_fields1", "*req.suffix_indexed_fields2"}, utils.ExistsIndexedFieldsCfg: []string{"*req.exists_indexed_field"}, utils.NestedFieldsCfg: true, + utils.EEsExporterIDsCfg: []string{}, + utils.EEsConnsCfg: []string{}, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, utils.MetaProfileIgnoreFiltersCfg: false, diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index 8519cd5f0..853337ff5 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -364,6 +364,7 @@ CREATE TABLE tp_thresholds ( `weight` decimal(8,2) NOT NULL, `action_ids` varchar(64) NOT NULL, `async` BOOLEAN NOT NULL, + `ees_ids` varchar(64) NOT NULL, `created_at` TIMESTAMP, PRIMARY KEY (`pk`), KEY `tpid` (`tpid`), diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index 832bc2572..90c583e5b 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -355,6 +355,7 @@ CREATE TABLE tp_thresholds ( "weight" decimal(8,2) NOT NULL, "action_ids" varchar(64) NOT NULL, "async" BOOLEAN NOT NULL, + "ees_ids" varchar(64) NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE ); CREATE INDEX tp_thresholds_idx ON tp_thresholds (tpid); diff --git a/data/tariffplans/oldtutorial/Thresholds.csv b/data/tariffplans/oldtutorial/Thresholds.csv index 438e0ccf2..ed8316629 100644 --- a/data/tariffplans/oldtutorial/Thresholds.csv +++ b/data/tariffplans/oldtutorial/Thresholds.csv @@ -1,8 +1,8 @@ -#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] -cgrates.org,THD_ACNT_BALANCE_1,FLTR_ACNT_BALANCE_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_ACNT_EXPIRED,FLTR_ACNT_EXPIRED,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_STATS_1,FLTR_STATS_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_STATS_2,FLTR_STATS_2,2014-07-29T15:00:00Z,-1,1,1s,false,10,DISABLE_AND_LOG,false -cgrates.org,THD_STATS_3,FLTR_STATS_3,2014-07-29T15:00:00Z,1,1,1s,false,10,TOPUP_100SMS_DE_MOBILE,false -cgrates.org,THD_RES_1,FLTR_RES_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_CDRS_1,FLTR_ACNT_1007;FLTR_CDR_UPDATE,2014-07-29T15:00:00Z,1,1,1s,false,10,LOG_WARNING,false +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11] +cgrates.org,THD_ACNT_BALANCE_1,FLTR_ACNT_BALANCE_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_ACNT_EXPIRED,FLTR_ACNT_EXPIRED,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_STATS_1,FLTR_STATS_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_STATS_2,FLTR_STATS_2,2014-07-29T15:00:00Z,-1,1,1s,false,10,DISABLE_AND_LOG,false, +cgrates.org,THD_STATS_3,FLTR_STATS_3,2014-07-29T15:00:00Z,1,1,1s,false,10,TOPUP_100SMS_DE_MOBILE,false, +cgrates.org,THD_RES_1,FLTR_RES_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_CDRS_1,FLTR_ACNT_1007;FLTR_CDR_UPDATE,2014-07-29T15:00:00Z,1,1,1s,false,10,LOG_WARNING,false, diff --git a/data/tariffplans/precache/Thresholds.csv b/data/tariffplans/precache/Thresholds.csv index 438e0ccf2..ed8316629 100644 --- a/data/tariffplans/precache/Thresholds.csv +++ b/data/tariffplans/precache/Thresholds.csv @@ -1,8 +1,8 @@ -#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] -cgrates.org,THD_ACNT_BALANCE_1,FLTR_ACNT_BALANCE_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_ACNT_EXPIRED,FLTR_ACNT_EXPIRED,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_STATS_1,FLTR_STATS_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_STATS_2,FLTR_STATS_2,2014-07-29T15:00:00Z,-1,1,1s,false,10,DISABLE_AND_LOG,false -cgrates.org,THD_STATS_3,FLTR_STATS_3,2014-07-29T15:00:00Z,1,1,1s,false,10,TOPUP_100SMS_DE_MOBILE,false -cgrates.org,THD_RES_1,FLTR_RES_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false -cgrates.org,THD_CDRS_1,FLTR_ACNT_1007;FLTR_CDR_UPDATE,2014-07-29T15:00:00Z,1,1,1s,false,10,LOG_WARNING,false +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11] +cgrates.org,THD_ACNT_BALANCE_1,FLTR_ACNT_BALANCE_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_ACNT_EXPIRED,FLTR_ACNT_EXPIRED,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_STATS_1,FLTR_STATS_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_STATS_2,FLTR_STATS_2,2014-07-29T15:00:00Z,-1,1,1s,false,10,DISABLE_AND_LOG,false, +cgrates.org,THD_STATS_3,FLTR_STATS_3,2014-07-29T15:00:00Z,1,1,1s,false,10,TOPUP_100SMS_DE_MOBILE,false, +cgrates.org,THD_RES_1,FLTR_RES_1,2014-07-29T15:00:00Z,-1,1,1s,false,10,LOG_WARNING,false, +cgrates.org,THD_CDRS_1,FLTR_ACNT_1007;FLTR_CDR_UPDATE,2014-07-29T15:00:00Z,1,1,1s,false,10,LOG_WARNING,false, diff --git a/data/tariffplans/testit/Thresholds.csv b/data/tariffplans/testit/Thresholds.csv index abec5bf62..ede301aa3 100644 --- a/data/tariffplans/testit/Thresholds.csv +++ b/data/tariffplans/testit/Thresholds.csv @@ -1,2 +1,2 @@ -#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] -cgrates.org,THD_ACNT_1001,FLTR_ACCOUNT_1001,2014-07-29T15:00:00Z,-1,0,0,false,10,TOPUP_MONETARY_10,false \ No newline at end of file +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11] +cgrates.org,THD_ACNT_1001,FLTR_ACCOUNT_1001,2014-07-29T15:00:00Z,-1,0,0,false,10,TOPUP_MONETARY_10,false, \ No newline at end of file diff --git a/data/tariffplans/testtp/Thresholds.csv b/data/tariffplans/testtp/Thresholds.csv index f4fdabe20..9aa1c8a37 100644 --- a/data/tariffplans/testtp/Thresholds.csv +++ b/data/tariffplans/testtp/Thresholds.csv @@ -1,2 +1,2 @@ -#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] -cgrates.org,Threshold1,FLTR_1;FLTR_ACNT_dan,2014-07-29T15:00:00Z,-1,10,1s,true,10,THRESH1;THRESH2,true +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11] +cgrates.org,Threshold1,FLTR_1;FLTR_ACNT_dan,2014-07-29T15:00:00Z,-1,10,1s,true,10,THRESH1;THRESH2,true, diff --git a/data/tariffplans/tutorial/Thresholds.csv b/data/tariffplans/tutorial/Thresholds.csv index d36d65814..cdaa96680 100644 --- a/data/tariffplans/tutorial/Thresholds.csv +++ b/data/tariffplans/tutorial/Thresholds.csv @@ -1,3 +1,3 @@ -#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] -cgrates.org,THD_ACNT_1001,FLTR_ACNT_1001,2014-07-29T15:00:00Z,1,1,1s,false,10,ACT_LOG_WARNING,true -cgrates.org,THD_ACNT_1002,FLTR_ACNT_1002,2014-07-29T15:00:00Z,-1,1,1s,false,10,ACT_LOG_WARNING,true +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11] +cgrates.org,THD_ACNT_1001,FLTR_ACNT_1001,2014-07-29T15:00:00Z,1,1,1s,false,10,ACT_LOG_WARNING,true,ocs_api_event +cgrates.org,THD_ACNT_1002,FLTR_ACNT_1002,2014-07-29T15:00:00Z,-1,1,1s,false,10,ACT_LOG_WARNING,true, diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 7af09c04c..b38c2ed52 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -245,8 +245,8 @@ cgrates.org,Ranking1,@every 5m,Stats2;Stats3;Stats4,Metric1;Metric3,*asc,,true,T 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] -cgrates.org,Threshold1,*string:~*req.Account:1001;*string:~*req.RunID:*default,2014-07-29T15:00:00Z,12,10,1s,true,10,THRESH1,true +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11] +cgrates.org,Threshold1,*string:~*req.Account:1001;*string:~*req.RunID:*default,2014-07-29T15:00:00Z,12,10,1s,true,10,THRESH1,true, ` FiltersCSVContent = ` diff --git a/engine/model_helpers.go b/engine/model_helpers.go index 0ff535b1a..013a1ea67 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -1813,13 +1813,14 @@ type ThresholdMdls []*ThresholdMdl func (tps ThresholdMdls) CSVHeader() (result []string) { return []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, utils.ActivationIntervalString, utils.MaxHits, utils.MinHits, utils.MinSleep, - utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async} + utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async, utils.EeIDs} } func (tps ThresholdMdls) AsTPThreshold() (result []*utils.TPThresholdProfile) { mst := make(map[string]*utils.TPThresholdProfile) filterMap := make(map[string]utils.StringSet) actionMap := make(map[string]utils.StringSet) + eeIDsMap := make(map[string]utils.StringSet) for _, tp := range tps { tenID := (&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID() th, found := mst[tenID] @@ -1841,6 +1842,12 @@ func (tps ThresholdMdls) AsTPThreshold() (result []*utils.TPThresholdProfile) { } actionMap[tenID].AddSlice(strings.Split(tp.ActionIDs, utils.InfieldSep)) } + if tp.EeIDs != utils.EmptyString { + if _, has := eeIDsMap[tenID]; !has { + eeIDsMap[tenID] = make(utils.StringSet) + } + eeIDsMap[tenID].AddSlice(strings.Split(tp.EeIDs, utils.InfieldSep)) + } if tp.Weight != 0 { th.Weight = tp.Weight } @@ -1869,6 +1876,7 @@ func (tps ThresholdMdls) AsTPThreshold() (result []*utils.TPThresholdProfile) { result[i] = th result[i].FilterIDs = filterMap[tntID].AsSlice() result[i].ActionIDs = actionMap[tntID].AsSlice() + result[i].EeIDs = eeIDsMap[tntID].AsSlice() i++ } return @@ -1883,7 +1891,10 @@ func APItoModelTPThreshold(th *utils.TPThresholdProfile) (mdls ThresholdMdls) { if min > len(th.ActionIDs) { min = len(th.ActionIDs) } - for i := 0; i < min; i++ { + if min > len(th.EeIDs) { + min = len(th.EeIDs) + } + for i := range min { mdl := &ThresholdMdl{ Tpid: th.TPid, Tenant: th.Tenant, @@ -1907,6 +1918,7 @@ func APItoModelTPThreshold(th *utils.TPThresholdProfile) (mdls ThresholdMdls) { } mdl.FilterIDs = th.FilterIDs[i] mdl.ActionIDs = th.ActionIDs[i] + mdl.EeIDs = th.EeIDs[i] mdls = append(mdls, mdl) } @@ -1921,6 +1933,17 @@ func APItoModelTPThreshold(th *utils.TPThresholdProfile) (mdls ThresholdMdls) { mdls = append(mdls, mdl) } } + if len(th.EeIDs)-min > 0 { + for i := min; i < len(th.EeIDs); i++ { + mdl := &ThresholdMdl{ + Tpid: th.TPid, + Tenant: th.Tenant, + ID: th.ID, + } + mdl.EeIDs = th.EeIDs[i] + mdls = append(mdls, mdl) + } + } if len(th.ActionIDs)-min > 0 { for i := min; i < len(th.ActionIDs); i++ { mdl := &ThresholdMdl{ @@ -1963,6 +1986,7 @@ func APItoThresholdProfile(tpTH *utils.TPThresholdProfile, timezone string) (th Async: tpTH.Async, ActionIDs: make([]string, len(tpTH.ActionIDs)), FilterIDs: make([]string, len(tpTH.FilterIDs)), + EeIDs: make([]string, len(tpTH.EeIDs)), } if tpTH.MinSleep != utils.EmptyString { if th.MinSleep, err = utils.ParseDurationWithNanosecs(tpTH.MinSleep); err != nil { @@ -1972,6 +1996,7 @@ func APItoThresholdProfile(tpTH *utils.TPThresholdProfile, timezone string) (th copy(th.ActionIDs, tpTH.ActionIDs) copy(th.FilterIDs, tpTH.FilterIDs) + copy(th.EeIDs, tpTH.EeIDs) if tpTH.ActivationInterval != nil { if th.ActivationInterval, err = tpTH.ActivationInterval.AsActivationInterval(timezone); err != nil { @@ -1992,6 +2017,7 @@ func ThresholdProfileToAPI(th *ThresholdProfile) (tpTH *utils.TPThresholdProfile Blocker: th.Blocker, Weight: th.Weight, ActionIDs: make([]string, len(th.ActionIDs)), + EeIDs: make([]string, len(th.EeIDs)), Async: th.Async, } if th.MinSleep != time.Duration(0) { @@ -2000,6 +2026,7 @@ func ThresholdProfileToAPI(th *ThresholdProfile) (tpTH *utils.TPThresholdProfile copy(tpTH.FilterIDs, th.FilterIDs) copy(tpTH.ActionIDs, th.ActionIDs) + copy(tpTH.EeIDs, th.EeIDs) if th.ActivationInterval != nil { if !th.ActivationInterval.ActivationTime.IsZero() { diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index 87258fa90..7beb3786d 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -2290,6 +2290,7 @@ func TestAPItoModelTPThreshold(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } models := ThresholdMdls{ { @@ -2304,6 +2305,7 @@ func TestAPItoModelTPThreshold(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: "WARN3", + EeIDs: "EE1", }, } rcv := APItoModelTPThreshold(th) @@ -2328,6 +2330,7 @@ func TestAPItoModelTPThreshold2(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } models := ThresholdMdls{ { @@ -2342,6 +2345,7 @@ func TestAPItoModelTPThreshold2(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: "WARN3", + EeIDs: "EE1", }, { Tpid: "TP1", @@ -2372,6 +2376,7 @@ func TestAPItoModelTPThreshold3(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: []string{"WARN3", "LOG"}, + EeIDs: []string{"EE1"}, } models := ThresholdMdls{ { @@ -2386,6 +2391,7 @@ func TestAPItoModelTPThreshold3(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: "WARN3", + EeIDs: "EE1", }, { Tpid: "TP1", @@ -2415,9 +2421,16 @@ func TestAPItoModelTPThreshold4(t *testing.T) { MinSleep: "1s", Blocker: false, Weight: 20.0, - ActionIDs: []string{"WARN3", "LOG"}, + ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } models := ThresholdMdls{ + { + Tpid: "TP1", + Tenant: "cgrates.org", + ID: "TH_1", + EeIDs: "EE1", + }, { Tpid: "TP1", Tenant: "cgrates.org", @@ -2430,12 +2443,6 @@ func TestAPItoModelTPThreshold4(t *testing.T) { Weight: 20.0, ActionIDs: "WARN3", }, - { - Tpid: "TP1", - Tenant: "cgrates.org", - ID: "TH_1", - ActionIDs: "LOG", - }, } rcv := APItoModelTPThreshold(th) if !reflect.DeepEqual(models, rcv) { @@ -2459,6 +2466,7 @@ func TestAPItoModelTPThreshold5(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: []string{}, + EeIDs: []string{}, } rcv := APItoModelTPThreshold(th) if rcv != nil { @@ -2478,6 +2486,7 @@ func TestAPItoTPThreshold(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } eTPs := &ThresholdProfile{ @@ -2488,6 +2497,7 @@ func TestAPItoTPThreshold(t *testing.T) { Weight: tps.Weight, FilterIDs: tps.FilterIDs, ActionIDs: []string{"WARN3"}, + EeIDs: tps.EeIDs, } if eTPs.MinSleep, err = utils.ParseDurationWithNanosecs(tps.MinSleep); err != nil { t.Errorf("Got error: %+v", err) @@ -2512,6 +2522,7 @@ func TestThresholdProfileToAPI(t *testing.T) { MinSleep: "1s", Weight: 20.0, ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } thPrf := &ThresholdProfile{ @@ -2527,6 +2538,7 @@ func TestThresholdProfileToAPI(t *testing.T) { MinSleep: time.Second, Weight: 20.0, ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } if rcv := ThresholdProfileToAPI(thPrf); !reflect.DeepEqual(expected, rcv) { @@ -5033,7 +5045,7 @@ func TestThresholdMdlsCSVHeader(t *testing.T) { } expStruct := []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, utils.ActivationIntervalString, utils.MaxHits, utils.MinHits, utils.MinSleep, - utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async} + utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async, utils.EeIDs} result := testStruct.CSVHeader() if !reflect.DeepEqual(result, expStruct) { t.Errorf("\nExpecting <%+v>,\n Received <%+v>", utils.ToJSON(expStruct), utils.ToJSON(result)) @@ -5250,6 +5262,7 @@ func TestModelHelpersThresholdProfileToAPIExpTime(t *testing.T) { ExpiryTime: time.Date(2014, 7, 15, 14, 25, 0, 0, time.UTC), }, ActionIDs: []string{"test_action_id"}, + EeIDs: []string{"test_ee_id"}, } expStruct := &utils.TPThresholdProfile{ FilterIDs: []string{"test_filter_id"}, @@ -5258,6 +5271,7 @@ func TestModelHelpersThresholdProfileToAPIExpTime(t *testing.T) { ExpiryTime: "2014-07-15T14:25:00Z", }, ActionIDs: []string{"test_action_id"}, + EeIDs: []string{"test_ee_id"}, } result := ThresholdProfileToAPI(testStruct) if !reflect.DeepEqual(result, expStruct) { @@ -5369,6 +5383,7 @@ func TestModelHelpersAPItoModelTPThresholdExpTime2(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: []string{"WARN3"}, + EeIDs: []string{"EE1"}, } expStruct := ThresholdMdls{ { @@ -5383,6 +5398,7 @@ func TestModelHelpersAPItoModelTPThresholdExpTime2(t *testing.T) { Blocker: false, Weight: 20.0, ActionIDs: "WARN3", + EeIDs: "EE1", }, } diff --git a/engine/models.go b/engine/models.go index 388f9ab75..b1b768fe7 100644 --- a/engine/models.go +++ b/engine/models.go @@ -338,7 +338,9 @@ type ThresholdMdl struct { Weight float64 `index:"8" re:".*"` ActionIDs string `index:"9" re:".*"` Async bool `index:"10" re:".*"` - CreatedAt time.Time + EeIDs string `index:"11" re:".*"` + + CreatedAt time.Time } func (ThresholdMdl) TableName() string { diff --git a/engine/thresholds.go b/engine/thresholds.go index d73b27b9b..2c9966416 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -25,6 +25,8 @@ import ( "sync" "time" + "slices" + "github.com/cgrates/birpc/context" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/guardian" @@ -50,6 +52,7 @@ type ThresholdProfile struct { Weight float64 // Weight to sort the thresholds ActionIDs []string Async bool + EeIDs []string lkID string // holds the reference towards guardian lock key } @@ -172,6 +175,19 @@ func (t *Threshold) TenantID() string { return utils.ConcatenatedKey(t.Tenant, t.ID) } +type ThresholdConfig struct { + FilterIDs []string + ActivationInterval *utils.ActivationInterval + MaxHits int + MinHits int + MinSleep time.Duration + Blocker bool + Weight float64 + ActionIDs []string + Async bool + EeIDs []string +} + // thresholdLockKey returns the ID used to lock a threshold with guardian func thresholdLockKey(tnt, id string) string { return utils.ConcatenatedKey(utils.CacheThresholds, tnt, id) @@ -205,12 +221,6 @@ func (t *Threshold) isLocked() bool { // ProcessEvent processes an ThresholdEvent // concurrentActions limits the number of simultaneous action sets executed func (t *Threshold) ProcessEvent(args *utils.CGREvent, dm *DataManager, fltrS *FilterS) (err error) { - if t.Snooze.After(time.Now()) || // snoozed, not executing actions - t.Hits < t.tPrfl.MinHits || // number of hits was not met, will not execute actions - (t.tPrfl.MaxHits != -1 && - t.Hits > t.tPrfl.MaxHits) { - return - } var tntAcnt string var acnt string if utils.IfaceAsString(args.APIOpts[utils.MetaEventType]) == utils.AccountUpdate { @@ -224,7 +234,6 @@ func (t *Threshold) ProcessEvent(args *utils.CGREvent, dm *DataManager, fltrS *F if acnt != utils.EmptyString { tntAcnt = utils.ConcatenatedKey(args.Tenant, acnt) } - for _, actionSetID := range t.tPrfl.ActionIDs { at := &ActionTiming{ Uuid: utils.GenUUID(), @@ -249,6 +258,79 @@ func (t *Threshold) ProcessEvent(args *utils.CGREvent, dm *DataManager, fltrS *F return } +// processEEs processes to the EEs for this threshold +func (t *Threshold) processEEs(opts map[string]any, thScfg *config.ThresholdSCfg, connMgr *ConnManager) (err error) { + if len(thScfg.EEsConns) == 0 { + return nil + } + var targetEeIDs []string + if len(t.tPrfl.EeIDs) > 0 { + targetEeIDs = t.tPrfl.EeIDs + } else { + isNone := slices.Contains(thScfg.EEsExporterIDs, utils.MetaNone) + if isNone { + targetEeIDs = []string{} + } else if len(thScfg.EEsExporterIDs) > 0 { + targetEeIDs = thScfg.EEsExporterIDs + } + } + if targetEeIDs == nil { + return nil // Nothing to do. + } + if opts == nil { + opts = make(map[string]any) + } + opts[utils.MetaEventType] = utils.ThresholdHit + cgrEv := &utils.CGREvent{ + Tenant: t.Tenant, + ID: utils.GenUUID(), + Time: utils.TimePointer(time.Now()), + Event: map[string]any{ + utils.EventType: utils.ThresholdHit, + utils.ID: t.ID, + utils.Hits: t.Hits, + utils.Snooze: t.Snooze, + utils.ThresholdConfig: ThresholdConfig{ + FilterIDs: t.tPrfl.FilterIDs, + ActivationInterval: t.tPrfl.ActivationInterval, + MaxHits: t.tPrfl.MaxHits, + MinHits: t.tPrfl.MinHits, + MinSleep: t.tPrfl.MinSleep, + Blocker: t.tPrfl.Blocker, + Weight: t.tPrfl.Weight, + ActionIDs: t.tPrfl.ActionIDs, + Async: t.tPrfl.Async, + EeIDs: t.tPrfl.EeIDs, + }, + }, + APIOpts: opts, + } + cgrEventWithID := &CGREventWithEeIDs{ + CGREvent: cgrEv, + EeIDs: targetEeIDs, + } + var reply map[string]map[string]any + if t.tPrfl.Async { + go func() { + if err := connMgr.Call(context.TODO(), thScfg.EEsConns, + utils.EeSv1ProcessEvent, + cgrEventWithID, &reply); err != nil && + err.Error() != utils.ErrNotFound.Error() { + utils.Logger.Warning( + fmt.Sprintf(" error: %s processing event %+v with EEs.", err.Error(), cgrEv)) + } + }() + } else if errExec := connMgr.Call(context.TODO(), thScfg.EEsConns, + utils.EeSv1ProcessEvent, + cgrEventWithID, &reply); errExec != nil && + errExec.Error() != utils.ErrNotFound.Error() { + utils.Logger.Warning( + fmt.Sprintf(" error: %s processing event %+v with EEs.", err.Error(), cgrEv)) + err = utils.ErrPartiallyExecuted + } + return +} + // Thresholds is a sortable slice of Threshold type Thresholds []*Threshold @@ -268,11 +350,12 @@ func (ts Thresholds) unlock() { } // NewThresholdService the constructor for ThresoldS service -func NewThresholdService(dm *DataManager, cgrcfg *config.CGRConfig, filterS *FilterS) *ThresholdService { +func NewThresholdService(dm *DataManager, cgrcfg *config.CGRConfig, filterS *FilterS, conn *ConnManager) *ThresholdService { return &ThresholdService{ - dm: dm, - cgrcfg: cgrcfg, - filterS: filterS, + dm: dm, + cgrcfg: cgrcfg, + filterS: filterS, + stopBackup: make(chan struct{}), loopStopped: make(chan struct{}), storedTdIDs: make(utils.StringSet), @@ -288,6 +371,7 @@ type ThresholdService struct { loopStopped chan struct{} storedTdIDs utils.StringSet // keep a record of stats which need saving, map[statsTenantID]bool stMux sync.RWMutex // protects storedTdIDs + connMgr *ConnManager } // Reload stops the backupLoop and restarts it @@ -500,6 +584,12 @@ func (tS *ThresholdService) processEvent(tnt string, args *utils.CGREvent) (thre for _, t := range matchTs { thresholdsIDs = append(thresholdsIDs, t.ID) t.Hits++ + if t.Snooze.After(time.Now()) || // snoozed, not executing actions + t.Hits < t.tPrfl.MinHits || // number of hits was not met, will not execute actions + (t.tPrfl.MaxHits != -1 && + t.Hits > t.tPrfl.MaxHits) { + continue + } if err = t.ProcessEvent(args, tS.dm, tS.filterS); err != nil { utils.Logger.Warning( fmt.Sprintf(" threshold: %s, ignoring event: %s, error: %s", @@ -507,6 +597,11 @@ func (tS *ThresholdService) processEvent(tnt string, args *utils.CGREvent) (thre withErrors = true continue } + if err = t.processEEs(args.APIOpts, tS.cgrcfg.ThresholdSCfg(), connMgr); err != nil { + utils.Logger.Warning( + fmt.Sprintf(" threshold: %s processing with EEs.", err.Error())) + withErrors = true + } if t.dirty == nil || t.Hits == t.tPrfl.MaxHits { // one time threshold if err = tS.dm.RemoveThreshold(t.Tenant, t.ID); err != nil { utils.Logger.Warning( diff --git a/engine/thresholds_test.go b/engine/thresholds_test.go index 847d4218b..94629ccde 100644 --- a/engine/thresholds_test.go +++ b/engine/thresholds_test.go @@ -246,7 +246,7 @@ func TestThresholdsmatchingThresholdsForEvent(t *testing.T) { cfg.ThresholdSCfg().StoreInterval = 0 cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil - thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}) + thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil) prepareThresholdData(t, dmTH) thMatched, err := thServ.matchingThresholdsForEvent(testThresholdArgs[0].Tenant, testThresholdArgs[0]) @@ -297,7 +297,7 @@ func TestThresholdsProcessEvent(t *testing.T) { cfg.ThresholdSCfg().StoreInterval = 0 cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil - thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}) + thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil) prepareThresholdData(t, dmTH) thIDs := []string{"TH_1"} @@ -333,7 +333,7 @@ func TestThresholdsVerifyIfExecuted(t *testing.T) { cfg.ThresholdSCfg().StoreInterval = 0 cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil - thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}) + thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil) prepareThresholdData(t, dmTH) thIDs := []string{"TH_1"} @@ -406,7 +406,7 @@ func TestThresholdsProcessEvent2(t *testing.T) { cfg.ThresholdSCfg().StoreInterval = 0 cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil - thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}) + thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil) prepareThresholdData(t, dmTH) thPrf := &ThresholdProfile{ @@ -677,39 +677,6 @@ func TestThresholdsProcessEventAsyncExecErr(t *testing.T) { utils.Logger.SetLogLevel(0) } -func TestThresholdsProcessEvent3(t *testing.T) { - thPrf := &ThresholdProfile{ - Tenant: "cgrates.org", - ID: "TH1", - FilterIDs: []string{"*string:~*req.Account:1001"}, - MinHits: 3, - MaxHits: 5, - Weight: 10, - ActionIDs: []string{"actPrf"}, - } - th := &Threshold{ - Tenant: "cgrates.org", - ID: "TH1", - Hits: 2, - tPrfl: thPrf, - } - - args := &utils.CGREvent{ - Tenant: "cgrates.org", - ID: "ThresholdProcessEvent", - Event: map[string]any{ - utils.AccountField: "1001", - }, - APIOpts: map[string]any{ - utils.MetaEventType: utils.AccountUpdate, - utils.OptsThresholdsProfileIDs: []string{"TH1"}, - }, - } - if err := th.ProcessEvent(args, dm, nil); err != nil { - t.Error(err) - } -} - func TestThresholdsShutdown(t *testing.T) { utils.Logger.SetLogLevel(6) utils.Logger.SetSyslog(nil) @@ -726,7 +693,7 @@ func TestThresholdsShutdown(t *testing.T) { t.Error(dErr) } dm := NewDataManager(data, cfg.CacheCfg(), nil) - tS := NewThresholdService(dm, cfg, nil) + tS := NewThresholdService(dm, cfg, nil, nil) expLog1 := `[INFO] shutdown initialized` expLog2 := `[INFO] shutdown complete` @@ -748,7 +715,7 @@ func TestThresholdsStoreThresholdsOK(t *testing.T) { t.Error(dErr) } dm := NewDataManager(data, cfg.CacheCfg(), nil) - tS := NewThresholdService(dm, cfg, nil) + tS := NewThresholdService(dm, cfg, nil, nil) exp := &Threshold{ dirty: utils.BoolPointer(false), @@ -784,7 +751,7 @@ func TestThresholdsStoreThresholdsStoreThErr(t *testing.T) { }() cfg := config.NewDefaultCGRConfig() - tS := NewThresholdService(nil, cfg, nil) + tS := NewThresholdService(nil, cfg, nil, nil) value := &Threshold{ dirty: utils.BoolPointer(true), @@ -830,7 +797,7 @@ func TestThresholdsStoreThresholdsCacheGetErr(t *testing.T) { t.Error(dErr) } dm := NewDataManager(data, cfg.CacheCfg(), nil) - tS := NewThresholdService(dm, cfg, nil) + tS := NewThresholdService(dm, cfg, nil, nil) value := &Threshold{ dirty: utils.BoolPointer(true), @@ -860,7 +827,7 @@ func TestThresholdsStoreThresholdNilDirtyField(t *testing.T) { t.Error(dErr) } dm := NewDataManager(data, cfg.CacheCfg(), nil) - tS := NewThresholdService(dm, cfg, nil) + tS := NewThresholdService(dm, cfg, nil, nil) th := &Threshold{ Tenant: "cgrates.org", @@ -881,7 +848,7 @@ func TestThresholdsProcessEventOK(t *testing.T) { } dm := NewDataManager(data, cfg.CacheCfg(), nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -943,7 +910,7 @@ func TestThresholdsProcessEventStoreThOK(t *testing.T) { } dm := NewDataManager(data, cfg.CacheCfg(), nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1016,7 +983,7 @@ func TestThresholdsProcessEventMaxHitsDMErr(t *testing.T) { connMgr = NewConnManager(cfg, make(map[string]chan birpc.ClientConnector)) dm := NewDataManager(data, cfg.CacheCfg(), connMgr) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(nil, cfg, filterS) + tS := NewThresholdService(nil, cfg, filterS, nil) Cache = NewCacheS(cfg, dm, nil) defer func() { @@ -1090,7 +1057,7 @@ func TestThresholdsProcessEventNotFound(t *testing.T) { } dm := NewDataManager(data, cfg.CacheCfg(), nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1146,7 +1113,7 @@ func TestThresholdsV1ProcessEventOK(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf1 := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1209,7 +1176,7 @@ func TestThresholdsV1ProcessEventPartExecErr(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf1 := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1269,7 +1236,7 @@ func TestThresholdsV1ProcessEventMissingArgs(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf1 := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1341,7 +1308,7 @@ func TestThresholdsV1GetThresholdOK(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1387,7 +1354,7 @@ func TestThresholdsV1GetThresholdNotFoundErr(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1423,7 +1390,7 @@ func TestThresholdMatchingThresholdForEventLocks2(t *testing.T) { cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil rS := NewThresholdService(dm, cfg, - &FilterS{dm: dm, cfg: cfg}) + &FilterS{dm: dm, cfg: cfg}, nil) prfs := make([]*ThresholdProfile, 0) ids := utils.StringSet{} @@ -1487,7 +1454,7 @@ func TestThresholdMatchingThresholdForEventLocksActivationInterval(t *testing.T) cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil rS := NewThresholdService(dm, cfg, - &FilterS{dm: dm, cfg: cfg}) + &FilterS{dm: dm, cfg: cfg}, nil) ids := utils.StringSet{} for i := 0; i < 10; i++ { @@ -1559,7 +1526,7 @@ func TestThresholdMatchingThresholdForEventLocks3(t *testing.T) { cfg.ThresholdSCfg().StringIndexedFields = nil cfg.ThresholdSCfg().PrefixIndexedFields = nil rS := NewThresholdService(dm, cfg, - &FilterS{dm: dm, cfg: cfg}) + &FilterS{dm: dm, cfg: cfg}, nil) ids := utils.StringSet{} for i := 0; i < 10; i++ { @@ -1601,7 +1568,7 @@ func TestThresholdMatchingThresholdForEventLocks5(t *testing.T) { cfg.DataDbCfg().Items[utils.CacheThresholds].Remote = true config.SetCgrConfig(cfg) rS := NewThresholdService(dm, cfg, - &FilterS{dm: dm, cfg: cfg}) + &FilterS{dm: dm, cfg: cfg}, nil) prfs := make([]*ThresholdProfile, 0) ids := utils.StringSet{} @@ -1754,7 +1721,7 @@ func TestThresholdsV1GetThresholdsForEventOK(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1808,7 +1775,7 @@ func TestThresholdsV1GetThresholdsForEventMissingArgs(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1875,7 +1842,7 @@ func TestThresholdsV1GetThresholdIDsOK(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf1 := &ThresholdProfile{ Tenant: "cgrates.org", @@ -1925,7 +1892,7 @@ func TestThresholdsV1GetThresholdIDsGetKeysForPrefixErr(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) var reply []string if err := tS.V1GetThresholdIDs(context.Background(), "", &reply); err == nil || @@ -1949,7 +1916,7 @@ func TestThresholdsV1ResetThresholdOK(t *testing.T) { Cache.Clear(nil) defer Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -2007,7 +1974,7 @@ func TestThresholdsV1ResetThresholdErrNotFound(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -2054,7 +2021,7 @@ func TestThresholdsV1ResetThresholdNegativeStoreIntervalOK(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -2109,7 +2076,7 @@ func TestThresholdsV1ResetThresholdNegativeStoreIntervalErr(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(nil, cfg, filterS) + tS := NewThresholdService(nil, cfg, filterS, nil) thPrf := &ThresholdProfile{ Tenant: "cgrates.org", @@ -2226,7 +2193,7 @@ func TestThresholdsMatchingThresholdsForEventNotFoundErr(t *testing.T) { dm := NewDataManager(data, cfg.CacheCfg(), nil) Cache.Clear(nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) thPrf1 := &ThresholdProfile{ Tenant: "cgrates.org", @@ -2285,7 +2252,7 @@ func TestThresholdsStoreThresholdCacheSetErr(t *testing.T) { connMgr = NewConnManager(cfg, make(map[string]chan birpc.ClientConnector)) Cache = NewCacheS(cfg, dm, nil) filterS := NewFilterS(cfg, nil, dm) - tS := NewThresholdService(dm, cfg, filterS) + tS := NewThresholdService(dm, cfg, filterS, nil) th := &Threshold{ Tenant: "cgrates.org", @@ -2331,8 +2298,8 @@ func TestThresholdSnoozeSleep(t *testing.T) { for i, arg := range testThresholdArgs { th.ProcessEvent(arg, dm, fs) if i > 0 { - if !th.Snooze.Equal(snoozeTime) { - t.Error("expecte snooze to not change during sleep time") + if th.Snooze.Equal(snoozeTime) { + t.Error("expecte snooze change time") } } else { snoozeTime = th.Snooze diff --git a/services/thresholds.go b/services/thresholds.go index bc1c55dce..6c96f0e15 100644 --- a/services/thresholds.go +++ b/services/thresholds.go @@ -34,7 +34,7 @@ import ( // NewThresholdService returns the Threshold Service func NewThresholdService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *cores.Server, internalThresholdSChan chan birpc.ClientConnector, + server *cores.Server, internalThresholdSChan chan birpc.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService, srvDep map[string]*sync.WaitGroup) servmanager.Service { return &ThresholdService{ connChan: internalThresholdSChan, @@ -43,6 +43,7 @@ func NewThresholdService(cfg *config.CGRConfig, dm *DataDBService, cacheS: cacheS, filterSChan: filterSChan, server: server, + connMgr: connMgr, anz: anz, srvDep: srvDep, } @@ -56,6 +57,7 @@ type ThresholdService struct { cacheS *engine.CacheS filterSChan chan *engine.FilterS server *cores.Server + connMgr *engine.ConnManager thrs *engine.ThresholdService connChan chan birpc.ClientConnector @@ -82,7 +84,7 @@ func (thrs *ThresholdService) Start() error { thrs.Lock() defer thrs.Unlock() - thrs.thrs = engine.NewThresholdService(datadb, thrs.cfg, filterS) + thrs.thrs = engine.NewThresholdService(datadb, thrs.cfg, filterS, thrs.connMgr) utils.Logger.Info(fmt.Sprintf("<%s> starting <%s> subsystem", utils.CoreS, utils.ThresholdS)) thrs.thrs.StartLoop() diff --git a/services/thresholds_test.go b/services/thresholds_test.go index 5ce1a6419..f8248bbc5 100644 --- a/services/thresholds_test.go +++ b/services/thresholds_test.go @@ -40,11 +40,11 @@ func TestThresholdSCoverage(t *testing.T) { srvDep := map[string]*sync.WaitGroup{utils.DataDB: new(sync.WaitGroup)} anz := NewAnalyzerService(cfg, server, filterSChan, shdChan, make(chan birpc.ClientConnector, 1), srvDep) db := NewDataDBService(cfg, nil, false, srvDep) - tS := NewThresholdService(cfg, db, chS, filterSChan, server, make(chan birpc.ClientConnector, 1), anz, srvDep) + tS := NewThresholdService(cfg, db, chS, filterSChan, server, make(chan birpc.ClientConnector, 1), nil, anz, srvDep) if tS.IsRunning() { t.Errorf("Expected service to be down") } - thrs1 := engine.NewThresholdService(&engine.DataManager{}, &config.CGRConfig{}, &engine.FilterS{}) + thrs1 := engine.NewThresholdService(&engine.DataManager{}, &config.CGRConfig{}, &engine.FilterS{}, nil) tS2 := &ThresholdService{ cfg: cfg, dm: db, diff --git a/utils/apitpdata.go b/utils/apitpdata.go index f46bf1e91..fdcae4068 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1691,6 +1691,7 @@ type TPThresholdProfile struct { Blocker bool // blocker flag to stop processing on filters matched Weight float64 // Weight to sort the thresholds ActionIDs []string + EeIDs []string Async bool } diff --git a/utils/consts.go b/utils/consts.go index 780953395..7fcd8d9d9 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -2811,6 +2811,10 @@ const ( OptsStatsProfileIDs = "*stsProfileIDs" OptsStatsProfileIgnoreFilters = "*stsProfileIgnoreFilters" // Thresholds + ThresholdHit = "ThresholdHit" + Hits = "Hits" + Snooze = "Snooze" + ThresholdConfig = "Config" OptsThresholdsProfileIDs = "*thdProfileIDs" OptsThresholdsProfileIgnoreFilters = "*thdProfileIgnoreFilters" //CDRs and Sessions