mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-23 16:18:44 +05:00
Update QOS strategy to take the average of metrics
This commit is contained in:
committed by
Dan Christian Bogos
parent
8f7f414d0c
commit
cc818b0199
@@ -20,11 +20,9 @@ package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -95,29 +93,21 @@ func (sSpls *SortedSuppliers) SortHighestCost() {
|
||||
// SortQOS is part of sort interface,
|
||||
// sort based on Stats
|
||||
func (sSpls *SortedSuppliers) SortQOS(params []string) {
|
||||
//sort the metrics before sorting the suppliers
|
||||
for _, val := range sSpls.SortedSuppliers {
|
||||
for _, iface := range val.SortingData {
|
||||
if castedVal, canCast := iface.(SplStatMetrics); canCast {
|
||||
castedVal.Sort()
|
||||
}
|
||||
}
|
||||
}
|
||||
//sort suppliers
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
for _, param := range params {
|
||||
//in case we have the same value for the current param we skip to the next one
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(SplStatMetrics)[0].MetricValue == sSpls.SortedSuppliers[j].SortingData[param].(SplStatMetrics)[0].MetricValue {
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(float64) == sSpls.SortedSuppliers[j].SortingData[param].(float64) {
|
||||
continue
|
||||
}
|
||||
switch sSpls.SortedSuppliers[i].SortingData[param].(SplStatMetrics)[0].metricType {
|
||||
switch param {
|
||||
default:
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(SplStatMetrics)[0].MetricValue > sSpls.SortedSuppliers[j].SortingData[param].(SplStatMetrics)[0].MetricValue {
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(float64) > sSpls.SortedSuppliers[j].SortingData[param].(float64) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case utils.MetaPDD: //in case of pdd the smalles value if the best
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(SplStatMetrics)[0].MetricValue < sSpls.SortedSuppliers[j].SortingData[param].(SplStatMetrics)[0].MetricValue {
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(float64) < sSpls.SortedSuppliers[j].SortingData[param].(float64) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -191,98 +181,3 @@ func (ssd SupplierSortDispatcher) SortSuppliers(prflID, strategy string,
|
||||
}
|
||||
return sd.SortSuppliers(prflID, suppls, suplEv, extraOpts)
|
||||
}
|
||||
|
||||
//StatMetric used to store the statID and the metric value
|
||||
type SplStatMetric struct {
|
||||
StatID string
|
||||
MetricValue float64
|
||||
|
||||
metricType string
|
||||
}
|
||||
|
||||
//StatMetrics is a sortable list of StatMetric
|
||||
type SplStatMetrics []*SplStatMetric
|
||||
|
||||
// Sort is part of sort interface, sort based on Weight
|
||||
func (sm SplStatMetrics) Sort() {
|
||||
sort.Slice(sm, func(i, j int) bool {
|
||||
switch sm[i].metricType {
|
||||
default:
|
||||
return sm[i].MetricValue < sm[j].MetricValue
|
||||
case utils.MetaPDD: // in case of PDD we take the greater value
|
||||
return sm[i].MetricValue > sm[j].MetricValue
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// newSplDataProvider constructs a DataProvider
|
||||
func newSplDataProvider(event, sortingData map[string]interface{}) (dP config.DataProvider) {
|
||||
for _, iface := range sortingData {
|
||||
if castedVal, canCast := iface.(SplStatMetrics); canCast {
|
||||
castedVal.Sort()
|
||||
}
|
||||
}
|
||||
dP = &supplierDP{event: config.NewNavigableMap(event), sortingData: sortingData, cache: config.NewNavigableMap(nil)}
|
||||
return
|
||||
}
|
||||
|
||||
// supplierDP implements engine.DataProvider
|
||||
type supplierDP struct {
|
||||
event *config.NavigableMap
|
||||
sortingData map[string]interface{}
|
||||
cache *config.NavigableMap
|
||||
}
|
||||
|
||||
// String is part of engine.DataProvider interface
|
||||
// when called, it will display the already parsed values out of cache
|
||||
func (sDP *supplierDP) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// FieldAsInterface is part of engine.DataProvider interface
|
||||
func (sDP *supplierDP) FieldAsInterface(fldPath []string) (data interface{}, err error) {
|
||||
if data, err = sDP.cache.FieldAsInterface(fldPath); err != nil {
|
||||
if err != utils.ErrNotFound { // item found in cache
|
||||
return
|
||||
}
|
||||
err = nil // cancel previous err
|
||||
} else {
|
||||
return // data found in cache
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.MetaReq:
|
||||
data, err = sDP.event.FieldAsInterface(fldPath[1:])
|
||||
case utils.MetaVars:
|
||||
if _, canCast := sDP.sortingData[fldPath[1]].(SplStatMetrics); canCast {
|
||||
data = sDP.sortingData[fldPath[1]].(SplStatMetrics)[0].MetricValue
|
||||
} else {
|
||||
data = sDP.sortingData[fldPath[1]]
|
||||
}
|
||||
}
|
||||
sDP.cache.Set(fldPath, data, false, false)
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsString is part of engine.DataProvider interface
|
||||
func (sDP *supplierDP) FieldAsString(fldPath []string) (data string, err error) {
|
||||
var valIface interface{}
|
||||
valIface, err = sDP.FieldAsInterface(fldPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
data, err = utils.IfaceAsString(valIface)
|
||||
return
|
||||
}
|
||||
|
||||
// AsNavigableMap is part of engine.DataProvider interface
|
||||
func (sDP *supplierDP) AsNavigableMap([]*config.FCTemplate) (
|
||||
nm *config.NavigableMap, err error) {
|
||||
return nil, utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
// RemoteHost is part of engine.DataProvider interface
|
||||
func (sDP *supplierDP) RemoteHost() net.Addr {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -279,204 +279,38 @@ func TestLibSuppliersSortHighestCost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLibSuppliersStatMetricSort(t *testing.T) {
|
||||
sm := SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 23.1},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.0},
|
||||
}
|
||||
sm.Sort()
|
||||
exp := SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.0},
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 23.1},
|
||||
}
|
||||
if !reflect.DeepEqual(exp, sm) {
|
||||
t.Errorf("Expecting: %s, received: %s",
|
||||
utils.ToJSON(exp), utils.ToJSON(sm))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLibSuppliersStatMetricSort2(t *testing.T) {
|
||||
sm := SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 10.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 23.1},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 10.0},
|
||||
}
|
||||
sm.Sort()
|
||||
exp := SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 23.1},
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 10.1},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 10.0},
|
||||
}
|
||||
if !reflect.DeepEqual(exp, sm) {
|
||||
t.Errorf("Expecting: %s, received: %s",
|
||||
utils.ToJSON(exp), utils.ToJSON(sm))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLibSuppliersSplDataProvide(t *testing.T) {
|
||||
//simulatedData simulate sortingData
|
||||
simulatedData := map[string]interface{}{
|
||||
utils.Cost: 12.45,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{
|
||||
StatID: utils.META_NONE,
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 9.0},
|
||||
&SplStatMetric{
|
||||
StatID: utils.META_NONE,
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.0},
|
||||
},
|
||||
utils.MetaPDD: SplStatMetrics{
|
||||
&SplStatMetric{
|
||||
StatID: utils.META_NONE,
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 12.0},
|
||||
&SplStatMetric{
|
||||
StatID: utils.META_NONE,
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 5.0},
|
||||
},
|
||||
}
|
||||
ev := map[string]interface{}{
|
||||
utils.Account: "1001",
|
||||
}
|
||||
sDP := newSplDataProvider(ev, simulatedData)
|
||||
exp := "1001"
|
||||
if rcv, err := sDP.FieldAsInterface([]string{utils.MetaReq, utils.Account}); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rcv, exp) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
|
||||
}
|
||||
exp2 := 12.45
|
||||
if rcv, err := sDP.FieldAsInterface([]string{utils.MetaVars, utils.Cost}); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rcv, exp2) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", exp2, rcv)
|
||||
}
|
||||
exp3 := 9.0
|
||||
if rcv, err := sDP.FieldAsInterface([]string{utils.MetaVars, utils.MetaACD}); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rcv, exp3) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", exp3, rcv)
|
||||
}
|
||||
exp4 := 12.0
|
||||
if rcv, err := sDP.FieldAsInterface([]string{utils.MetaVars, utils.MetaPDD}); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rcv, exp4) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", exp4, rcv)
|
||||
}
|
||||
}
|
||||
|
||||
//sort based on *acd and *tcd
|
||||
func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
sSpls := &SortedSuppliers{
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier1 for *acd is 0.5 , *tcd 1.1
|
||||
//the average value for supplier1 for *acd is 0.5 , *tcd 1.1
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Cost: 0.5,
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 23.1},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.0},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 1.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 12.1},
|
||||
},
|
||||
utils.Cost: 0.5,
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaACD: 0.5,
|
||||
utils.MetaTCD: 1.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier2 for *acd is 0.5 , *tcd 4.1
|
||||
//the average value for supplier2 for *acd is 0.5 , *tcd 4.1
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Cost: 0.1,
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 1.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 12.1},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 12.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 4.1},
|
||||
},
|
||||
utils.Cost: 0.1,
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: 0.5,
|
||||
utils.MetaTCD: 4.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier3 for *acd is 0.4 , *tcd 5.1
|
||||
//the average value for supplier3 for *acd is 0.4 , *tcd 5.1
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Cost: 1.1,
|
||||
utils.Weight: 17.8,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.4},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 2.1},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 6.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 5.1},
|
||||
},
|
||||
utils.Cost: 1.1,
|
||||
utils.Weight: 17.8,
|
||||
utils.MetaACD: 0.4,
|
||||
utils.MetaTCD: 5.1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -501,29 +335,12 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
sSpls := &SortedSuppliers{
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier1 for *acd is 0.5 , *tcd 1.1
|
||||
//the average value for supplier1 for *acd is 0.5 , *tcd 1.1
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.7},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.6},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 1.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 12.1},
|
||||
},
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaACD: 0.5,
|
||||
utils.MetaTCD: 1.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
@@ -532,50 +349,19 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
//will be sorted based on weight
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 17.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 1.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 12.1},
|
||||
},
|
||||
utils.Weight: 17.0,
|
||||
utils.MetaACD: 0.5,
|
||||
utils.MetaTCD: 1.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier1 for *acd is 0.5 , *tcd 1.1
|
||||
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Cost: 0.5,
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat3",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.5},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 1.2},
|
||||
},
|
||||
utils.Cost: 0.5,
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaACD: 0.7,
|
||||
utils.MetaTCD: 1.1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -603,60 +389,27 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
//will be sorted based on weight
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaPDD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 0.5},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.7},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 1.1},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 12.1},
|
||||
},
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaPDD: 0.7,
|
||||
utils.MetaTCD: 1.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier2 for *pdd is 1.2, *tcd 1.1
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaPDD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 0.9},
|
||||
&SplStatMetric{StatID: "SampleStat2",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 1.2},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 1.1},
|
||||
},
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaPDD: 1.2,
|
||||
utils.MetaTCD: 1.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
//the worst value for supplier3 for *pdd is 0.7, *tcd 10.1
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaPDD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaPDD,
|
||||
MetricValue: 0.7},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 10.1},
|
||||
},
|
||||
utils.Weight: 10.0,
|
||||
utils.MetaPDD: 0.7,
|
||||
utils.MetaTCD: 10.1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -680,61 +433,25 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.2},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 15.0},
|
||||
},
|
||||
utils.MetaASR: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaASR,
|
||||
MetricValue: 1.2},
|
||||
},
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
utils.MetaASR: 1.2,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.2},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 20.0},
|
||||
},
|
||||
utils.MetaASR: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaASR,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
utils.MetaASR: -1.0,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.1},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 10.0},
|
||||
},
|
||||
utils.MetaASR: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaASR,
|
||||
MetricValue: 1.2},
|
||||
},
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
utils.MetaASR: 1.2,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -758,76 +475,28 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.2},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 15.0},
|
||||
},
|
||||
utils.MetaASR: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaASR,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.MetaTCC: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCC,
|
||||
MetricValue: 10.1},
|
||||
},
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
utils.MetaASR: -1.0,
|
||||
utils.MetaTCC: 10.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.2},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 20.0},
|
||||
},
|
||||
utils.MetaASR: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaASR,
|
||||
MetricValue: 1.2},
|
||||
},
|
||||
utils.MetaTCC: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCC,
|
||||
MetricValue: 10.1},
|
||||
},
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
utils.MetaASR: 1.2,
|
||||
utils.MetaTCC: 10.1,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.1},
|
||||
},
|
||||
utils.MetaTCD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCD,
|
||||
MetricValue: 10.0},
|
||||
},
|
||||
utils.MetaASR: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaASR,
|
||||
MetricValue: 1.2},
|
||||
},
|
||||
utils.MetaTCC: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaTCC,
|
||||
MetricValue: 10.1},
|
||||
},
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
utils.MetaASR: 1.2,
|
||||
utils.MetaTCC: 10.1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -851,34 +520,22 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.2},
|
||||
},
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: 0.2,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 25.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.2},
|
||||
},
|
||||
utils.Weight: 25.0,
|
||||
utils.MetaACD: 0.2,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 20.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 0.1},
|
||||
},
|
||||
utils.Weight: 20.0,
|
||||
utils.MetaACD: 0.1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -902,34 +559,22 @@ func TestLibSuppliersSortQOS7(t *testing.T) {
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: -1.0,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 25.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.Weight: 25.0,
|
||||
utils.MetaACD: -1.0,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 20.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.Weight: 20.0,
|
||||
utils.MetaACD: -1.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -953,35 +598,22 @@ func TestLibSuppliersSortQOS8(t *testing.T) {
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.Weight: 15.0,
|
||||
utils.MetaACD: -1.0,
|
||||
},
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 25.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: -1.0},
|
||||
},
|
||||
utils.Weight: 25.0,
|
||||
utils.MetaACD: -1.0,
|
||||
},
|
||||
SupplierParameters: "param2",
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 20.0,
|
||||
utils.MetaACD: SplStatMetrics{
|
||||
&SplStatMetric{StatID: "SampleStat",
|
||||
metricType: utils.MetaACD,
|
||||
MetricValue: 10.0},
|
||||
},
|
||||
utils.Weight: 20.0,
|
||||
utils.MetaACD: 10.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -253,8 +253,9 @@ func (spS *SupplierService) costForEvent(ev *utils.CGREvent,
|
||||
|
||||
// statMetrics will query a list of statIDs and return composed metric values
|
||||
// first metric found is always returned
|
||||
func (spS *SupplierService) statMetrics(statIDs []string, tenant string) (stsMetric map[string]SplStatMetrics, err error) {
|
||||
stsMetric = make(map[string]SplStatMetrics)
|
||||
func (spS *SupplierService) statMetrics(statIDs []string, tenant string) (stsMetric map[string]float64, err error) {
|
||||
stsMetric = make(map[string]float64)
|
||||
provStsMetrics := make(map[string][]float64)
|
||||
if spS.statS != nil {
|
||||
for _, statID := range statIDs {
|
||||
var metrics map[string]float64
|
||||
@@ -265,9 +266,17 @@ func (spS *SupplierService) statMetrics(statIDs []string, tenant string) (stsMet
|
||||
fmt.Sprintf("<SupplierS> error: %s getting statMetrics for stat : %s", err.Error(), statID))
|
||||
}
|
||||
for key, val := range metrics {
|
||||
stsMetric[key] = append(stsMetric[key], &SplStatMetric{StatID: statID, metricType: key, MetricValue: val})
|
||||
//add value of metric in a slice in case that we get the same metric from different stat
|
||||
provStsMetrics[key] = append(provStsMetrics[key], val)
|
||||
}
|
||||
}
|
||||
for metric, slice := range provStsMetrics {
|
||||
sum := 0.0
|
||||
for _, val := range slice {
|
||||
sum += val
|
||||
}
|
||||
stsMetric[metric] = sum / float64(len(slice))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -348,9 +357,9 @@ func (spS *SupplierService) populateSortingData(ev *utils.CGREvent, spl *Supplie
|
||||
if _, hasMetric := metricSupp[metric]; !hasMetric {
|
||||
switch metric {
|
||||
default:
|
||||
sortedSpl.SortingData[metric] = SplStatMetrics{&SplStatMetric{StatID: utils.META_NONE, metricType: metric, MetricValue: -1.0}}
|
||||
sortedSpl.SortingData[metric] = -1.0
|
||||
case utils.MetaPDD:
|
||||
sortedSpl.SortingData[metric] = SplStatMetrics{&SplStatMetric{StatID: utils.META_NONE, metricType: metric, MetricValue: 10000000.0}}
|
||||
sortedSpl.SortingData[metric] = 10000000.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -373,10 +382,12 @@ func (spS *SupplierService) populateSortingData(ev *utils.CGREvent, spl *Supplie
|
||||
//filter the supplier
|
||||
if len(spl.FilterIDs) != 0 {
|
||||
//construct the DP and pass it to filterS
|
||||
sDP := newSplDataProvider(ev.Event, sortedSpl.SortingData)
|
||||
nM := config.NewNavigableMap(nil)
|
||||
nM.Set([]string{utils.MetaReq}, ev.Event, false, false)
|
||||
nM.Set([]string{utils.MetaVars}, sortedSpl.SortingData, false, false)
|
||||
|
||||
if pass, err = spS.filterS.Pass(ev.Tenant, spl.FilterIDs,
|
||||
sDP); err != nil {
|
||||
nM); err != nil {
|
||||
return nil, false, err
|
||||
} else if !pass {
|
||||
return nil, false, nil
|
||||
|
||||
Reference in New Issue
Block a user