From 646f9a33cdb416d93ace97121dc463bbdf16e195 Mon Sep 17 00:00:00 2001 From: DanB Date: Wed, 19 Feb 2020 20:27:12 +0100 Subject: [PATCH] [Docs] Adding suppliers documentation --- docs/attributes.rst | 46 +++++++++++- docs/resources.rst | 13 +++- docs/stats.rst | 35 ++++++++- docs/suppliers.rst | 174 +++++++++++++++++++++++++++++++++++++++++++- engine/suppliers.go | 15 +++- 5 files changed, 271 insertions(+), 12 deletions(-) diff --git a/docs/attributes.rst b/docs/attributes.rst index d838d3805..c99f9d0a2 100644 --- a/docs/attributes.rst +++ b/docs/attributes.rst @@ -4,7 +4,7 @@ AttributeS **AttributeS** is a standalone subsystem within **CGRateS** and it is the equivalent of a key-value store. It is accessed via :ref:`CGRateS RPC APIs`. As most of the other subsystems, it is performance oriented, stored inside *DataDB* but cached inside the *cgr-engine* process. -Caching can be done dynamically/on-demand or at start-time/precached and it is configurable within "cache" section in the .json configuration file. +Caching can be done dynamically/on-demand or at start-time/precached and it is configurable within *cache* section in the :ref:`JSON configuration `. Selection --------- @@ -18,9 +18,37 @@ Parameters ---------- +AttributeS +^^^^^^^^^^ + +**AttributeS** is the **CGRateS** component responsible of handling the *AttributeProfiles*. + +It is configured within **attributes** section from :ref:`JSON configuration ` via the following parameters: + +enabled + Will enable starting of the service. Possible values: . + +indexed_selects + Enable profile matching exclusively on indexes. If not enabled, the *ResourceProfiles* are checked one by one which for a larger number can slow down the processing time. Possible values: . + +string_indexed_fields + Query string indexes based only on these fields for faster processing. If commented out, each field from the event will be checked against indexes. If uncommented and defined as empty list, no fields will be checked. + +prefix_indexed_fields + Query prefix indexes based only on these fields for faster processing. If defined as empty list, no fields will be checked. + +nested_fields + Applied when all event fields are checked against indexes, and decides whether subfields are also checked. + +process_runs + Limit the number of loops when processing an Event. The event loop is however clever enough to stop when the same processing occurs or no more additional profiles are matching, so higher numbers are ignored if not needed. + + AttributeProfile ^^^^^^^^^^^^^^^^ +Represents the configuration for a group of attributes applied. + Tenant The tenant on the platform (one can see the tenant as partition ID) @@ -77,7 +105,21 @@ Type Will compute the exponent of the first field in the *Value*. Value - The value which will be set for *Path*. It can be a list of :ref:`RSRParsers` capturing even from multiple sources in the same event. If the *Value* is *\*none* the field with *Path* will be removed from *Event* + The value which will be set for *Path*. It can be a list of :ref:`RSRParsers` capturing even from multiple sources in the same event. If the *Value* is *\*remove* the field with *Path* will be removed from *Event* + + +Inline Attribute +^^^^^^^^^^^^^^^^ + +In order to facilitate quick attribute definition (without the need of separate *AttributeProfile*), one can define attributes directly as *AttributeIDs* following the special format. + +Inline filter format:: + + attributeType:attributePath:attributeValue + +Example:: + + *constant:*req.RequestType:*prepaid Use cases diff --git a/docs/resources.rst b/docs/resources.rst index 39d60ade7..7c4579a46 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -2,12 +2,13 @@ ResourceS ========= -**ResourceS** is a standalone subsystem part of the **CGRateS** infrastructure, designed allocate virtual resources for the generic *Events* (hashmaps) it receives. +**ResourceS** is a standalone subsystem part of the **CGRateS** infrastructure, designed to allocate virtual resources for the generic *Events* (hashmaps) it receives. Both receiving of *Events* as well as operational commands on the virtual resources is performed via a complete set of :ref:`CGRateS RPC APIs`. Due it's real-time nature, **ResourceS** are designed towards high throughput being able to process thousands of *Events* per second. This is doable since each *Resource* is a very light object, held in memory and eventually backed up in *DataDB*. + Processing logic ---------------- @@ -44,11 +45,17 @@ ResourceS **ResourceS** is the **CGRateS** component responsible of handling the *Resources*. -It is configured within *resources* section from :ref:`JSON configuration ` via the following parameters: +It is configured within **resources** section from :ref:`JSON configuration ` via the following parameters: enabled Will enable starting of the service. Possible values: . +store_interval + Time interval for backing up the stats into *DataDB*. + +thresholds_conns + Connections IDs towards *ThresholdS* component. If not defined, there will be no notifications sent to *ThresholdS* on *Resource* changes. + indexed_selects Enable profile matching exclusively on indexes. If not enabled, the *ResourceProfiles* are checked one by one which for a larger number can slow down the processing time. Possible values: . @@ -101,8 +108,6 @@ ThresholdIDs List of ThresholdProfiles targetted by the *Resource*. If empty, the match will be done in :ref:`ThresholdS` component. - - ResourceUsage ^^^^^^^^^^^^^ diff --git a/docs/stats.rst b/docs/stats.rst index d5049334d..13da95d6f 100644 --- a/docs/stats.rst +++ b/docs/stats.rst @@ -8,6 +8,7 @@ Both receiving of *Events* as well as *Metrics* displaying is performed via a co Due it's real-time nature, **StatS** are designed towards high throughput being able to process thousands of *Events* per second. This is doable since each *StatQueue* is a very light object, held in memory and eventually backed up in *DataDB*. + Processing logic ---------------- @@ -24,6 +25,38 @@ Parameters ---------- +StatS +^^^^^ + +**StatS** is the **CGRateS** component responsible of handling the *StatQueues*. + +It is configured within **stats** section from :ref:`JSON configuration ` via the following parameters: + +enabled + Will enable starting of the service. Possible values: . + +store_interval + Time interval for backing up the stats into *DataDB*. + +store_uncompressed_limit + After this limit is hit the events within *StatQueue* will be stored aggregated. + +thresholds_conns + Connections IDs towards *ThresholdS* component. If not defined, there will be no notifications sent to *ThresholdS* on *StatQueue* changes. + +indexed_selects + Enable profile matching exclusively on indexes. If not enabled, the *StatQueues* are checked one by one which for a larger number can slow down the processing time. Possible values: . + +string_indexed_fields + Query string indexes based only on these fields for faster processing. If commented out, each field from the event will be checked against indexes. If uncommented and defined as empty list, no fields will be checked. + +prefix_indexed_fields + Query prefix indexes based only on these fields for faster processing. If defined as empty list, no fields will be checked. + +nested_fields + Applied when all event fields are checked against indexes, and decides whether subfields are also checked. + + StatQueueProfile ^^^^^^^^^^^^^^^^ @@ -36,7 +69,7 @@ ID Identifier for the *StatQueueProfile*, unique within a *Tenant*. FilterIDs - List of *FilterProfiles* which should match in order to consider the *StatQueueProfile* matching the event. + List of *FilterProfileIDs* which should match in order to consider the profile matching the event. ActivationInterval The time interval when this profile becomes active. If undefined, the profile is always active. Other options are start time, end time or both. diff --git a/docs/suppliers.rst b/docs/suppliers.rst index 3bb36ccf4..d9401b627 100644 --- a/docs/suppliers.rst +++ b/docs/suppliers.rst @@ -2,4 +2,176 @@ SupplierS ========= -TBD \ No newline at end of file +**SupplierS** is a standalone subsystem within **CGRateS** responsible to compute a list of suppliers which can be used for a specific event received to process. It is accessed via :ref:`CGRateS RPC APIs`. + +As most of the other subsystems, it is performance oriented, stored inside *DataDB* but cached inside the *cgr-engine* process. +Caching can be done dynamically/on-demand or at start-time/precached and it is configurable within *cache* section in the .json configuration file. + + +Processing logic +---------------- + +When a new *Event* is received, **SupplierS** will pass it to :ref:`FilterS` in order to find all *SupplierProfiles* matching the *Event*. + +As a result of the selection process we will get a single *SupplierProfile* matching the *Event* is active at the *EventTime* and has a higher priority than the other matching *SupplierProfiles*. + +Depending on the *Strategy* defined in the *SupplierProfile*, further steps will be taken (ie: query cost, stats, ordering) for each of the individual *SupplierIDs* defined within the *SupplierProfile*. + +APIs logic +---------- + +GetSupplierProfilesForEvent +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Given the *Event* it will return a list of ordered *SupplierProfiles* matching at the *EventTime*. + +This API is useful to test configurations. + + +GetSuppliers +^^^^^^^^^^^^ + +Will return a list of *Suppliers* from within a *SupplierProfile* ordered based on *Strategy*. + + +Parameters +---------- + + +SupplierS +^^^^^^^^^ + +**SupplierS** is the **CGRateS** component responsible for handling the *SupplierProfiles*. + +It is configured within **suppliers** section from :ref:`JSON configuration ` via the following parameters: + +enabled + Will enable starting of the service. Possible values: . + +indexed_selects + Enable profile matching exclusively on indexes. If not enabled, the *SupplierProfiles* are checked one by one which for a larger number can slow down the processing time. Possible values: . + +string_indexed_fields + Query string indexes based only on these fields for faster processing. If commented out, each field from the event will be checked against indexes. If defined as empty list, no fields will be checked. + +prefix_indexed_fields + Query prefix indexes based only on these fields for faster processing. If defined as empty list, no fields will be checked. + +nested_fields + Applied when all event fields are checked against indexes, and decides whether subfields are also checked. + +attributes_conns + Connections to AttributeS for altering events before supplier queries. If undefined, fields modifications are disabled. + +resources_conns + Connections to ResourceS for *res sorting, empty to disable functionality. + +stats_conns + Connections to StatS for *stats sorting, empty to disable stats functionality. + +default_ratio + Default ratio used in case of *load strategy + + +SupplierProfile +^^^^^^^^^^^^^^^ + +Contains the configuration for a set of suppliers which will be returned in case of match. Following fields can be defined: + +Tenant + The tenant on the platform (one can see the tenant as partition ID). + +ID + The profile identificator. + +FilterIDs + List of *FilterProfileIDs* which should match in order to consider the profile matching the event. + +ActivationInterval + The time interval when this profile becomes active. If undefined, the profile is always active. Other options are start time, end time or both. + +Sorting + Sorting strategy applied when ordering the individual *Suppliers* defined bellow. Possible values are: + + **\*weight** + Classic method of statically sorting the suppliers based on their priority. + + **\*lc** + LeastCost will sort the suppliers based on their cost (lowest cost will have higher priority). If two suppliers will be identical as cost, their *Weight* will influence the sorting further. If *AccountIDs* will be specified, bundles can be also used during cost calculation, the only condition is that the bundles should cover complete usage. + + The following fields are mandatory for cost calculation: *Account*/*Subject*, *Destination*, *SetupTime*. *Usage* is optional and if present in event, it will be used for the cost calculation. + + **\*hc** + HighestCost will sort the suppliers based on their cost(higher cost will have higher priority). If two suppliers will be identical as cost, their *Weight* will influence the sorting further. + + The following fields are mandatory for cost calculation: *Account*/*Subject*, *Destination*, *SetupTime*. *Usage* is optional and if present in event, it will be used for the cost calculation. + + **\*qos** + QualityOfService strategy will sort the suppliers based on their stats. It takes the StatIDs to check from the supplier *StatIDs* definition. The metrics used as part of sorting are to be defined in *SortingParameters* field bellow. If Stats are missing the metrics defined in *SortingParameters* defaults for those will be populated for order (10000000 as PDD and -1 for the rest). + + **\*reas** + ResourceAscendentSorter will sort the suppliers based on their resource usage, lowest usage giving higher priority. The resources will be queried for each supplier based on it's *ResourceIDs* field and the final usage for each supplier will be given by the sum of all the resource usages queried. + + **\*reds** + ResourceDescendentSorter will sort the suppliers based on their resource usage, highest usage giving higher priority. The resources will be queried for each supplier based on it's *ResourceIDs* field and the final usage for each supplier will be given by the sum of all the resource usages queried. + + **\*load** + LoadDistribution will sort the suppliers based on their load. An important parameter is the *\*ratio* which is defined as *supplierID:Ratio* within the SortingParameters. If no supplierID is present within SortingParameters, the system will look for *\*default* or fallback in the configuration to *default_ratio* within :ref:`JSON configuration `. The *\*ratio* will specify the probability to get traffic on a *Supplier*, the higher the *\*ratio* more chances will a *Supplier* get for traffic. + + The load will be calculated out of the *StatIDs* parameter of each *Supplier*. It is possible to also specify there directly the metric being used in the format *StatID:MetricID*. If only *StatID* is instead specified, all metrics will be summed to get the final value. + + +SortingParameters + Will define additional parameters for each strategy. Following extra parameters are available(based on strategy): + + **\*qos** + List of metrics to be used for sorting in order of importance. + +Weight + Priority in case of multiple *SupplierProfiles* matching an *Event*. Higher *Weight* will have more priority. + +Suppliers + List of *Supplier* objects which are part of this *SupplierProfile* + + +Supplier +^^^^^^^^ + +The *Supplier* represents one supplier within the *SupplierProfile*. Following parameters are defined for it: + +ID + Supplier ID, will be returned via APIs. Should be known on the remote side and match some business logic (ie: gateway id or directly an IP address). + +FilterIDs + List of *FilterProfileIDs* which should match in order to consider the *Supplier* in use/active. + +AccountIDs + List of account IDs which should be checked in case of some strategies (ie: *lc, *hc). + +RatingPlanIDs + List of RatingPlanIDs which should be checked in case of some strategies (ie: *lc, *hc). + +ResourceIDs + List of ResourceIDs which should be checked in case of some strategies (ie: *reas or *reds). + +StatIDs + List of StatIDs which should be checked in case of some strategies (ie: *qos or *load). Can also be defined as *StatID:MetricID*. + +Weight + Used for sorting in some strategies (ie: *weight, *lc or *hc). + +Blocker + No more suppliers are provided after this one. + +SupplierParameters + Container which is trasparently passed to the remote client to be used in it's own logic (ie: gateway prefix stripping or other gateway parameters). + + + +Use cases +--------- + +* Calculate LCR directly by querying APIs (GetSuppliers). +* LCR system together with Kamailio_ *dispatcher* module where the *SupplierID* whithin *CGRateS* will be used as dispatcher set within Kamailio_. +* LCR system together with OpenSIPS_ drouting module where the *SupplierID* whithin *CGRateS* will be used as drouting carrier id. +* LCR system together with FreeSWITCH_ or Asterisk_ where the *SupplierID* whithin *CGRateS* will be used as gateway ID within the dialplan of FreesWITCH_ or Asterisk_. \ No newline at end of file diff --git a/engine/suppliers.go b/engine/suppliers.go index 2116a6c2e..3648aa109 100644 --- a/engine/suppliers.go +++ b/engine/suppliers.go @@ -331,16 +331,23 @@ func (spS *SupplierService) statMetricsForLoadDistribution(statIDs []string, ten // check if we get an ID in the following form (StatID:MetricID) statWithMetric := strings.Split(statID, utils.InInFieldSep) var metrics map[string]float64 - if err = spS.connMgr.Call(spS.cgrcfg.SupplierSCfg().StatSConns, nil, utils.StatSv1GetQueueFloatMetrics, - &utils.TenantIDWithArgDispatcher{TenantID: &utils.TenantID{Tenant: tenant, ID: statWithMetric[0]}}, &metrics); err != nil && + if err = spS.connMgr.Call( + spS.cgrcfg.SupplierSCfg().StatSConns, nil, + utils.StatSv1GetQueueFloatMetrics, + &utils.TenantIDWithArgDispatcher{ + TenantID: &utils.TenantID{ + Tenant: tenant, ID: statWithMetric[0]}}, + &metrics); err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning( - fmt.Sprintf(" error: %s getting statMetrics for stat : %s", err.Error(), statWithMetric[0])) + fmt.Sprintf(" error: %s getting statMetrics for stat : %s", + err.Error(), statWithMetric[0])) } if len(statWithMetric) == 2 { // in case we have MetricID defined with StatID we consider only that metric // check if statQueue have metric defined if metricVal, has := metrics[statWithMetric[1]]; !has { - return 0, fmt.Errorf("<%s> error: %s metric %s for statID: %s", utils.SupplierS, utils.ErrNotFound, statWithMetric[1], statWithMetric[0]) + return 0, fmt.Errorf("<%s> error: %s metric %s for statID: %s", + utils.SupplierS, utils.ErrNotFound, statWithMetric[1], statWithMetric[0]) } else { provStsMetrics[statWithMetric[1]] = append(provStsMetrics[statWithMetric[1]], metricVal) }