Dynamic template for *cgrlog, RSRFields instead of RSRField in extra_params

This commit is contained in:
DanB
2015-04-30 13:28:59 +02:00
parent 35de85f130
commit e4a4732fee
3 changed files with 106 additions and 20 deletions

View File

@@ -128,11 +128,64 @@ func logAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (er
return
}
// Used by cdrLogAction to dynamically parse values out of account and action
func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) string {
dta, err := utils.NewDTAFromAccountKey(acnt.Id) // Account information should be valid
if err != nil {
dta = new(utils.DirectionTenantAccount) // Init with empty values
}
var parsedValue string // Template values
for _, rsrFld := range rsrFlds {
switch rsrFld.Id {
case "account_id":
parsedValue += rsrFld.ParseValue(acnt.Id)
case "direction":
parsedValue += rsrFld.ParseValue(dta.Direction)
case "tenant":
parsedValue += rsrFld.ParseValue(dta.Tenant)
case "account":
parsedValue += rsrFld.ParseValue(dta.Account)
case "action_id":
parsedValue += rsrFld.ParseValue(action.Id)
case "action_type":
parsedValue += rsrFld.ParseValue(action.ActionType)
case "balance_type":
parsedValue += rsrFld.ParseValue(action.BalanceType)
case "balance_uuid":
parsedValue += rsrFld.ParseValue(action.Balance.Uuid)
case "balance_id":
parsedValue += rsrFld.ParseValue(action.Balance.Id)
case "balance_value":
parsedValue += rsrFld.ParseValue(strconv.FormatFloat(action.Balance.Value, 'f', -1, 64))
case "destination_id":
parsedValue += rsrFld.ParseValue(action.Balance.DestinationId)
case "extra_params":
parsedValue += rsrFld.ParseValue(action.ExtraParameters)
case "rating_subject":
parsedValue += rsrFld.ParseValue(action.Balance.RatingSubject)
case "category":
parsedValue += rsrFld.ParseValue(action.Balance.Category)
case "shared_group":
parsedValue += rsrFld.ParseValue(action.Balance.SharedGroup)
default:
parsedValue += rsrFld.ParseValue("") // Mostly for static values
}
}
return parsedValue
}
func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
defaultTemplate := map[string]*utils.RSRField{
"CdrHost": utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP)[0],
"ReqType": utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP)[0],
"MediationRunId": utils.ParseRSRFieldsMustCompile("^"+utils.META_DEFAULT, utils.INFIELD_SEP)[0],
defaultTemplate := map[string]utils.RSRFields{
"TOR": utils.ParseRSRFieldsMustCompile("balance_type", utils.INFIELD_SEP),
"CdrHost": utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP),
"Direction": utils.ParseRSRFieldsMustCompile("direction", utils.INFIELD_SEP),
"ReqType": utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP),
"Tenant": utils.ParseRSRFieldsMustCompile("tenant", utils.INFIELD_SEP),
"Account": utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
"Subject": utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
"Cost": utils.ParseRSRFieldsMustCompile("balance_value", utils.INFIELD_SEP),
"MediationRunId": utils.ParseRSRFieldsMustCompile("^"+utils.META_DEFAULT, utils.INFIELD_SEP),
}
template := make(map[string]string)
@@ -142,7 +195,7 @@ func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions)
return
}
for field, rsr := range template {
defaultTemplate[field], err = utils.NewRSRField(rsr)
defaultTemplate[field], err = utils.ParseRSRFields(rsr, utils.INFIELD_SEP)
if err != nil {
return err
}
@@ -152,35 +205,32 @@ func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions)
// set stored cdr values
var cdrs []*StoredCdr
for _, action := range acs {
if !utils.IsSliceMember([]string{DEBIT, DEBIT_RESET}, action.ActionType) {
if !utils.IsSliceMember([]string{DEBIT, DEBIT_RESET}, action.ActionType) || action.Balance == nil {
continue // Only log specific actions
}
cdr := &StoredCdr{CdrSource: CDRLOG, SetupTime: time.Now(), AnswerTime: time.Now(), AccId: utils.GenUUID()}
cdr := &StoredCdr{CdrSource: CDRLOG, SetupTime: time.Now(), AnswerTime: time.Now(), AccId: utils.GenUUID(), ExtraFields: make(map[string]string)}
cdr.CgrId = utils.Sha1(cdr.AccId, cdr.SetupTime.String())
cdr.Usage = time.Duration(1) * time.Second
elem := reflect.ValueOf(cdr).Elem()
for key, rsr := range defaultTemplate {
for key, rsrFlds := range defaultTemplate {
parsedValue := parseTemplateValue(rsrFlds, acc, action)
field := elem.FieldByName(key)
if field.IsValid() && field.CanSet() {
switch field.Kind() {
case reflect.Float64:
value, err := strconv.ParseFloat(rsr.ParseValue(""), 64)
value, err := strconv.ParseFloat(parsedValue, 64)
if err != nil {
continue
}
field.SetFloat(value)
case reflect.String:
field.SetString(rsr.ParseValue(""))
field.SetString(parsedValue)
}
} else { // invalid fields go in extraFields of CDR
cdr.ExtraFields[key] = parsedValue
}
}
// Hardcode the data for now, expand it with templates later
cdr.TOR = action.BalanceType
cdr.Direction = action.Direction
if action.Balance != nil {
cdr.Cost = action.Balance.Value
}
Logger.Debug(fmt.Sprintf("action: %+v, balance: %+v", action, action.Balance))
//Logger.Debug(fmt.Sprintf("account: %+v, action: %+v, balance: %+v", acc, action, action.Balance))
cdrs = append(cdrs, cdr)
if cdrStorage == nil { // Only save if the cdrStorage is defined
continue

View File

@@ -111,6 +111,9 @@ func TestActionsLocalSetCdrlogActions(t *testing.T) {
rcvedCdrs[0].CdrHost != "127.0.0.1" ||
rcvedCdrs[0].CdrSource != CDRLOG ||
rcvedCdrs[0].ReqType != utils.META_PREPAID ||
rcvedCdrs[0].Tenant != "cgrates.org" ||
rcvedCdrs[0].Account != "dan2904" ||
rcvedCdrs[0].Subject != "dan2904" ||
rcvedCdrs[0].Usage != "1" ||
rcvedCdrs[0].MediationRunId != utils.META_DEFAULT ||
rcvedCdrs[0].Cost != attrsAA.Actions[0].Units {

View File

@@ -1113,12 +1113,14 @@ func TestTopupActionLoaded(t *testing.T) {
}
func TestActionCdrlogEmpty(t *testing.T) {
acnt := &Account{Id: "*out:cgrates.org:dan2904"}
cdrlog := &Action{
ActionType: CDRLOG,
}
err := cdrLogAction(nil, nil, cdrlog, Actions{
err := cdrLogAction(acnt, nil, cdrlog, Actions{
&Action{
ActionType: DEBIT,
Balance: &Balance{Value: 25, DestinationId: "RET", Weight: 20},
},
})
if err != nil {
@@ -1132,16 +1134,19 @@ func TestActionCdrlogEmpty(t *testing.T) {
}
func TestActionCdrlogWithParams(t *testing.T) {
acnt := &Account{Id: "*out:cgrates.org:dan2904"}
cdrlog := &Action{
ActionType: CDRLOG,
ExtraParameters: `{"Account":"^dan","Subject": "^rif","Destination":"^1234","Tor":"~action_tag:s/^at(.)$/0$1/"}`,
ExtraParameters: `{"ReqType":"^*pseudoprepaid","Subject":"^rif", "TOR":"~action_type:s/^\\*(.*)$/did_$1/"}`,
}
err := cdrLogAction(nil, nil, cdrlog, Actions{
err := cdrLogAction(acnt, nil, cdrlog, Actions{
&Action{
ActionType: DEBIT,
Balance: &Balance{Value: 25, DestinationId: "RET", Weight: 20},
},
&Action{
ActionType: DEBIT_RESET,
Balance: &Balance{Value: 25, DestinationId: "RET", Weight: 20},
},
})
if err != nil {
@@ -1155,6 +1160,34 @@ func TestActionCdrlogWithParams(t *testing.T) {
}
}
/*
func TestActionCdrLogParamsOverload(t *testing.T) {
cdrlog := &Action{
ActionType: CDRLOG,
ExtraParameters: `{"Account":"^dan","Subject": "^rif","Destination":"^1234","Tor":"~action_tag:s/^at(.)$/0$1/"}`,
}
err := cdrLogAction(nil, nil, cdrlog, Actions{
&Action{
ActionType: DEBIT,
Balance: &Balance{Value: 25, DestinationId: "RET", Weight: 20},
},
&Action{
ActionType: DEBIT_RESET,
Balance: &Balance{Value: 25, DestinationId: "RET", Weight: 20},
},
})
if err != nil {
t.Error("Error performing cdrlog action: ", err)
}
cdrs := make([]*StoredCdr, 0)
json.Unmarshal([]byte(cdrlog.ExpirationString), &cdrs)
if len(cdrs) != 2 ||
cdrs[0].Subject != "rif" {
t.Errorf("Wrong cdrlogs: %+v", cdrs[0])
}
}
*/
/********************************** Benchmarks ********************************/
func BenchmarkUUID(b *testing.B) {