Replace RSRFields in FsAgentConfig with RSRParsers

This commit is contained in:
Trial97
2018-11-23 15:49:26 +02:00
committed by Dan Christian Bogos
parent 811dfbe20f
commit ea47d051ec
7 changed files with 77 additions and 58 deletions

View File

@@ -297,60 +297,60 @@ func (fsev FSEvent) GetExtraFields() map[string]string {
config.CgrConfig().GeneralCfg().DefaultTimezone); err != nil {
utils.Logger.Warning(fmt.Sprintf("<%s> error: %s parsing event rule: %+v", utils.FreeSWITCHAgent, err.Error(), fldRule))
} else {
extraFields[fldRule.Id] = parsed
extraFields[fldRule.AttrName()] = parsed
}
}
return extraFields
}
// Used in derived charging and sittuations when we need to run regexp on fields
func (fsev FSEvent) ParseEventValue(rsrFld *utils.RSRField, timezone string) (parsed string, err error) {
switch rsrFld.Id {
func (fsev FSEvent) ParseEventValue(rsrFld *config.RSRParser, timezone string) (parsed string, err error) {
switch rsrFld.AttrName() {
case utils.ToR:
return rsrFld.Parse(utils.VOICE)
return rsrFld.ParseValue(utils.VOICE)
case utils.OriginID:
return rsrFld.Parse(fsev.GetUUID())
return rsrFld.ParseValue(fsev.GetUUID())
case utils.OriginHost:
return rsrFld.Parse(utils.FirstNonEmpty(fsev[VarCGROriginHost], fsev[FS_IPv4]))
return rsrFld.ParseValue(utils.FirstNonEmpty(fsev[VarCGROriginHost], fsev[FS_IPv4]))
case utils.Source:
return rsrFld.Parse("FS_EVENT")
return rsrFld.ParseValue("FS_EVENT")
case utils.RequestType:
return rsrFld.Parse(fsev.GetReqType(""))
return rsrFld.ParseValue(fsev.GetReqType(""))
case utils.Direction:
return rsrFld.Parse(fsev.GetDirection(""))
return rsrFld.ParseValue(fsev.GetDirection(""))
case utils.Tenant:
return rsrFld.Parse(fsev.GetTenant(""))
return rsrFld.ParseValue(fsev.GetTenant(""))
case utils.Category:
return rsrFld.Parse(fsev.GetCategory(""))
return rsrFld.ParseValue(fsev.GetCategory(""))
case utils.Account:
return rsrFld.Parse(fsev.GetAccount(""))
return rsrFld.ParseValue(fsev.GetAccount(""))
case utils.Subject:
return rsrFld.Parse(fsev.GetSubject(""))
return rsrFld.ParseValue(fsev.GetSubject(""))
case utils.Destination:
return rsrFld.Parse(fsev.GetDestination(""))
return rsrFld.ParseValue(fsev.GetDestination(""))
case utils.SetupTime:
st, _ := fsev.GetSetupTime("", timezone)
return rsrFld.Parse(st.String())
return rsrFld.ParseValue(st.String())
case utils.AnswerTime:
at, _ := fsev.GetAnswerTime("", timezone)
return rsrFld.Parse(at.String())
return rsrFld.ParseValue(at.String())
case utils.Usage:
dur, _ := fsev.GetDuration("")
return rsrFld.Parse(strconv.FormatInt(dur.Nanoseconds(), 10))
return rsrFld.ParseValue(strconv.FormatInt(dur.Nanoseconds(), 10))
case utils.PDD:
PDD, _ := fsev.GetPdd(utils.META_DEFAULT)
return rsrFld.Parse(strconv.FormatFloat(PDD.Seconds(), 'f', -1, 64))
return rsrFld.ParseValue(strconv.FormatFloat(PDD.Seconds(), 'f', -1, 64))
case utils.SUPPLIER:
return rsrFld.Parse(fsev.GetSupplier(""))
return rsrFld.ParseValue(fsev.GetSupplier(""))
case utils.DISCONNECT_CAUSE:
return rsrFld.Parse(fsev.GetDisconnectCause(""))
return rsrFld.ParseValue(fsev.GetDisconnectCause(""))
case utils.RunID:
return rsrFld.Parse(utils.DEFAULT_RUNID)
return rsrFld.ParseValue(utils.DEFAULT_RUNID)
case utils.Cost:
return rsrFld.Parse(strconv.FormatFloat(-1, 'f', -1, 64)) // Recommended to use FormatCost
return rsrFld.ParseValue(strconv.FormatFloat(-1, 'f', -1, 64)) // Recommended to use FormatCost
default:
if parsed, err = rsrFld.Parse(fsev[rsrFld.Id]); err != nil {
parsed, err = rsrFld.Parse(fsev[FS_VARPREFIX+rsrFld.Id])
if parsed, err = rsrFld.ParseValue(fsev[rsrFld.AttrName()]); err != nil {
parsed, err = rsrFld.ParseValue(fsev[FS_VARPREFIX+rsrFld.AttrName()])
}
return
}

View File

@@ -498,63 +498,63 @@ func TestParseEventValue(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
config.SetCgrConfig(cfg)
ev := NewFSEvent(hangupEv)
if tor, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.ToR}, ""); tor != utils.VOICE {
if tor, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.ToR, true), ""); tor != utils.VOICE {
t.Error("Unexpected tor parsed", tor)
}
if accid, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.OriginID}, ""); accid != "e3133bf7-dcde-4daf-9663-9a79ffcef5ad" {
if accid, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.OriginID, true), ""); accid != "e3133bf7-dcde-4daf-9663-9a79ffcef5ad" {
t.Error("Unexpected result parsed", accid)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.OriginHost}, ""); parsed != "10.0.3.15" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.OriginHost, true), ""); parsed != "10.0.3.15" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Source}, ""); parsed != "FS_EVENT" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Source, true), ""); parsed != "FS_EVENT" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.RequestType}, ""); parsed != utils.META_PREPAID {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.RequestType, true), ""); parsed != utils.META_PREPAID {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Direction}, ""); parsed != utils.OUT {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Direction, true), ""); parsed != utils.OUT {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Tenant}, ""); parsed != "cgrates.org" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Tenant, true), ""); parsed != "cgrates.org" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Category}, ""); parsed != "call" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Category, true), ""); parsed != "call" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Account}, ""); parsed != "1001" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Account, true), ""); parsed != "1001" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Subject}, ""); parsed != "1001" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Subject, true), ""); parsed != "1001" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Destination}, ""); parsed != "1003" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Destination, true), ""); parsed != "1003" {
t.Error("Unexpected result parsed", parsed)
}
sTime, _ := utils.ParseTimeDetectLayout("1436280728471153"[:len("1436280728471153")-6], "") // We discard nanoseconds information so we can correlate csv
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.SetupTime}, ""); parsed != sTime.String() {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.SetupTime, true), ""); parsed != sTime.String() {
t.Errorf("Expecting: %s, parsed: %s", sTime.String(), parsed)
}
aTime, _ := utils.ParseTimeDetectLayout("1436280728971147"[:len("1436280728971147")-6], "")
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.AnswerTime}, ""); parsed != aTime.String() {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.AnswerTime, true), ""); parsed != aTime.String() {
t.Errorf("Expecting: %s, parsed: %s", aTime.String(), parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.Usage}, ""); parsed != "66000000000" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.Usage, true), ""); parsed != "66000000000" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.PDD}, ""); parsed != "0.028" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.PDD, true), ""); parsed != "0.028" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.SUPPLIER}, ""); parsed != "supplier1" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.SUPPLIER, true), ""); parsed != "supplier1" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.RunID}, ""); parsed != utils.DEFAULT_RUNID {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.RunID, true), ""); parsed != utils.DEFAULT_RUNID {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: utils.COST}, ""); parsed != "-1" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+utils.COST, true), ""); parsed != "-1" {
t.Error("Unexpected result parsed", parsed)
}
if parsed, _ := ev.ParseEventValue(&utils.RSRField{Id: "Hangup-Cause"}, ""); parsed != "NORMAL_CLEARING" {
if parsed, _ := ev.ParseEventValue(config.NewRSRParserMustCompile("~"+"Hangup-Cause", true), ""); parsed != "NORMAL_CLEARING" {
t.Error("Unexpected result parsed", parsed)
}
}
@@ -616,10 +616,16 @@ func TestFsEvAsMapStringInterface(t *testing.T) {
func TestFsEvGetExtraFields(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
cfg.FsAgentCfg().ExtraFields = []*utils.RSRField{
{Id: "Channel-Read-Codec-Name"},
{Id: "Channel-Write-Codec-Name"},
{Id: "NonExistingHeader"}}
var err error
err = nil
cfg.FsAgentCfg().ExtraFields, err = config.NewRSRParsersFromSlice([]string{
"~Channel-Read-Codec-Name",
"~Channel-Write-Codec-Name",
"~NonExistingHeader",
}, true)
if err != nil {
t.Error(err)
}
config.SetCgrConfig(cfg)
ev := NewFSEvent(hangupEv)
expectedExtraFields := map[string]string{

View File

@@ -170,11 +170,21 @@ func testCDReFromFolder(t *testing.T) {
// Test CDR from external sources
func testCDReProcessExternalCdr(t *testing.T) {
cdr := &engine.ExternalCDR{ToR: utils.VOICE,
OriginID: "testextcdr1", OriginHost: "127.0.0.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED,
Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1001",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
Usage: "1s", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
cdr := &engine.ExternalCDR{
ToR: utils.VOICE,
OriginID: "testextcdr1",
OriginHost: "127.0.0.1",
Source: utils.UNIT_TEST,
RequestType: utils.META_RATED,
Tenant: "cgrates.org",
Category: "call",
Account: "1003",
Subject: "1003",
Destination: "1001",
SetupTime: "2014-08-04T13:00:00Z",
AnswerTime: "2014-08-04T13:00:07Z",
Usage: "1s",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
if err := cdreRPC.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil {

View File

@@ -738,7 +738,7 @@ func TestCgrCfgJSONDefaultsFsAgentConfig(t *testing.T) {
{Address: "*internal"}},
SubscribePark: true,
CreateCdr: false,
ExtraFields: nil,
ExtraFields: RSRParsers{},
EmptyBalanceContext: "",
EmptyBalanceAnnFile: "",
MaxWaitConnection: 2 * time.Second,
@@ -751,7 +751,7 @@ func TestCgrCfgJSONDefaultsFsAgentConfig(t *testing.T) {
}
if !reflect.DeepEqual(cgrCfg.fsAgentCfg, eFsAgentCfg) {
t.Errorf("received: %+v, expecting: %+v", cgrCfg.fsAgentCfg, eFsAgentCfg)
t.Errorf("received: %+v, expecting: %+v", utils.ToJSON(cgrCfg.fsAgentCfg), utils.ToJSON(eFsAgentCfg))
}
}

View File

@@ -248,7 +248,7 @@ type FsAgentCfg struct {
SessionSConns []*HaPoolConfig
SubscribePark bool
CreateCdr bool
ExtraFields []*utils.RSRField
ExtraFields RSRParsers
//MinDurLowBalance time.Duration
//LowBalanceAnnFile string
EmptyBalanceContext string
@@ -279,7 +279,7 @@ func (self *FsAgentCfg) loadFromJsonCfg(jsnCfg *FreeswitchAgentJsonCfg) error {
self.CreateCdr = *jsnCfg.Create_cdr
}
if jsnCfg.Extra_fields != nil {
if self.ExtraFields, err = utils.ParseRSRFieldsFromSlice(*jsnCfg.Extra_fields); err != nil {
if self.ExtraFields, err = NewRSRParsersFromSlice(*jsnCfg.Extra_fields, true); err != nil {
return err
}
}

View File

@@ -163,6 +163,7 @@ func TestFsAgentCfgloadFromJsonCfg2(t *testing.T) {
SessionSConns: []*HaPoolConfig{{Address: "*internal"}},
SubscribePark: true,
MaxWaitConnection: time.Duration(2 * time.Second),
ExtraFields: RSRParsers{},
EventSocketConns: []*FsConnCfg{{
Address: "127.0.0.1:8021",
Password: "ClueCon",

View File

@@ -171,12 +171,14 @@ func cdrLogAction(acc *Account, a *Action, acs Actions, extraData interface{}) (
action.Balance == nil {
continue // Only log specific actions
}
cdr := &CDR{RunID: action.ActionType,
cdr := &CDR{
RunID: action.ActionType,
Source: CDRLOG,
SetupTime: time.Now(), AnswerTime: time.Now(),
OriginID: utils.GenUUID(),
ExtraFields: make(map[string]string),
PreRated: true}
PreRated: true,
}
cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.SetupTime.String())
cdr.Usage = time.Duration(1)
elem := reflect.ValueOf(cdr).Elem()