diff --git a/config/attributescfg.go b/config/attributescfg.go index 2032569d4..192679c5b 100644 --- a/config/attributescfg.go +++ b/config/attributescfg.go @@ -42,6 +42,7 @@ type AttributeSCfg struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string NestedFields bool AnyContext bool Opts *AttributesOpts @@ -123,6 +124,10 @@ func (alS *AttributeSCfg) loadFromJSONCfg(jsnCfg *AttributeSJsonCfg) (err error) copy(sif, *jsnCfg.Suffix_indexed_fields) alS.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + alS.ExistsIndexedFields = &eif + } if jsnCfg.Nested_fields != nil { alS.NestedFields = *jsnCfg.Nested_fields } @@ -168,6 +173,10 @@ func (alS *AttributeSCfg) AsMapInterface() (initialMP map[string]any) { copy(suffixIndexedFields, *alS.SuffixIndexedFields) initialMP[utils.SuffixIndexedFieldsCfg] = suffixIndexedFields } + if alS.ExistsIndexedFields != nil { + eif := slices.Clone(*alS.ExistsIndexedFields) + initialMP[utils.ExistsIndexedFieldsCfg] = eif + } if alS.StatSConns != nil { statSConns := make([]string, len(alS.StatSConns)) for i, item := range alS.StatSConns { @@ -253,5 +262,9 @@ func (alS AttributeSCfg) Clone() (cln *AttributeSCfg) { copy(idx, *alS.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if alS.ExistsIndexedFields != nil { + idx := slices.Clone(*alS.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/attributescfg_test.go b/config/attributescfg_test.go index bcc575ddb..44ff5eb5a 100644 --- a/config/attributescfg_test.go +++ b/config/attributescfg_test.go @@ -35,6 +35,7 @@ func TestAttributeSCfgloadFromJsonCfg(t *testing.T) { String_indexed_fields: &[]string{"*req.index1"}, Prefix_indexed_fields: &[]string{"*req.index1", "*req.index2"}, Suffix_indexed_fields: &[]string{"*req.index1"}, + ExistsIndexedFields: &[]string{"*req.index1"}, Nested_fields: utils.BoolPointer(true), Any_context: utils.BoolPointer(true), Opts: &AttributesOptsJson{ @@ -51,6 +52,7 @@ func TestAttributeSCfgloadFromJsonCfg(t *testing.T) { StringIndexedFields: &[]string{"*req.index1"}, PrefixIndexedFields: &[]string{"*req.index1", "*req.index2"}, SuffixIndexedFields: &[]string{"*req.index1"}, + ExistsIndexedFields: &[]string{"*req.index1"}, NestedFields: true, AnyContext: true, Opts: &AttributesOpts{ @@ -80,7 +82,8 @@ func TestAttributeSCfgAsMapInterface(t *testing.T) { "stats_conns": ["*internal"], "resources_conns": ["*internal"], "apiers_conns": ["*internal"], - "prefix_indexed_fields": ["*req.index1","*req.index2"], + "prefix_indexed_fields": ["*req.index1","*req.index2"], + "exists_indexed_fields": ["*req.index1","*req.index2"], "string_indexed_fields": ["*req.index1"], "opts": { "*processRuns": 3, @@ -95,6 +98,7 @@ func TestAttributeSCfgAsMapInterface(t *testing.T) { utils.ApierSConnsCfg: []string{utils.MetaInternal}, utils.StringIndexedFieldsCfg: []string{"*req.index1"}, utils.PrefixIndexedFieldsCfg: []string{"*req.index1", "*req.index2"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.index1", "*req.index2"}, utils.IndexedSelectsCfg: true, utils.NestedFieldsCfg: false, utils.SuffixIndexedFieldsCfg: []string{}, @@ -118,6 +122,7 @@ func TestAttributeSCfgAsMapInterface2(t *testing.T) { cfgJSONStr := `{ "attributes": { "suffix_indexed_fields": ["*req.index1","*req.index2"], + "exists_indexed_fields": ["*req.index1","*req.index2"], "nested_fields": true, "enabled": true, "opts": { @@ -133,6 +138,7 @@ func TestAttributeSCfgAsMapInterface2(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{"*req.index1", "*req.index2"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.index1", "*req.index2"}, utils.NestedFieldsCfg: true, utils.AnyContextCfg: true, utils.OptsCfg: map[string]any{ @@ -163,6 +169,7 @@ func TestAttributeSCfgAsMapInterface3(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.AnyContextCfg: true, utils.OptsCfg: map[string]any{ diff --git a/config/chargerscfg.go b/config/chargerscfg.go index 77c0dcb5c..f3510c539 100644 --- a/config/chargerscfg.go +++ b/config/chargerscfg.go @@ -19,6 +19,8 @@ along with this program. If not, see package config import ( + "slices" + "github.com/cgrates/cgrates/utils" ) @@ -30,6 +32,7 @@ type ChargerSCfg struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string NestedFields bool } @@ -68,6 +71,10 @@ func (cS *ChargerSCfg) loadFromJSONCfg(jsnCfg *ChargerSJsonCfg) (err error) { copy(sif, *jsnCfg.Suffix_indexed_fields) cS.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + cS.ExistsIndexedFields = &eif + } if jsnCfg.Nested_fields != nil { cS.NestedFields = *jsnCfg.Nested_fields } @@ -106,6 +113,10 @@ func (cS *ChargerSCfg) AsMapInterface() (initialMP map[string]any) { copy(sufixIndexedFields, *cS.SuffixIndexedFields) initialMP[utils.SuffixIndexedFieldsCfg] = sufixIndexedFields } + if cS.ExistsIndexedFields != nil { + eif := slices.Clone(*cS.ExistsIndexedFields) + initialMP[utils.ExistsIndexedFieldsCfg] = eif + } return } @@ -136,5 +147,9 @@ func (cS ChargerSCfg) Clone() (cln *ChargerSCfg) { copy(idx, *cS.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if cS.ExistsIndexedFields != nil { + idx := slices.Clone(*cS.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/chargerscfg_test.go b/config/chargerscfg_test.go index 57beefac3..9b205897a 100644 --- a/config/chargerscfg_test.go +++ b/config/chargerscfg_test.go @@ -32,6 +32,7 @@ func TestChargerSCfgloadFromJsonCfg(t *testing.T) { String_indexed_fields: &[]string{"*req.Field1"}, Prefix_indexed_fields: &[]string{"*req.Field1", "*req.Field2"}, Suffix_indexed_fields: &[]string{"*req.Field1", "*req.Field2"}, + ExistsIndexedFields: &[]string{"*req.Field1", "*req.Field2"}, Nested_fields: utils.BoolPointer(true), } expected := &ChargerSCfg{ @@ -41,6 +42,7 @@ func TestChargerSCfgloadFromJsonCfg(t *testing.T) { StringIndexedFields: &[]string{"*req.Field1"}, PrefixIndexedFields: &[]string{"*req.Field1", "*req.Field2"}, SuffixIndexedFields: &[]string{"*req.Field1", "*req.Field2"}, + ExistsIndexedFields: &[]string{"*req.Field1", "*req.Field2"}, NestedFields: true, } jsncfg := NewDefaultCGRConfig() @@ -68,6 +70,7 @@ func TestChargerSCfgAsMapInterface(t *testing.T) { utils.PrefixIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { t.Error(err) @@ -83,8 +86,9 @@ func TestChargerSCfgAsMapInterface1(t *testing.T) { "attributes_conns": ["*internal:*attributes", "*conn1"], "indexed_selects":true, "string_indexed_fields": ["*req.Field1","*req.Field2","*req.Field3"], - "prefix_indexed_fields": ["*req.DestinationPrefix"], - "suffix_indexed_fields": ["*req.Field1","*req.Field2","*req.Field3"], + "prefix_indexed_fields": ["*req.DestinationPrefix"], + "suffix_indexed_fields": ["*req.Field1","*req.Field2","*req.Field3"], + "exists_indexed_fields": ["*req.Field1","*req.Field2","*req.Field3"], "nested_fields": false, }, }` @@ -96,6 +100,7 @@ func TestChargerSCfgAsMapInterface1(t *testing.T) { utils.PrefixIndexedFieldsCfg: []string{"*req.DestinationPrefix"}, utils.NestedFieldsCfg: false, utils.SuffixIndexedFieldsCfg: []string{"*req.Field1", "*req.Field2", "*req.Field3"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.Field1", "*req.Field2", "*req.Field3"}, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { t.Error(err) diff --git a/config/config_defaults.go b/config/config_defaults.go index 7e4bdab6a..f476e8a41 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -836,6 +836,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) "any_context": true, // if we match the *any context "opts": { @@ -854,6 +855,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) }, @@ -866,6 +868,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) "opts": { "*usageID": "", @@ -886,6 +889,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) "opts": { "*profileIDs": [], @@ -925,6 +929,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) "opts": { "*profileIDs": [], @@ -939,6 +944,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) "attributes_conns": [], // connections to AttributeS for altering events before route queries: <""|*internal|$rpc_conns_id> "resources_conns": [], // connections to ResourceS for *res sorting, empty to disable functionality: <""|*internal|$rpc_conns_id> @@ -1224,6 +1230,7 @@ const CGRATES_CFG_JSON = ` //"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 + "exists_indexed_fields": [], // query indexes based on these fields for faster processing "nested_fields": false, // determines which field is checked when matching indexed filters(true: all; false: only the one on the first level) "attributes_conns": [], // connections to AttributeS for API authorization, empty to disable auth functionality: <""|*internal|$rpc_conns_id> "any_subsystem": true, // if we match the *any subsystem diff --git a/config/config_it_test.go b/config/config_it_test.go index cc0349742..b68457356 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -155,6 +155,7 @@ func testCGRConfigReloadAttributeS(t *testing.T) { StringIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.AccountField}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, IndexedSelects: true, AnyContext: true, Opts: &AttributesOpts{ @@ -210,6 +211,7 @@ func testCGRConfigReloadChargerS(t *testing.T) { StringIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.AccountField}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, IndexedSelects: true, AttributeSConns: []string{"*localhost"}, } @@ -238,6 +240,7 @@ func testCGRConfigReloadThresholdS(t *testing.T) { StringIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.AccountField}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, IndexedSelects: true, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, @@ -268,6 +271,7 @@ func testCGRConfigReloadStatS(t *testing.T) { StringIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.AccountField}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, IndexedSelects: true, ThresholdSConns: []string{utils.MetaLocalHost}, Opts: &StatsOpts{ @@ -300,6 +304,7 @@ func testCGRConfigReloadResourceS(t *testing.T) { StringIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.AccountField}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, IndexedSelects: true, ThresholdSConns: []string{utils.MetaLocalHost}, Opts: &ResourcesOpts{ @@ -332,6 +337,7 @@ func testCGRConfigReloadSupplierS(t *testing.T) { StringIndexedFields: &[]string{"*req.LCRProfile"}, PrefixIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.Destination}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, ResourceSConns: []string{}, StatSConns: []string{}, AttributeSConns: []string{}, diff --git a/config/config_json_test.go b/config/config_json_test.go index a80cc7210..6935daa59 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -1141,6 +1141,7 @@ func TestDfAttributeServJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Nested_fields: utils.BoolPointer(false), Any_context: utils.BoolPointer(true), Opts: &AttributesOptsJson{ @@ -1169,6 +1170,7 @@ func TestDfChargerServJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Nested_fields: utils.BoolPointer(false), } dfCgrJSONCfg, err := NewCgrJsonCfgFromBytes([]byte(CGRATES_CFG_JSON)) @@ -1210,6 +1212,7 @@ func TestDfResourceLimiterSJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Nested_fields: utils.BoolPointer(false), Opts: &ResourcesOptsJson{ UsageID: utils.StringPointer(utils.EmptyString), @@ -1237,6 +1240,7 @@ func TestDfStatServiceJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Nested_fields: utils.BoolPointer(false), Ees_conns: &[]string{}, Ees_exporter_ids: &[]string{}, @@ -1265,6 +1269,7 @@ func TestDfThresholdSJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Nested_fields: utils.BoolPointer(false), Opts: &ThresholdsOptsJson{ ProfileIDs: &[]string{}, @@ -1289,6 +1294,7 @@ func TestDfRouteSJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Attributes_conns: &[]string{}, Resources_conns: &[]string{}, Stats_conns: &[]string{}, @@ -1930,6 +1936,7 @@ func TestDfDispatcherSJsonCfg(t *testing.T) { String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, + ExistsIndexedFields: &[]string{}, Attributes_conns: &[]string{}, Nested_fields: utils.BoolPointer(false), Any_subsystem: utils.BoolPointer(true), diff --git a/config/config_test.go b/config/config_test.go index a13a03d07..3cfff3e27 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -717,6 +717,7 @@ func TestCgrCfgJSONDefaultSChargerSCfg(t *testing.T) { StringIndexedFields: nil, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, } if !reflect.DeepEqual(eChargerSCfg, cgrCfg.chargerSCfg) { t.Errorf("received: %+v, expecting: %+v", eChargerSCfg, cgrCfg.chargerSCfg) @@ -732,6 +733,7 @@ func TestCgrCfgJSONDefaultsResLimCfg(t *testing.T) { StringIndexedFields: nil, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, Opts: &ResourcesOpts{ UsageID: utils.EmptyString, Units: 1, @@ -752,6 +754,7 @@ func TestCgrCfgJSONDefaultStatsCfg(t *testing.T) { StringIndexedFields: nil, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, Opts: &StatsOpts{ ProfileIDs: []string{}, }, @@ -770,6 +773,7 @@ func TestCgrCfgJSONDefaultThresholdSCfg(t *testing.T) { StringIndexedFields: nil, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, }, @@ -786,6 +790,7 @@ func TestCgrCfgJSONDefaultRouteSCfg(t *testing.T) { StringIndexedFields: nil, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, AttributeSConns: []string{}, ResourceSConns: []string{}, StatSConns: []string{}, @@ -1832,6 +1837,7 @@ func TestAttributeSConfig(t *testing.T) { IndexedSelects: true, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, NestedFields: false, AnyContext: true, Opts: &AttributesOpts{ @@ -1853,6 +1859,7 @@ func TestChargersConfig(t *testing.T) { AttributeSConns: []string{}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, NestedFields: false, } cgrConfig := NewDefaultCGRConfig() @@ -1870,6 +1877,7 @@ func TestResourceSConfig(t *testing.T) { ThresholdSConns: []string{}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, NestedFields: false, Opts: &ResourcesOpts{ UsageID: "", @@ -1892,6 +1900,7 @@ func TestStatSConfig(t *testing.T) { ThresholdSConns: []string{}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, NestedFields: false, Opts: &StatsOpts{ ProfileIDs: []string{}, @@ -1912,6 +1921,7 @@ func TestThresholdSConfig(t *testing.T) { StoreInterval: 0, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, NestedFields: false, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, @@ -1930,6 +1940,7 @@ func TestRouteSConfig(t *testing.T) { IndexedSelects: true, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, AttributeSConns: []string{}, ResourceSConns: []string{}, StatSConns: []string{}, @@ -2102,6 +2113,7 @@ func TestDispatcherSConfig(t *testing.T) { IndexedSelects: true, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, AttributeSConns: []string{}, NestedFields: false, AnySubsystem: true, @@ -3123,6 +3135,7 @@ func TestCgrCfgJSONDefaultDispatcherSCfg(t *testing.T) { StringIndexedFields: nil, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, + ExistsIndexedFields: &[]string{}, AttributeSConns: []string{}, AnySubsystem: true, } @@ -3950,6 +3963,7 @@ func TestV1GetConfigAttribute(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.AnyContextCfg: true, utils.OptsCfg: map[string]any{ @@ -3978,6 +3992,7 @@ func TestV1GetConfigChargers(t *testing.T) { utils.PrefixIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, }, } cfgCgr := NewDefaultCGRConfig() @@ -3998,6 +4013,7 @@ func TestV1GetConfigResourceS(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaUnitsCfg: 1., @@ -4024,6 +4040,7 @@ func TestV1GetConfigStats(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, @@ -4050,6 +4067,7 @@ func TestV1GetConfigThresholds(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, @@ -4073,6 +4091,7 @@ func TestV1GetConfigRoutes(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.AttributeSConnsCfg: []string{}, utils.ResourceSConnsCfg: []string{}, @@ -4143,6 +4162,7 @@ func TestV1GetConfigDispatcherS(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.AttributeSConnsCfg: []string{}, utils.AnySubsystemCfg: true, @@ -4939,7 +4959,7 @@ func TestV1GetConfigAsJSONDNSAgent(t *testing.T) { func TestV1GetConfigAsJSONAttributes(t *testing.T) { var reply string - expected := `{"attributes":{"any_context":true,"apiers_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*processRuns":1,"*profileIDs":[],"*profileIgnoreFilters":false,"*profileRuns":0},"prefix_indexed_fields":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]}}` + expected := `{"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":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: ATTRIBUTE_JSN}, &reply); err != nil { t.Error(err) @@ -4950,7 +4970,7 @@ func TestV1GetConfigAsJSONAttributes(t *testing.T) { func TestV1GetConfigAsJSONChargerS(t *testing.T) { var reply string - expected := `{"chargers":{"attributes_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"suffix_indexed_fields":[]}}` + expected := `{"chargers":{"attributes_conns":[],"enabled":false,"exists_indexed_fields":[],"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"suffix_indexed_fields":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: ChargerSCfgJson}, &reply); err != nil { t.Error(err) @@ -4961,7 +4981,7 @@ func TestV1GetConfigAsJSONChargerS(t *testing.T) { func TestV1GetConfigAsJSONResourceS(t *testing.T) { var reply string - expected := `{"resources":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*units":1,"*usageID":""},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[],"thresholds_conns":[]}}` + expected := `{"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":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: RESOURCES_JSON}, &reply); err != nil { t.Error(err) @@ -4972,7 +4992,7 @@ func TestV1GetConfigAsJSONResourceS(t *testing.T) { func TestV1GetConfigAsJSONStatS(t *testing.T) { var reply string - expected := `{"stats":{"ees_conns":[],"ees_exporter_ids":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","store_uncompressed_limit":0,"suffix_indexed_fields":[],"thresholds_conns":[]}}` + expected := `{"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":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: STATS_JSON}, &reply); err != nil { t.Error(err) @@ -4983,7 +5003,7 @@ func TestV1GetConfigAsJSONStatS(t *testing.T) { func TestV1GetConfigAsJSONThresholdS(t *testing.T) { var reply string - expected := `{"thresholds":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]}}` + 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":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: THRESHOLDS_JSON}, &reply); err != nil { t.Error(err) @@ -4994,7 +5014,7 @@ func TestV1GetConfigAsJSONThresholdS(t *testing.T) { func TestV1GetConfigAsJSONRouteS(t *testing.T) { var reply string - expected := `{"routes":{"attributes_conns":[],"default_ratio":1,"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*context":"*routes","*ignoreErrors":false,"*maxCost":""},"prefix_indexed_fields":[],"rals_conns":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]}}` + expected := `{"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":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: RouteSJson}, &reply); err != nil { t.Error(err) @@ -5018,7 +5038,7 @@ func TestV1GetConfigAsJSONSureTax(t *testing.T) { func TestV1GetConfigAsJSONDispatcherS(t *testing.T) { var reply string - expected := `{"dispatchers":{"any_subsystem":true,"attributes_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"prevent_loop":false,"suffix_indexed_fields":[]}}` + expected := `{"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":[]}}` cgrCfg := NewDefaultCGRConfig() if err := cgrCfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: DispatcherSJson}, &reply); err != nil { t.Error(err) @@ -5275,7 +5295,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,"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,"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":0,"internalDBDumpPath":"/var/lib/cgrates/internal_db/datadb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":0,"internalDBStartTimeout":300000000000,"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_filtered":false},"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,"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,"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,"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,"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":0,"internalDBDumpPath":"/var/lib/cgrates/internal_db/stordb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":0,"internalDBStartTimeout":300000000000,"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,"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":0,"internalDBDumpPath":"/var/lib/cgrates/internal_db/datadb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":0,"internalDBStartTimeout":300000000000,"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_filtered":false},"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":0,"internalDBDumpPath":"/var/lib/cgrates/internal_db/stordb","internalDBFileSizeLimit":1073741824,"internalDBRewriteInterval":0,"internalDBStartTimeout":300000000000,"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":[]}}` if err != nil { t.Fatal(err) } diff --git a/config/dispatcherscfg.go b/config/dispatcherscfg.go index 6fbd45b44..ef3c310ee 100644 --- a/config/dispatcherscfg.go +++ b/config/dispatcherscfg.go @@ -19,6 +19,8 @@ along with this program. If not, see package config import ( + "slices" + "github.com/cgrates/cgrates/utils" ) @@ -29,6 +31,7 @@ type DispatcherSCfg struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string AttributeSConns []string NestedFields bool AnySubsystem bool @@ -60,6 +63,10 @@ func (dps *DispatcherSCfg) loadFromJSONCfg(jsnCfg *DispatcherSJsonCfg) (err erro copy(sif, *jsnCfg.Suffix_indexed_fields) dps.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + dps.ExistsIndexedFields = &eif + } if jsnCfg.Attributes_conns != nil { dps.AttributeSConns = make([]string, len(*jsnCfg.Attributes_conns)) for idx, connID := range *jsnCfg.Attributes_conns { @@ -106,6 +113,10 @@ func (dps *DispatcherSCfg) AsMapInterface() (mp map[string]any) { copy(suffixIndexedFields, *dps.SuffixIndexedFields) mp[utils.SuffixIndexedFieldsCfg] = suffixIndexedFields } + if dps.ExistsIndexedFields != nil { + eif := slices.Clone(*dps.ExistsIndexedFields) + mp[utils.ExistsIndexedFieldsCfg] = eif + } if dps.AttributeSConns != nil { attributeSConns := make([]string, len(dps.AttributeSConns)) for i, item := range dps.AttributeSConns { @@ -148,5 +159,9 @@ func (dps DispatcherSCfg) Clone() (cln *DispatcherSCfg) { copy(idx, *dps.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if dps.ExistsIndexedFields != nil { + idx := slices.Clone(*dps.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/dispatcherscfg_test.go b/config/dispatcherscfg_test.go index 73374e47b..092fa2924 100644 --- a/config/dispatcherscfg_test.go +++ b/config/dispatcherscfg_test.go @@ -32,6 +32,7 @@ func TestDispatcherSCfgloadFromJsonCfg(t *testing.T) { String_indexed_fields: &[]string{"*req.prefix", "*req.indexed"}, Prefix_indexed_fields: &[]string{"*req.prefix", "*req.indexed", "*req.fields"}, Suffix_indexed_fields: &[]string{"*req.prefix", "*req.indexed", "*req.fields"}, + ExistsIndexedFields: &[]string{"*req.exists", "*req.indexed", "*req.fields"}, Attributes_conns: &[]string{utils.MetaInternal, "*conn1"}, Nested_fields: utils.BoolPointer(true), Any_subsystem: utils.BoolPointer(true), @@ -42,6 +43,7 @@ func TestDispatcherSCfgloadFromJsonCfg(t *testing.T) { StringIndexedFields: &[]string{"*req.prefix", "*req.indexed"}, PrefixIndexedFields: &[]string{"*req.prefix", "*req.indexed", "*req.fields"}, SuffixIndexedFields: &[]string{"*req.prefix", "*req.indexed", "*req.fields"}, + ExistsIndexedFields: &[]string{"*req.exists", "*req.indexed", "*req.fields"}, AttributeSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAttributes), "*conn1"}, NestedFields: true, AnySubsystem: true, @@ -61,6 +63,7 @@ func TestDispatcherSCfgAsMapInterface(t *testing.T) { "indexed_selects":true, "prefix_indexed_fields": [], "suffix_indexed_fields": [], + "exists_indexed_fields": [], "nested_fields": false, "attributes_conns": [], }, @@ -71,6 +74,7 @@ func TestDispatcherSCfgAsMapInterface(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.AttributeSConnsCfg: []string{}, utils.AnySubsystemCfg: true, @@ -91,6 +95,7 @@ func TestDispatcherSCfgAsMapInterface1(t *testing.T) { "string_indexed_fields": ["*req.prefix"], "prefix_indexed_fields": ["*req.prefix","*req.indexed","*req.fields"], "suffix_indexed_fields": ["*req.prefix"], + "exists_indexed_fields": ["*req.exists"], "nested_fields": false, "attributes_conns": ["*internal:*attributes", "*conn1"], "prevent_loop": true @@ -103,6 +108,7 @@ func TestDispatcherSCfgAsMapInterface1(t *testing.T) { utils.StringIndexedFieldsCfg: []string{"*req.prefix"}, utils.PrefixIndexedFieldsCfg: []string{"*req.prefix", "*req.indexed", "*req.fields"}, utils.SuffixIndexedFieldsCfg: []string{"*req.prefix"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.exists"}, utils.NestedFieldsCfg: false, utils.AttributeSConnsCfg: []string{"*internal", "*conn1"}, utils.AnySubsystemCfg: true, @@ -124,6 +130,7 @@ func TestDispatcherSCfgAsMapInterface2(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.AttributeSConnsCfg: []string{}, utils.AnySubsystemCfg: true, diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 98259d57f..fdea807e9 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -637,7 +637,8 @@ type AttributeSJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined Any_context *bool Opts *AttributesOptsJson } @@ -650,7 +651,8 @@ type ChargerSJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined } type ResourcesOptsJson struct { @@ -668,7 +670,8 @@ type ResourceSJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined Opts *ResourcesOptsJson } @@ -687,7 +690,8 @@ type StatServJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined Opts *StatsOptsJson Ees_conns *[]string Ees_exporter_ids *[]string @@ -728,7 +732,8 @@ type ThresholdSJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined Opts *ThresholdsOptsJson } @@ -748,7 +753,8 @@ type RouteSJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined Attributes_conns *[]string Resources_conns *[]string Stats_conns *[]string @@ -822,7 +828,8 @@ type DispatcherSJsonCfg struct { String_indexed_fields *[]string Prefix_indexed_fields *[]string Suffix_indexed_fields *[]string - Nested_fields *bool // applies when indexed fields is not defined + ExistsIndexedFields *[]string `json:"exists_indexed_fields"` + Nested_fields *bool // applies when indexed fields is not defined Attributes_conns *[]string Any_subsystem *bool Prevent_loop *bool diff --git a/config/resourcescfg.go b/config/resourcescfg.go index 3ab93938d..fee3ff2de 100644 --- a/config/resourcescfg.go +++ b/config/resourcescfg.go @@ -19,6 +19,7 @@ along with this program. If not, see package config import ( + "slices" "time" "github.com/cgrates/cgrates/utils" @@ -39,6 +40,7 @@ type ResourceSConfig struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string NestedFields bool Opts *ResourcesOpts } @@ -103,6 +105,10 @@ func (rlcfg *ResourceSConfig) loadFromJSONCfg(jsnCfg *ResourceSJsonCfg) (err err copy(sif, *jsnCfg.Suffix_indexed_fields) rlcfg.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + rlcfg.ExistsIndexedFields = &eif + } if jsnCfg.Nested_fields != nil { rlcfg.NestedFields = *jsnCfg.Nested_fields } @@ -153,6 +159,10 @@ func (rlcfg *ResourceSConfig) AsMapInterface() (initialMP map[string]any) { copy(suffixIndexedFields, *rlcfg.SuffixIndexedFields) initialMP[utils.SuffixIndexedFieldsCfg] = suffixIndexedFields } + if rlcfg.ExistsIndexedFields != nil { + eif := slices.Clone(*rlcfg.ExistsIndexedFields) + initialMP[utils.ExistsIndexedFieldsCfg] = eif + } if rlcfg.StoreInterval != 0 { initialMP[utils.StoreIntervalCfg] = rlcfg.StoreInterval.String() } @@ -200,5 +210,9 @@ func (rlcfg ResourceSConfig) Clone() (cln *ResourceSConfig) { copy(idx, *rlcfg.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if rlcfg.ExistsIndexedFields != nil { + idx := slices.Clone(*rlcfg.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/resourcescfg_test.go b/config/resourcescfg_test.go index da0a7de7c..95c9bf741 100644 --- a/config/resourcescfg_test.go +++ b/config/resourcescfg_test.go @@ -34,6 +34,7 @@ func TestResourceSConfigloadFromJsonCfgCase1(t *testing.T) { String_indexed_fields: &[]string{"*req.index1"}, Prefix_indexed_fields: &[]string{"*req.index1"}, Suffix_indexed_fields: &[]string{"*req.index1"}, + ExistsIndexedFields: &[]string{"*req.index1"}, Nested_fields: utils.BoolPointer(true), } expected := &ResourceSConfig{ @@ -44,6 +45,7 @@ func TestResourceSConfigloadFromJsonCfgCase1(t *testing.T) { StringIndexedFields: &[]string{"*req.index1"}, PrefixIndexedFields: &[]string{"*req.index1"}, SuffixIndexedFields: &[]string{"*req.index1"}, + ExistsIndexedFields: &[]string{"*req.index1"}, NestedFields: true, Opts: &ResourcesOpts{ Units: 1, @@ -96,6 +98,7 @@ func TestResourceSConfigAsMapInterface(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaUnitsCfg: 1., @@ -119,6 +122,7 @@ func TestResourceSConfigAsMapInterface1(t *testing.T) { "string_indexed_fields": ["*req.index1"], "prefix_indexed_fields": ["*req.prefix_indexed_fields1","*req.prefix_indexed_fields2"], "suffix_indexed_fields": ["*req.prefix_indexed_fields1"], + "exists_indexed_fields": ["*req.exists_indexed_field"], "nested_fields": true, "opts":{ "*usageTTL":"1" @@ -134,6 +138,7 @@ func TestResourceSConfigAsMapInterface1(t *testing.T) { utils.StringIndexedFieldsCfg: []string{"*req.index1"}, utils.PrefixIndexedFieldsCfg: []string{"*req.prefix_indexed_fields1", "*req.prefix_indexed_fields2"}, utils.SuffixIndexedFieldsCfg: []string{"*req.prefix_indexed_fields1"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.exists_indexed_field"}, utils.NestedFieldsCfg: true, utils.OptsCfg: map[string]any{ utils.MetaUnitsCfg: 1., diff --git a/config/routescfg.go b/config/routescfg.go index b7bf11b9b..1f5018567 100644 --- a/config/routescfg.go +++ b/config/routescfg.go @@ -19,6 +19,8 @@ along with this program. If not, see package config import ( + "slices" + "github.com/cgrates/cgrates/utils" ) @@ -38,6 +40,7 @@ type RouteSCfg struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string AttributeSConns []string ResourceSConns []string StatSConns []string @@ -96,6 +99,10 @@ func (rts *RouteSCfg) loadFromJSONCfg(jsnCfg *RouteSJsonCfg) (err error) { copy(sif, *jsnCfg.Suffix_indexed_fields) rts.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + rts.ExistsIndexedFields = &eif + } if jsnCfg.Attributes_conns != nil { rts.AttributeSConns = make([]string, len(*jsnCfg.Attributes_conns)) for idx, conn := range *jsnCfg.Attributes_conns { @@ -188,6 +195,10 @@ func (rts *RouteSCfg) AsMapInterface() (initialMP map[string]any) { copy(suffixIndexedFieldsCfg, *rts.SuffixIndexedFields) initialMP[utils.SuffixIndexedFieldsCfg] = suffixIndexedFieldsCfg } + if rts.ExistsIndexedFields != nil { + eif := slices.Clone(*rts.ExistsIndexedFields) + initialMP[utils.ExistsIndexedFieldsCfg] = eif + } if rts.AttributeSConns != nil { attributeSConns := make([]string, len(rts.AttributeSConns)) for i, item := range rts.AttributeSConns { @@ -292,5 +303,9 @@ func (rts RouteSCfg) Clone() (cln *RouteSCfg) { copy(idx, *rts.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if rts.ExistsIndexedFields != nil { + idx := slices.Clone(*rts.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/routescfg_test.go b/config/routescfg_test.go index b6363a3af..5c6ff2088 100644 --- a/config/routescfg_test.go +++ b/config/routescfg_test.go @@ -31,6 +31,7 @@ func TestRouteSCfgloadFromJsonCfg(t *testing.T) { String_indexed_fields: &[]string{"*req.index1"}, Prefix_indexed_fields: &[]string{"*req.index1", "*req.index2"}, Suffix_indexed_fields: &[]string{"*req.index1", "*req.index2"}, + ExistsIndexedFields: &[]string{"*req.index1", "*req.index2"}, Attributes_conns: &[]string{utils.MetaInternal, "conn1"}, Resources_conns: &[]string{utils.MetaInternal, "conn1"}, Stats_conns: &[]string{utils.MetaInternal, "conn1"}, @@ -50,6 +51,7 @@ func TestRouteSCfgloadFromJsonCfg(t *testing.T) { StringIndexedFields: &[]string{"*req.index1"}, PrefixIndexedFields: &[]string{"*req.index1", "*req.index2"}, SuffixIndexedFields: &[]string{"*req.index1", "*req.index2"}, + ExistsIndexedFields: &[]string{"*req.index1", "*req.index2"}, AttributeSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAttributes), "conn1"}, ResourceSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResources), "conn1"}, StatSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats), "conn1"}, @@ -124,6 +126,7 @@ func TestRouteSCfgAsMapInterface1(t *testing.T) { "string_indexed_fields": ["*req.string"], "prefix_indexed_fields": ["*req.prefix","*req.indexed","*req.fields"], "suffix_indexed_fields": ["*req.prefix","*req.indexed"], + "exists_indexed_fields": ["*req.exists","*req.indexed"], "nested_fields": true, "attributes_conns": ["*internal:*attributes", "conn1"], "resources_conns": ["*internal:*resources", "conn1"], @@ -138,6 +141,7 @@ func TestRouteSCfgAsMapInterface1(t *testing.T) { utils.StringIndexedFieldsCfg: []string{"*req.string"}, utils.PrefixIndexedFieldsCfg: []string{"*req.prefix", "*req.indexed", "*req.fields"}, utils.SuffixIndexedFieldsCfg: []string{"*req.prefix", "*req.indexed"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.exists", "*req.indexed"}, utils.NestedFieldsCfg: true, utils.AttributeSConnsCfg: []string{utils.MetaInternal, "conn1"}, utils.ResourceSConnsCfg: []string{utils.MetaInternal, "conn1"}, diff --git a/config/statscfg.go b/config/statscfg.go index 0a7f27186..f5af406cb 100644 --- a/config/statscfg.go +++ b/config/statscfg.go @@ -40,6 +40,7 @@ type StatSCfg struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string NestedFields bool Opts *StatsOpts EEsConns []string @@ -114,6 +115,10 @@ func (st *StatSCfg) loadFromJSONCfg(jsnCfg *StatServJsonCfg) (err error) { copy(sif, *jsnCfg.Suffix_indexed_fields) st.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + st.ExistsIndexedFields = &eif + } if jsnCfg.Nested_fields != nil { st.NestedFields = *jsnCfg.Nested_fields } @@ -164,6 +169,10 @@ func (st *StatSCfg) AsMapInterface() (initialMP map[string]any) { initialMP[utils.SuffixIndexedFieldsCfg] = suffixIndexedFields } + if st.ExistsIndexedFields != nil { + eif := slices.Clone(*st.ExistsIndexedFields) + initialMP[utils.ExistsIndexedFieldsCfg] = eif + } if st.ThresholdSConns != nil { thresholdSConns := make([]string, len(st.ThresholdSConns)) for i, item := range st.ThresholdSConns { @@ -231,5 +240,9 @@ func (st StatSCfg) Clone() (cln *StatSCfg) { copy(idx, *st.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if st.ExistsIndexedFields != nil { + idx := slices.Clone(*st.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/statscfg_test.go b/config/statscfg_test.go index d3d94738c..c1bb4d1b3 100644 --- a/config/statscfg_test.go +++ b/config/statscfg_test.go @@ -34,6 +34,7 @@ func TestStatSCfgloadFromJsonCfgCase1(t *testing.T) { String_indexed_fields: &[]string{"*req.string"}, Prefix_indexed_fields: &[]string{"*req.index1", "*req.index2"}, Suffix_indexed_fields: &[]string{"*req.index1", "*req.index2"}, + ExistsIndexedFields: &[]string{"*req.index1", "*req.index2"}, Nested_fields: utils.BoolPointer(true), Ees_conns: &[]string{utils.MetaInternal, "*conn1"}, Ees_exporter_ids: &[]string{"exporterID"}, @@ -47,6 +48,7 @@ func TestStatSCfgloadFromJsonCfgCase1(t *testing.T) { StringIndexedFields: &[]string{"*req.string"}, PrefixIndexedFields: &[]string{"*req.index1", "*req.index2"}, SuffixIndexedFields: &[]string{"*req.index1", "*req.index2"}, + ExistsIndexedFields: &[]string{"*req.index1", "*req.index2"}, NestedFields: true, Opts: &StatsOpts{ ProfileIDs: []string{}, @@ -90,6 +92,7 @@ func TestStatSCfgAsMapInterface(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, @@ -116,6 +119,7 @@ func TestStatSCfgAsMapInterface1(t *testing.T) { "string_indexed_fields": ["*req.string"], "prefix_indexed_fields": ["*req.prefix_indexed_fields1","*req.prefix_indexed_fields2"], "suffix_indexed_fields":["*req.suffix_indexed_fields"], + "exists_indexed_fields":["*req.exists_indexed_field"], "nested_fields": true, "ees_conns": ["*internal:*ees", "*conn1"], "ees_exporter_ids":["exporterID"], @@ -130,6 +134,7 @@ func TestStatSCfgAsMapInterface1(t *testing.T) { utils.StringIndexedFieldsCfg: []string{"*req.string"}, utils.PrefixIndexedFieldsCfg: []string{"*req.prefix_indexed_fields1", "*req.prefix_indexed_fields2"}, utils.SuffixIndexedFieldsCfg: []string{"*req.suffix_indexed_fields"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.exists_indexed_field"}, utils.NestedFieldsCfg: true, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, diff --git a/config/thresholdscfg.go b/config/thresholdscfg.go index 59cc50b08..9b115d5f9 100644 --- a/config/thresholdscfg.go +++ b/config/thresholdscfg.go @@ -39,6 +39,7 @@ type ThresholdSCfg struct { StringIndexedFields *[]string PrefixIndexedFields *[]string SuffixIndexedFields *[]string + ExistsIndexedFields *[]string NestedFields bool Opts *ThresholdsOpts } @@ -95,6 +96,10 @@ func (t *ThresholdSCfg) loadFromJSONCfg(jsnCfg *ThresholdSJsonCfg) (err error) { copy(sif, *jsnCfg.Suffix_indexed_fields) t.SuffixIndexedFields = &sif } + if jsnCfg.ExistsIndexedFields != nil { + eif := slices.Clone(*jsnCfg.ExistsIndexedFields) + t.ExistsIndexedFields = &eif + } if jsnCfg.Nested_fields != nil { t.NestedFields = *jsnCfg.Nested_fields } @@ -145,6 +150,10 @@ func (t *ThresholdSCfg) AsMapInterface() (initialMP map[string]any) { copy(suffixIndexedFields, *t.SuffixIndexedFields) initialMP[utils.SuffixIndexedFieldsCfg] = suffixIndexedFields } + if t.ExistsIndexedFields != nil { + eif := slices.Clone(*t.ExistsIndexedFields) + initialMP[utils.ExistsIndexedFieldsCfg] = eif + } return } @@ -183,5 +192,9 @@ func (t ThresholdSCfg) Clone() (cln *ThresholdSCfg) { copy(idx, *t.SuffixIndexedFields) cln.SuffixIndexedFields = &idx } + if t.ExistsIndexedFields != nil { + idx := slices.Clone(*t.ExistsIndexedFields) + cln.ExistsIndexedFields = &idx + } return } diff --git a/config/thresholdscfg_test.go b/config/thresholdscfg_test.go index f4891f653..e512888da 100644 --- a/config/thresholdscfg_test.go +++ b/config/thresholdscfg_test.go @@ -32,6 +32,7 @@ func TestThresholdSCfgloadFromJsonCfgCase1(t *testing.T) { String_indexed_fields: &[]string{"*req.prefix"}, Prefix_indexed_fields: &[]string{"*req.index1"}, Suffix_indexed_fields: &[]string{"*req.index1"}, + ExistsIndexedFields: &[]string{"*req.index1"}, Nested_fields: utils.BoolPointer(true), Opts: &ThresholdsOptsJson{ ProfileIDs: &[]string{}, @@ -45,6 +46,7 @@ func TestThresholdSCfgloadFromJsonCfgCase1(t *testing.T) { StringIndexedFields: &[]string{"*req.prefix"}, PrefixIndexedFields: &[]string{"*req.index1"}, SuffixIndexedFields: &[]string{"*req.index1"}, + ExistsIndexedFields: &[]string{"*req.index1"}, NestedFields: true, Opts: &ThresholdsOpts{ ProfileIDs: []string{}, @@ -86,6 +88,7 @@ func TestThresholdSCfgAsMapInterfaceCase1(t *testing.T) { utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, + utils.ExistsIndexedFieldsCfg: []string{}, utils.NestedFieldsCfg: false, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, @@ -108,6 +111,7 @@ func TestThresholdSCfgAsMapInterfaceCase2(t *testing.T) { "string_indexed_fields": ["*req.string"], "prefix_indexed_fields": ["*req.prefix","*req.indexed","*req.fields"], "suffix_indexed_fields": ["*req.suffix_indexed_fields1", "*req.suffix_indexed_fields2"], + "exists_indexed_fields": ["*req.exists_indexed_field"], "nested_fields": true, }, }` @@ -118,6 +122,7 @@ func TestThresholdSCfgAsMapInterfaceCase2(t *testing.T) { utils.StringIndexedFieldsCfg: []string{"*req.string"}, utils.PrefixIndexedFieldsCfg: []string{"*req.prefix", "*req.indexed", "*req.fields"}, utils.SuffixIndexedFieldsCfg: []string{"*req.suffix_indexed_fields1", "*req.suffix_indexed_fields2"}, + utils.ExistsIndexedFieldsCfg: []string{"*req.exists_indexed_field"}, utils.NestedFieldsCfg: true, utils.OptsCfg: map[string]any{ utils.MetaProfileIDs: []string{}, diff --git a/dispatchers/dispatchers.go b/dispatchers/dispatchers.go index 246657498..f997f6986 100644 --- a/dispatchers/dispatchers.go +++ b/dispatchers/dispatchers.go @@ -132,6 +132,7 @@ func (dS *DispatcherService) dispatcherProfilesForEvent(tnt string, ev *utils.CG dS.cfg.DispatcherSCfg().StringIndexedFields, dS.cfg.DispatcherSCfg().PrefixIndexedFields, dS.cfg.DispatcherSCfg().SuffixIndexedFields, + dS.cfg.DispatcherSCfg().ExistsIndexedFields, dS.dm, utils.CacheDispatcherFilterIndexes, idxKeyPrfx, dS.cfg.DispatcherSCfg().IndexedSelects, dS.cfg.DispatcherSCfg().NestedFields, @@ -146,6 +147,7 @@ func (dS *DispatcherService) dispatcherProfilesForEvent(tnt string, ev *utils.CG dS.cfg.DispatcherSCfg().StringIndexedFields, dS.cfg.DispatcherSCfg().PrefixIndexedFields, dS.cfg.DispatcherSCfg().SuffixIndexedFields, + dS.cfg.DispatcherSCfg().ExistsIndexedFields, dS.dm, utils.CacheDispatcherFilterIndexes, anyIdxPrfx, dS.cfg.DispatcherSCfg().IndexedSelects, dS.cfg.DispatcherSCfg().NestedFields, diff --git a/engine/attributes.go b/engine/attributes.go index ca11ebdcf..f5d07e2af 100644 --- a/engine/attributes.go +++ b/engine/attributes.go @@ -72,6 +72,7 @@ func (alS *AttributeService) attributeProfileForEvent(tnt string, ctx *string, a alS.cgrcfg.AttributeSCfg().StringIndexedFields, alS.cgrcfg.AttributeSCfg().PrefixIndexedFields, alS.cgrcfg.AttributeSCfg().SuffixIndexedFields, + alS.cgrcfg.AttributeSCfg().ExistsIndexedFields, alS.dm, utils.CacheAttributeFilterIndexes, attrIdxKey, alS.cgrcfg.AttributeSCfg().IndexedSelects, alS.cgrcfg.AttributeSCfg().NestedFields, @@ -86,6 +87,7 @@ func (alS *AttributeService) attributeProfileForEvent(tnt string, ctx *string, a alS.cgrcfg.AttributeSCfg().StringIndexedFields, alS.cgrcfg.AttributeSCfg().PrefixIndexedFields, alS.cgrcfg.AttributeSCfg().SuffixIndexedFields, + alS.cgrcfg.AttributeSCfg().ExistsIndexedFields, alS.dm, utils.CacheAttributeFilterIndexes, utils.ConcatenatedKey(tnt, utils.MetaAny), alS.cgrcfg.AttributeSCfg().IndexedSelects, diff --git a/engine/chargers.go b/engine/chargers.go index 3f21351df..e1da4a89f 100644 --- a/engine/chargers.go +++ b/engine/chargers.go @@ -56,6 +56,7 @@ func (cS *ChargerService) matchingChargerProfilesForEvent(tnt string, cgrEv *uti cS.cfg.ChargerSCfg().StringIndexedFields, cS.cfg.ChargerSCfg().PrefixIndexedFields, cS.cfg.ChargerSCfg().SuffixIndexedFields, + cS.cfg.ChargerSCfg().ExistsIndexedFields, cS.dm, utils.CacheChargerFilterIndexes, tnt, cS.cfg.ChargerSCfg().IndexedSelects, cS.cfg.ChargerSCfg().NestedFields, diff --git a/engine/filterhelpers.go b/engine/filterhelpers.go index 864961279..8399fe608 100644 --- a/engine/filterhelpers.go +++ b/engine/filterhelpers.go @@ -36,11 +36,11 @@ import ( // MatchingItemIDsForEvent returns the list of item IDs matching fieldName/fieldValue for an event // fieldIDs limits the fields which are checked against indexes // helper on top of dataDB.GetIndexes, adding utils.MetaAny to list of fields queried -func MatchingItemIDsForEvent(ev utils.MapStorage, stringFldIDs, prefixFldIDs, suffixFldIDs *[]string, +func MatchingItemIDsForEvent(ev utils.MapStorage, stringFldIDs, prefixFldIDs, suffixFldIDs, existsFldIDs *[]string, dm *DataManager, cacheID, itemIDPrefix string, indexedSelects, nestedFields bool) (itemIDs utils.StringSet, err error) { itemIDs = make(utils.StringSet) var allFieldIDs []string - if indexedSelects && (stringFldIDs == nil || prefixFldIDs == nil || suffixFldIDs == nil) { + if indexedSelects && (stringFldIDs == nil || prefixFldIDs == nil || suffixFldIDs == nil || existsFldIDs == nil) { allFieldIDs = ev.GetKeys(nestedFields, 2, utils.EmptyString) } // Guard will protect the function with automatic locking @@ -58,13 +58,32 @@ func MatchingItemIDsForEvent(ev utils.MapStorage, stringFldIDs, prefixFldIDs, su itemIDs = utils.NewStringSet(sliceIDs) return } - stringFieldVals := map[string]string{utils.MetaAny: utils.MetaAny} // cache here field string values, start with default one - filterIndexTypes := []string{utils.MetaString, utils.MetaPrefix, utils.MetaSuffix, utils.MetaNone} // the MetaNone is used for all items that do not have filters - for i, fieldIDs := range []*[]string{stringFldIDs, prefixFldIDs, suffixFldIDs, {utils.MetaAny}} { // same routine for both string and prefix filter types + stringFieldVals := map[string]string{utils.MetaAny: utils.MetaAny} // cache here field string values, start with default one + filterIndexTypes := []string{utils.MetaString, utils.MetaPrefix, utils.MetaSuffix, utils.MetaExists, utils.MetaNone} // the MetaNone is used for all items that do not have filters + for i, fieldIDs := range []*[]string{stringFldIDs, prefixFldIDs, suffixFldIDs, existsFldIDs, {utils.MetaAny}} { // same routine for both string and prefix filter types if fieldIDs == nil { fieldIDs = &allFieldIDs } for _, fldName := range *fieldIDs { + var dbItemIDs utils.StringSet // list of items matched in DB + if filterIndexTypes[i] == utils.MetaExists { + var dbIndexes map[string]utils.StringSet // list of items matched in DB + key := utils.ConcatenatedKey(filterIndexTypes[i], fldName) + if dbIndexes, err = dm.GetIndexes(cacheID, itemIDPrefix, key, true, true); err != nil { + if err == utils.ErrNotFound { + err = nil + continue + } + return + } + dbItemIDs = dbIndexes[key] + for itemID := range dbItemIDs { + if _, hasIt := itemIDs[itemID]; !hasIt { // Add it to list if not already there + itemIDs[itemID] = dbItemIDs[itemID] + } + } + continue // no need to look at values for *exists indexes + } var fieldValIf any fieldValIf, err = ev.FieldAsInterface(utils.SplitPath(fldName, utils.NestingSep[0], -1)) if err != nil && filterIndexTypes[i] != utils.MetaNone { @@ -81,7 +100,6 @@ func MatchingItemIDsForEvent(ev utils.MapStorage, stringFldIDs, prefixFldIDs, su } else if filterIndexTypes[i] == utils.MetaSuffix { fldVals = utils.SplitSuffix(fldVal) // all suffix till first digit } - var dbItemIDs utils.StringSet // list of items matched in DB for _, val := range fldVals { var dbIndexes map[string]utils.StringSet // list of items matched in DB key := utils.ConcatenatedKey(filterIndexTypes[i], fldName, val) diff --git a/engine/libindex.go b/engine/libindex.go index 5b2d82f3f..440b865b5 100644 --- a/engine/libindex.go +++ b/engine/libindex.go @@ -28,7 +28,7 @@ import ( ) var ( - FilterIndexTypes = utils.NewStringSet([]string{utils.MetaPrefix, utils.MetaString, utils.MetaSuffix}) + FilterIndexTypes = utils.NewStringSet([]string{utils.MetaPrefix, utils.MetaString, utils.MetaSuffix, utils.MetaExists}) // Element or values of a filter that starts with one of this should not be indexed ToNotBeIndexed = []string{ utils.DynamicDataPrefix + utils.MetaAccounts, @@ -86,6 +86,23 @@ func newFilterIndex(dm *DataManager, idxItmType, tnt, ctx, itemID string, filter continue } isDyn := strings.HasPrefix(flt.Element, utils.DynamicDataPrefix) + if isDyn && flt.Type == utils.MetaExists { + idxKey := utils.ConcatenatedKey(flt.Type, flt.Element[1:]) + var rcvIndx map[string]utils.StringSet + // only read from cache in case if we do not find the index to not cache the negative response + if rcvIndx, err = dm.GetIndexes(idxItmType, tntCtx, + idxKey, true, false); err != nil { + if err != utils.ErrNotFound { + return + } + err = nil + indexes[idxKey] = make(utils.StringSet) // create an empty index if is not found in DB in case we add them later + continue + } + for idxKey, idx := range rcvIndx { // parse the received indexes + indexes[idxKey] = idx + } + } for _, fldVal := range flt.Values { if IsDynamicDPPath(fldVal) { continue diff --git a/engine/libindex_test.go b/engine/libindex_test.go index 53c7caccc..2f2286107 100644 --- a/engine/libindex_test.go +++ b/engine/libindex_test.go @@ -268,6 +268,14 @@ func TestLibIndex_newFilterIndex(t *testing.T) { } wantIndexes := map[string]utils.StringSet{ + "*exists:*req.Field1": { + "ATTR_1": {}, + "ATTR_3": {}, + }, + "*exists:*req.Field2": { + "ATTR_2": {}, + "ATTR_3": {}, + }, "*prefix:*req.Field1:val": { "ATTR_1": {}, "ATTR_3": {}, @@ -347,7 +355,7 @@ func TestLibIndex_newFilterIndex(t *testing.T) { { name: "unindexable filter", idxItmType: utils.CacheAttributeFilterIndexes, - filterIDs: []string{"*exists:~*req.Field1:"}, + filterIDs: []string{"*notstring:~*req.Field1:val2"}, want: make(map[string]utils.StringSet), }, { @@ -454,6 +462,14 @@ func TestLibIndex_newFilterIndex(t *testing.T) { "*suffix:~*req.Field1:1", }, want: map[string]utils.StringSet{ + "*exists:*req.Field1": { + "ATTR_1": {}, + "ATTR_3": {}, + }, + "*exists:*req.Field2": { + "ATTR_2": {}, + "ATTR_3": {}, + }, "*prefix:*req.Field1:val": { "ATTR_1": {}, "ATTR_3": {}, @@ -494,6 +510,14 @@ func TestLibIndex_newFilterIndex(t *testing.T) { "*notstring:~*req.Field2:val1", }, want: map[string]utils.StringSet{ + "*exists:*req.Field1": { + "ATTR_1": {}, + "ATTR_3": {}, + }, + "*exists:*req.Field2": { + "ATTR_2": {}, + "ATTR_3": {}, + }, "*prefix:*req.Field1:val": { "ATTR_1": {}, "ATTR_3": {}, @@ -536,6 +560,14 @@ func TestLibIndex_newFilterIndex(t *testing.T) { "*string:~*req.Field5:val5", }, want: map[string]utils.StringSet{ + "*exists:*req.Field1": { + "ATTR_1": {}, + "ATTR_3": {}, + }, + "*exists:*req.Field2": { + "ATTR_2": {}, + "ATTR_3": {}, + }, "*prefix:*req.Field1:val": { "ATTR_1": {}, "ATTR_3": {}, @@ -570,15 +602,15 @@ func TestLibIndex_newFilterIndex(t *testing.T) { got, gotErr := newFilterIndex(dm, tt.idxItmType, tt.tnt, tt.ctx, tt.itemID, tt.filterIDs, tt.newFlt) if gotErr != nil { if !tt.wantErr { - t.Errorf("prepareFilterIndexMap() failed: %v", gotErr) + t.Errorf("newFilterIndex() failed: %v", gotErr) } return } if tt.wantErr { - t.Fatal("prepareFilterIndexMap() succeeded unexpectedly") + t.Fatal("newFilterIndex() succeeded unexpectedly") } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("prepareFilterIndexMap() = %s, want %s", utils.ToJSON(got), utils.ToJSON(tt.want)) + t.Errorf("newFilterIndex() = %s, want %s", utils.ToJSON(got), utils.ToJSON(tt.want)) } }) } diff --git a/engine/resources.go b/engine/resources.go index 9f736e7a5..9f6d8a754 100644 --- a/engine/resources.go +++ b/engine/resources.go @@ -659,6 +659,7 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv rS.cgrcfg.ResourceSCfg().StringIndexedFields, rS.cgrcfg.ResourceSCfg().PrefixIndexedFields, rS.cgrcfg.ResourceSCfg().SuffixIndexedFields, + rS.cgrcfg.ResourceSCfg().ExistsIndexedFields, rS.dm, utils.CacheResourceFilterIndexes, tnt, rS.cgrcfg.ResourceSCfg().IndexedSelects, rS.cgrcfg.ResourceSCfg().NestedFields, diff --git a/engine/routes.go b/engine/routes.go index 6b236e8f8..f9d250693 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -230,6 +230,7 @@ func (rpS *RouteService) matchingRouteProfilesForEvent(tnt string, ev *utils.CGR rpS.cgrcfg.RouteSCfg().StringIndexedFields, rpS.cgrcfg.RouteSCfg().PrefixIndexedFields, rpS.cgrcfg.RouteSCfg().SuffixIndexedFields, + rpS.cgrcfg.RouteSCfg().ExistsIndexedFields, rpS.dm, utils.CacheRouteFilterIndexes, tnt, rpS.cgrcfg.RouteSCfg().IndexedSelects, rpS.cgrcfg.RouteSCfg().NestedFields, diff --git a/engine/stats.go b/engine/stats.go index 49bdb6c89..02a4e401a 100644 --- a/engine/stats.go +++ b/engine/stats.go @@ -165,6 +165,7 @@ func (sS *StatService) matchingStatQueuesForEvent(tnt string, statsIDs []string, sS.cgrcfg.StatSCfg().StringIndexedFields, sS.cgrcfg.StatSCfg().PrefixIndexedFields, sS.cgrcfg.StatSCfg().SuffixIndexedFields, + sS.cgrcfg.StatSCfg().ExistsIndexedFields, sS.dm, utils.CacheStatFilterIndexes, tnt, sS.cgrcfg.StatSCfg().IndexedSelects, sS.cgrcfg.StatSCfg().NestedFields, diff --git a/engine/thresholds.go b/engine/thresholds.go index 61ce5b969..8ec0d5b74 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -411,6 +411,7 @@ func (tS *ThresholdService) matchingThresholdsForEvent(tnt string, args *utils.C tS.cgrcfg.ThresholdSCfg().StringIndexedFields, tS.cgrcfg.ThresholdSCfg().PrefixIndexedFields, tS.cgrcfg.ThresholdSCfg().SuffixIndexedFields, + tS.cgrcfg.ThresholdSCfg().ExistsIndexedFields, tS.dm, utils.CacheThresholdFilterIndexes, tnt, tS.cgrcfg.ThresholdSCfg().IndexedSelects, tS.cgrcfg.ThresholdSCfg().NestedFields, diff --git a/engine/z_filterhelpers_test.go b/engine/z_filterhelpers_test.go index ae0d68a19..aaa196bd8 100644 --- a/engine/z_filterhelpers_test.go +++ b/engine/z_filterhelpers_test.go @@ -103,7 +103,7 @@ func TestFilterMatchingItemIDsForEvent(t *testing.T) { utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC), "Field": "profile", }} - aPrflIDs, err := MatchingItemIDsForEvent(matchEV, nil, nil, nil, + aPrflIDs, err := MatchingItemIDsForEvent(matchEV, nil, nil, nil, nil, dmMatch, utils.CacheAttributeFilterIndexes, tntCtx, true, false) if err != nil { t.Errorf("Error: %+v", err) @@ -116,7 +116,7 @@ func TestFilterMatchingItemIDsForEvent(t *testing.T) { matchEV = utils.MapStorage{utils.MetaReq: map[string]any{ "Field": "profilePrefix", }} - aPrflIDs, err = MatchingItemIDsForEvent(matchEV, nil, nil, nil, + aPrflIDs, err = MatchingItemIDsForEvent(matchEV, nil, nil, nil, nil, dmMatch, utils.CacheAttributeFilterIndexes, tntCtx, true, false) if err != nil { t.Errorf("Error: %+v", err) @@ -129,7 +129,7 @@ func TestFilterMatchingItemIDsForEvent(t *testing.T) { matchEV = utils.MapStorage{utils.MetaReq: map[string]any{ "Field": "profilePrefix", }} - aPrflIDs, err = MatchingItemIDsForEvent(matchEV, nil, nil, nil, + aPrflIDs, err = MatchingItemIDsForEvent(matchEV, nil, nil, nil, nil, dmMatch, utils.CacheAttributeFilterIndexes, tntCtx, true, false) if err != nil { t.Errorf("Error: %+v", err) @@ -196,7 +196,7 @@ func TestFilterMatchingItemIDsForEvent2(t *testing.T) { utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC), "CallCost": map[string]any{"Account": 1001}, }} - aPrflIDs, err := MatchingItemIDsForEvent(matchEV, nil, nil, nil, + aPrflIDs, err := MatchingItemIDsForEvent(matchEV, nil, nil, nil, nil, dmMatch, utils.CacheAttributeFilterIndexes, tntCtx, true, true) if err != nil { t.Errorf("Error: %+v", err) @@ -208,7 +208,7 @@ func TestFilterMatchingItemIDsForEvent2(t *testing.T) { matchEV = utils.MapStorage{utils.MetaReq: map[string]any{ "CallCost": map[string]any{"Field": "profilePrefix"}, }} - aPrflIDs, err = MatchingItemIDsForEvent(matchEV, nil, nil, nil, + aPrflIDs, err = MatchingItemIDsForEvent(matchEV, nil, nil, nil, nil, dmMatch, utils.CacheAttributeFilterIndexes, tntCtx, true, true) if err != nil { t.Errorf("Error: %+v", err) diff --git a/utils/consts.go b/utils/consts.go index bc45bb757..5ba73caf1 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -2163,6 +2163,7 @@ const ( StringIndexedFieldsCfg = "string_indexed_fields" PrefixIndexedFieldsCfg = "prefix_indexed_fields" SuffixIndexedFieldsCfg = "suffix_indexed_fields" + ExistsIndexedFieldsCfg = "exists_indexed_fields" MongoQueryTimeoutCfg = "mongoQueryTimeout" MongoConnSchemeCfg = "mongoConnScheme" PgSSLModeCfg = "pgSSLMode"