Merge pull request #762 from TeoV/master

Add DDC metric and test for it
This commit is contained in:
Dan Christian Bogos
2017-09-28 11:07:37 +02:00
committed by GitHub
4 changed files with 188 additions and 1 deletions

View File

@@ -1,2 +1,3 @@
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],MinItems[6],Recurrent[7],MinSleep[8],Blocker[9],Stored[10],Weight[11],ActionIDs[12]
Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,,1.2,10,true,1s,true,true,10,THRESH1;THRESH2
Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,,1.2,10,true,1s,true,true,10,THRESH1;THRESH2
1 #Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],MinItems[6],Recurrent[7],MinSleep[8],Blocker[9],Stored[10],Weight[11],ActionIDs[12]
1 #Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],MinItems[6],Recurrent[7],MinSleep[8],Blocker[9],Stored[10],Weight[11],ActionIDs[12]
2 #Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],MinItems[6],Recurrent[7],MinSleep[8],Blocker[9],Stored[10],Weight[11],ActionIDs[12] Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,,1.2,10,true,1s,true,true,10,THRESH1;THRESH2
3

View File

@@ -128,6 +128,22 @@ func (se StatEvent) Pdd(timezone string) (pdd time.Duration, err error) {
return utils.ParseDurationWithSecs(pddStr)
}
// Destination returns the Destination of StatEvent
func (se StatEvent) Destination(timezone string) (ddc string, err error) {
ddcIf, has := se.Fields[utils.DESTINATION]
if !has {
return ddc, utils.ErrNotFound
}
if ddcInt, canCast := ddcIf.(int64); canCast {
return strconv.FormatInt(ddcInt, 64), nil
}
ddcStr, canCast := ddcIf.(string)
if !canCast {
return ddc, errors.New("cannot cast to string")
}
return ddcStr, nil
}
// NewStoredStatQueue initiates a StoredStatQueue out of StatQueue
func NewStoredStatQueue(sq *StatQueue, ms Marshaler) (sSQ *StoredStatQueue, err error) {
sSQ = &StoredStatQueue{

View File

@@ -36,6 +36,7 @@ func NewStatMetric(metricID string) (sm StatMetric, err error) {
utils.MetaACC: NewACC,
utils.MetaTCC: NewTCC,
utils.MetaPDD: NewPDD,
utils.MetaDDC: NewDCC,
}
if _, has := metrics[metricID]; !has {
return nil, fmt.Errorf("unsupported metric: %s", metricID)
@@ -549,3 +550,72 @@ func (pdd *StatPDD) Marshal(ms Marshaler) (marshaled []byte, err error) {
func (pdd *StatPDD) LoadMarshaled(ms Marshaler, marshaled []byte) (err error) {
return ms.Unmarshal(marshaled, pdd)
}
func NewDCC() (StatMetric, error) {
return &StatDDC{Destinations: make(map[string]utils.StringMap), EventDestinations: make(map[string]string)}, nil
}
type StatDDC struct {
Destinations map[string]utils.StringMap
EventDestinations map[string]string // map[EventTenantID]Destination
}
func (ddc *StatDDC) GetStringValue(fmtOpts string) (val string) {
if len(ddc.Destinations) == 0 {
return utils.NOT_AVAILABLE
}
return fmt.Sprintf("%+v", len(ddc.Destinations))
}
func (ddc *StatDDC) GetValue() (v interface{}) {
return len(ddc.Destinations)
}
func (ddc *StatDDC) GetFloat64Value() (v float64) {
if len(ddc.Destinations) == 0 {
return -1.0
}
return float64(len(ddc.Destinations))
}
func (ddc *StatDDC) AddEvent(ev *StatEvent) (err error) {
var dest string
if at, err := ev.AnswerTime(config.CgrConfig().DefaultTimezone); err != nil &&
err != utils.ErrNotFound {
return err
} else if !at.IsZero() {
if destination, err := ev.Destination(config.CgrConfig().DefaultTimezone); err != nil {
return err
} else {
dest = destination
if _, has := ddc.Destinations[dest]; !has {
ddc.Destinations[dest] = make(map[string]bool)
}
ddc.Destinations[dest][ev.TenantID()] = true
}
}
ddc.EventDestinations[ev.TenantID()] = dest
return
}
func (ddc *StatDDC) RemEvent(evTenantID string) (err error) {
destination, has := ddc.EventDestinations[evTenantID]
if !has {
return utils.ErrNotFound
}
if len(ddc.Destinations[destination]) == 1 {
delete(ddc.Destinations, destination)
} else {
delete(ddc.Destinations[destination], evTenantID)
}
delete(ddc.EventDestinations, evTenantID)
return
}
func (ddc *StatDDC) Marshal(ms Marshaler) (marshaled []byte, err error) {
return ms.Marshal(DDC)
}
func (ddc *StatDDC) LoadMarshaled(ms Marshaler, marshaled []byte) (err error) {
return ms.Unmarshal(marshaled, ddc)
}

View File

@@ -832,3 +832,103 @@ func TestPDDGetValue(t *testing.T) {
t.Errorf("wrong pdd value: %+v", v)
}
}
func TestDDCGetStringValue(t *testing.T) {
ddc, _ := NewDCC()
ev := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_1",
Fields: map[string]interface{}{
"AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
utils.DESTINATION: "1002"}}
if strVal := ddc.GetStringValue(""); strVal != utils.NOT_AVAILABLE {
t.Errorf("wrong ddc value: %s", strVal)
}
ddc.AddEvent(ev)
if strVal := ddc.GetStringValue(""); strVal != "1" {
t.Errorf("wrong ddc value: %s", strVal)
}
ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2",
Fields: map[string]interface{}{
"AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
utils.DESTINATION: "1002"}}
ev3 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_3",
Fields: map[string]interface{}{
"AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
utils.DESTINATION: "1001"}}
ddc.AddEvent(ev2)
ddc.AddEvent(ev3)
if strVal := ddc.GetStringValue(""); strVal != "2" {
t.Errorf("wrong ddc value: %s", strVal)
}
ddc.RemEvent(ev.TenantID())
if strVal := ddc.GetStringValue(""); strVal != "2" {
t.Errorf("wrong ddc value: %s", strVal)
}
ddc.RemEvent(ev2.TenantID())
if strVal := ddc.GetStringValue(""); strVal != "1" {
t.Errorf("wrong ddc value: %s", strVal)
}
ddc.RemEvent(ev3.TenantID())
if strVal := ddc.GetStringValue(""); strVal != utils.NOT_AVAILABLE {
t.Errorf("wrong ddc value: %s", strVal)
}
}
func TestDDCGetFloat64Value(t *testing.T) {
ddc, _ := NewDCC()
ev := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_1",
Fields: map[string]interface{}{
"AnswerTime": time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
"Usage": time.Duration(10 * time.Second),
utils.PDD: time.Duration(5 * time.Second),
utils.DESTINATION: "1002"}}
ddc.AddEvent(ev)
if v := ddc.GetFloat64Value(); v != 1 {
t.Errorf("wrong ddc value: %v", v)
}
ev2 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_2"}
ddc.AddEvent(ev2)
if v := ddc.GetFloat64Value(); v != 1 {
t.Errorf("wrong ddc value: %v", v)
}
ev4 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_4",
Fields: map[string]interface{}{
"Usage": time.Duration(1 * time.Minute),
"AnswerTime": time.Date(2015, 7, 14, 14, 25, 0, 0, time.UTC),
utils.PDD: time.Duration(10 * time.Second),
utils.DESTINATION: "1001",
},
}
ev5 := &StatEvent{Tenant: "cgrates.org", ID: "EVENT_5",
Fields: map[string]interface{}{
"Usage": time.Duration(1*time.Minute + 30*time.Second),
"AnswerTime": time.Date(2015, 7, 14, 14, 25, 0, 0, time.UTC),
utils.DESTINATION: "1003",
},
}
ddc.AddEvent(ev4)
if strVal := ddc.GetFloat64Value(); strVal != 2 {
t.Errorf("wrong ddc value: %v", strVal)
}
ddc.AddEvent(ev5)
if strVal := ddc.GetFloat64Value(); strVal != 3 {
t.Errorf("wrong ddc value: %v", strVal)
}
ddc.RemEvent(ev2.TenantID())
if strVal := ddc.GetFloat64Value(); strVal != 3 {
t.Errorf("wrong pdd value: %v", strVal)
}
ddc.RemEvent(ev4.TenantID())
if strVal := ddc.GetFloat64Value(); strVal != 2 {
t.Errorf("wrong ddc value: %v", strVal)
}
ddc.RemEvent(ev.TenantID())
if strVal := ddc.GetFloat64Value(); strVal != 1 {
t.Errorf("wrong ddc value: %v", strVal)
}
ddc.RemEvent(ev5.TenantID())
if strVal := ddc.GetFloat64Value(); strVal != -1.0 {
t.Errorf("wrong ddc value: %v", strVal)
}
}