mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Dynamic template for *cgrlog, RSRFields instead of RSRField in extra_params
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user