FilterS
FilterS are code blocks applied to generic events (hashmaps) in order to allow/deny further processing.
A Tenant will define multiple Filter profiles via .csv or API calls. The Filter profile ID is unique within a tenant but it can be repeated over multiple Tenants.
In order to be used in event processing, a Filter profile will be attached inside another subsystem profile definition, otherwise Filter profile will have no effect on it’s own.
A subsystem can use a Filter via FilterProfile or in-line (ad-hock in the same place where subsystem profile is defined).
Filter profile
Definition:
type Filter struct {
Tenant string
ID string
Rules []*FilterRule
ActivationInterval *utils.ActivationInterval
}
A Filter profile can be shared between multiple subsystem profile definitions.
A Filter profile can contain any number of Filter rules and each of them must pass in order for the filter profile to pass.
A Filter profile can be activated on specific interval, if multiple filters are used within a subsystem profile at least one needs to be active and passing in order for the subsystem profile to pass the event.
Filter rule
Definition:
type FilterRule struct {
Type string // Filter type
Element string // Name of the field providing us the Values to check (used in case of some )
Values []string // Filter definition
}
The matching logic of each FilterRule is given by it’s type.
The following types are implemented:
- *string*
Will match in full the Element with at least one value defined inside Values. Any of the values matching will have the FilterRule as matched.
- *notstring
Is the negation of *string.
- *prefix
Will match at beginning of Element one of the values defined inside Values.
- *notprefix
Is the negation of *prefix.
- *suffix
Will match at end of Element one of the values defined inside Values.
- *notsuffix*
Is the negation of *suffix.
- *empty
Will make sure that Element is empty or it does not exist in the event.
- *notempty
Is the negation of *empty.
- *exists
Will make sure that Element exists in the event.
- *notexists
Is the negation of *exists.
- *timings
Will compare the time contained in Element with one of the TimingIDs defined in Values.
- *nottimings
Is the negation of *timings.
- *destinations
Will make sure that the Element is a prefix contained inside one of the destination IDs as Values.
- *notdestinations
Is the negation of *destinations.
- *rsr
Will match the RSRRules defined in Values.
- *notrsr*
Is the negation of *rsr.
- *lt (less than), *lte (less than or equal), *gt (greather than), *gte (greather than or equal)
Are comparison operators and they pass if at least one of the values defined in Values are passing for the Element of event. The operators are able to compare string, float, int, time.Time, time.Duration, however both types need to be the same, otherwise the filter will raise incomparable as error.
Inline Filter
In order to facilitate quick filter definition (without the need of separate FilterProfile), one can define filters directly as FilterIDs following the special format.
Inline filter format:
filterType:fieldName:fieldValue
Example:
*string:WebsiteName:CGRateS.org
Subsystem profiles selection based on Filters
When a subsystem will process an event it will need to find fast enough (close to real-time and most preferably with constant speed) all the profiles having filters matching the event. For low number of profiles (tens of) we can go through all available profiles and check their filters but as soon as the number of profiles is growing, processing time will exponentially grow also. As an example, the AttributeS need to deal with 20 mil+ profiles in case of number portability implementation.
In order to guarantee constant processing time - O(1) - CGRateS will use internally a profile selection mechanism based on indexed filters which can be enabled within .json configuration file via indexed_selects. When indexed_selects is disabled, the indexes will not be used at all and profiles will be checked one by one. On the other hand, if indexed_selects is enabled, each FilterProfile needs to have at least one *string or *prefix type in order to be visible to the indexes (otherwise being completely ignored).
The following settings are further applied once indexed_selects is enabled:
- string_indexed_fields
list of field names in the event which will be checked against string indexes (defaults to nil which means check all fields)
- prefix_indexed_fields
list of field names in the event which will be checked against prefix indexes (default is empty, hence prefix matching is disabled inside indexes - small optimization since for prefixes there are multiple queries done for one field)