// Extracts the value specified by cfgHdr out of cdr func (cdre *CdrExporter) cdrFieldValue(cdr *utils.StoredCdr, fltrRl, rsrFld *utils.RSRField, layout string) (string, error) { if rsrFld == nil { return "", nil } if fltrPass, _ := cdr.PassesFieldFilter(fltrRl); !fltrPass { return "", fmt.Errorf("Field: %s not matching filter rule %v", fltrRl.Id, fltrRl) } if len(layout) == 0 { layout = time.RFC3339 } var cdrVal string switch rsrFld.Id { case COST_DETAILS: // Special case when we need to further extract cost_details out of logDb if cdrVal, err = cdre.getCdrCostDetails(cdr.CgrId, cdr.MediationRunId); err != nil { return "", err } case utils.COST: cdrVal = cdr.FormatCost(cdre.costShiftDigits, cdre.roundDecimals) case utils.USAGE: cdrVal = cdr.FormatUsage(layout) case utils.SETUP_TIME: cdrVal = cdr.SetupTime.Format(layout) case utils.ANSWER_TIME: // Format time based on layout cdrVal = cdr.AnswerTime.Format(layout) case utils.DESTINATION: cdrVal = cdr.FieldAsString(&utils.RSRField{Id: utils.DESTINATION}) if cdre.maskLen != -1 && cdre.maskedDestination(cdrVal) { cdrVal = MaskDestination(cdrVal, cdre.maskLen) } default: cdrVal = cdr.FieldAsString(rsrFld) } return rsrFld.ParseValue(cdrVal), nil }
// Follows the implementation in the StorCdr func passesFieldFilter(m *diam.Message, fieldFilter *utils.RSRField) (bool, int) { if fieldFilter == nil { return true, 0 } avps, err := avpsWithPath(m, fieldFilter) if err != nil { return false, 0 } else if len(avps) == 0 { return false, 0 // No AVPs with field filter ID } for avpIdx, avpVal := range avps { // First match wins due to index if fieldFilter.FilterPasses(avpValAsString(avpVal)) { return true, avpIdx } } return false, 0 }
func (storedCdr *StoredCdr) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string) { if fieldFilter == nil { return true, "" } if fieldFilter.IsStatic() && storedCdr.FieldAsString(&utils.RSRField{Id: fieldFilter.Id}) == storedCdr.FieldAsString(fieldFilter) { return true, storedCdr.FieldAsString(&utils.RSRField{Id: fieldFilter.Id}) } preparedFilter := &utils.RSRField{Id: fieldFilter.Id, RSRules: make([]*utils.ReSearchReplace, len(fieldFilter.RSRules))} // Reset rules so they do not point towards same structures as original fieldFilter for idx := range fieldFilter.RSRules { // Hardcode the template with maximum of 5 groups ordered preparedFilter.RSRules[idx] = &utils.ReSearchReplace{SearchRegexp: fieldFilter.RSRules[idx].SearchRegexp, ReplaceTemplate: utils.FILTER_REGEXP_TPL} } preparedVal := storedCdr.FieldAsString(preparedFilter) filteredValue := storedCdr.FieldAsString(fieldFilter) if preparedFilter.RegexpMatched() && (len(preparedVal) == 0 || preparedVal == filteredValue) { return true, filteredValue } return false, "" }
func (fsev FSEvent) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string) { // Keep in sync (or merge) with StoredCdr.PassesFieldFielter() if fieldFilter == nil { return true, "" } if fieldFilter.IsStatic() && fsev.ParseEventValue(&utils.RSRField{Id: fieldFilter.Id}, config.CgrConfig().DefaultTimezone) == fsev.ParseEventValue(fieldFilter, config.CgrConfig().DefaultTimezone) { return true, fsev.ParseEventValue(&utils.RSRField{Id: fieldFilter.Id}, config.CgrConfig().DefaultTimezone) } preparedFilter := &utils.RSRField{Id: fieldFilter.Id, RSRules: make([]*utils.ReSearchReplace, len(fieldFilter.RSRules))} // Reset rules so they do not point towards same structures as original fieldFilter for idx := range fieldFilter.RSRules { // Hardcode the template with maximum of 5 groups ordered preparedFilter.RSRules[idx] = &utils.ReSearchReplace{SearchRegexp: fieldFilter.RSRules[idx].SearchRegexp, ReplaceTemplate: utils.FILTER_REGEXP_TPL} } preparedVal := fsev.ParseEventValue(preparedFilter, config.CgrConfig().DefaultTimezone) filteredValue := fsev.ParseEventValue(fieldFilter, config.CgrConfig().DefaultTimezone) if preparedFilter.RegexpMatched() && (len(preparedVal) == 0 || preparedVal == filteredValue) { return true, filteredValue } return false, "" }
func passesFieldFilter(m *diam.Message, fieldFilter *utils.RSRField, processorVars map[string]string) (bool, int) { if fieldFilter == nil { return true, 0 } if val, hasIt := processorVars[fieldFilter.Id]; hasIt { // ProcessorVars have priority if fieldFilter.FilterPasses(val) { return true, 0 } return false, 0 } avps, err := avpsWithPath(m, fieldFilter) if err != nil { return false, 0 } if len(avps) == 0 { // No AVP found in request, treat it same as empty if fieldFilter.FilterPasses("") { return true, -1 } } for avpIdx, avpVal := range avps { // First match wins due to index if fieldFilter.FilterPasses(avpValAsString(avpVal)) { return true, avpIdx } } return false, 0 }
func (self SMGenericEvent) ParseEventValue(rsrFld *utils.RSRField, timezone string) string { switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(self.GetCgrId(timezone)) case utils.TOR: return rsrFld.ParseValue(utils.VOICE) case utils.ACCID: return rsrFld.ParseValue(self.GetUUID()) case utils.CDRHOST: return rsrFld.ParseValue(self.GetOriginatorIP(utils.META_DEFAULT)) case utils.CDRSOURCE: return rsrFld.ParseValue(self.GetName()) case utils.REQTYPE: return rsrFld.ParseValue(self.GetReqType(utils.META_DEFAULT)) case utils.DIRECTION: return rsrFld.ParseValue(self.GetDirection(utils.META_DEFAULT)) case utils.TENANT: return rsrFld.ParseValue(self.GetTenant(utils.META_DEFAULT)) case utils.CATEGORY: return rsrFld.ParseValue(self.GetCategory(utils.META_DEFAULT)) case utils.ACCOUNT: return rsrFld.ParseValue(self.GetAccount(utils.META_DEFAULT)) case utils.SUBJECT: return rsrFld.ParseValue(self.GetSubject(utils.META_DEFAULT)) case utils.DESTINATION: return rsrFld.ParseValue(self.GetDestination(utils.META_DEFAULT)) case utils.SETUP_TIME: st, _ := self.GetSetupTime(utils.META_DEFAULT, timezone) return rsrFld.ParseValue(st.String()) case utils.ANSWER_TIME: at, _ := self.GetAnswerTime(utils.META_DEFAULT, timezone) return rsrFld.ParseValue(at.String()) case utils.USAGE: dur, _ := self.GetUsage(utils.META_DEFAULT) return rsrFld.ParseValue(strconv.FormatInt(dur.Nanoseconds(), 10)) case utils.PDD: pdd, _ := self.GetPdd(utils.META_DEFAULT) return rsrFld.ParseValue(strconv.FormatFloat(pdd.Seconds(), 'f', -1, 64)) case utils.SUPPLIER: return rsrFld.ParseValue(self.GetSupplier(utils.META_DEFAULT)) case utils.DISCONNECT_CAUSE: return rsrFld.ParseValue(self.GetDisconnectCause(utils.META_DEFAULT)) case utils.MEDI_RUNID: return rsrFld.ParseValue(utils.META_DEFAULT) case utils.COST: return rsrFld.ParseValue(strconv.FormatFloat(-1, 'f', -1, 64)) // Recommended to use FormatCost default: strVal, _ := utils.ConvertIfaceToString(self[rsrFld.Id]) val := rsrFld.ParseValue(strVal) return val } return "" }
// Useful for CDR generation func (kev KamEvent) ParseEventValue(rsrFld *utils.RSRField, timezone string) string { sTime, _ := kev.GetSetupTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) aTime, _ := kev.GetAnswerTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) duration, _ := kev.GetDuration(utils.META_DEFAULT) switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(kev.GetCgrId(timezone)) case utils.TOR: return rsrFld.ParseValue(utils.VOICE) case utils.ACCID: return rsrFld.ParseValue(kev.GetUUID()) case utils.CDRHOST: return rsrFld.ParseValue(kev.GetOriginatorIP(utils.META_DEFAULT)) case utils.CDRSOURCE: return rsrFld.ParseValue(kev.GetCdrSource()) case utils.REQTYPE: return rsrFld.ParseValue(kev.GetReqType(utils.META_DEFAULT)) case utils.DIRECTION: return rsrFld.ParseValue(kev.GetDirection(utils.META_DEFAULT)) case utils.TENANT: return rsrFld.ParseValue(kev.GetTenant(utils.META_DEFAULT)) case utils.CATEGORY: return rsrFld.ParseValue(kev.GetCategory(utils.META_DEFAULT)) case utils.ACCOUNT: return rsrFld.ParseValue(kev.GetAccount(utils.META_DEFAULT)) case utils.SUBJECT: return rsrFld.ParseValue(kev.GetSubject(utils.META_DEFAULT)) case utils.DESTINATION: return rsrFld.ParseValue(kev.GetDestination(utils.META_DEFAULT)) case utils.SETUP_TIME: return rsrFld.ParseValue(sTime.String()) case utils.ANSWER_TIME: return rsrFld.ParseValue(aTime.String()) case utils.USAGE: return rsrFld.ParseValue(strconv.FormatFloat(utils.Round(duration.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)) case utils.PDD: return rsrFld.ParseValue(strconv.FormatFloat(utils.Round(duration.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)) case utils.SUPPLIER: return rsrFld.ParseValue(kev.GetSupplier(utils.META_DEFAULT)) case utils.DISCONNECT_CAUSE: return rsrFld.ParseValue(kev.GetDisconnectCause(utils.META_DEFAULT)) case utils.MEDI_RUNID: return rsrFld.ParseValue(utils.META_DEFAULT) case utils.COST: return rsrFld.ParseValue("-1.0") default: return rsrFld.ParseValue(kev.GetExtraFields()[rsrFld.Id]) } }
// Used in derived charging and sittuations when we need to run regexp on fields func (fsev FSEvent) ParseEventValue(rsrFld *utils.RSRField, timezone string) string { switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(fsev.GetCgrId(timezone)) case utils.TOR: return rsrFld.ParseValue(utils.VOICE) case utils.ACCID: return rsrFld.ParseValue(fsev.GetUUID()) case utils.CDRHOST: return rsrFld.ParseValue(fsev["FreeSWITCH-IPv4"]) case utils.CDRSOURCE: return rsrFld.ParseValue("FS_EVENT") case utils.REQTYPE: return rsrFld.ParseValue(fsev.GetReqType("")) case utils.DIRECTION: return rsrFld.ParseValue(fsev.GetDirection("")) case utils.TENANT: return rsrFld.ParseValue(fsev.GetTenant("")) case utils.CATEGORY: return rsrFld.ParseValue(fsev.GetCategory("")) case utils.ACCOUNT: return rsrFld.ParseValue(fsev.GetAccount("")) case utils.SUBJECT: return rsrFld.ParseValue(fsev.GetSubject("")) case utils.DESTINATION: return rsrFld.ParseValue(fsev.GetDestination("")) case utils.SETUP_TIME: st, _ := fsev.GetSetupTime("", timezone) return rsrFld.ParseValue(st.String()) case utils.ANSWER_TIME: at, _ := fsev.GetAnswerTime("", timezone) return rsrFld.ParseValue(at.String()) case utils.USAGE: dur, _ := fsev.GetDuration("") return rsrFld.ParseValue(strconv.FormatInt(dur.Nanoseconds(), 10)) case utils.PDD: pdd, _ := fsev.GetPdd(utils.META_DEFAULT) return rsrFld.ParseValue(strconv.FormatFloat(pdd.Seconds(), 'f', -1, 64)) case utils.SUPPLIER: return rsrFld.ParseValue(fsev.GetSupplier("")) case utils.DISCONNECT_CAUSE: return rsrFld.ParseValue(fsev.GetDisconnectCause("")) case utils.MEDI_RUNID: return rsrFld.ParseValue(utils.DEFAULT_RUNID) case utils.COST: return rsrFld.ParseValue(strconv.FormatFloat(-1, 'f', -1, 64)) // Recommended to use FormatCost default: val := rsrFld.ParseValue(fsev[rsrFld.Id]) if val == "" { // Trying looking for variable_+ Id also if the first one not found val = rsrFld.ParseValue(fsev[FS_VARPREFIX+rsrFld.Id]) } return val } }
// Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, PDDFld, answerTimeFld, durationFld, supplierFld, disconnectCauseFld, ratedFld, costFld *utils.RSRField, extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*CDR, error) { if RequestTypeFld == nil { RequestTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if RequestTypeFld.Id == utils.META_DEFAULT { RequestTypeFld.Id = utils.REQTYPE } if directionFld == nil { directionFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if directionFld.Id == utils.META_DEFAULT { directionFld.Id = utils.DIRECTION } if tenantFld == nil { tenantFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if tenantFld.Id == utils.META_DEFAULT { tenantFld.Id = utils.TENANT } if categFld == nil { categFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if categFld.Id == utils.META_DEFAULT { categFld.Id = utils.CATEGORY } if accountFld == nil { accountFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if accountFld.Id == utils.META_DEFAULT { accountFld.Id = utils.ACCOUNT } if subjectFld == nil { subjectFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if subjectFld.Id == utils.META_DEFAULT { subjectFld.Id = utils.SUBJECT } if destFld == nil { destFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if destFld.Id == utils.META_DEFAULT { destFld.Id = utils.DESTINATION } if setupTimeFld == nil { setupTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if setupTimeFld.Id == utils.META_DEFAULT { setupTimeFld.Id = utils.SETUP_TIME } if answerTimeFld == nil { answerTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if answerTimeFld.Id == utils.META_DEFAULT { answerTimeFld.Id = utils.ANSWER_TIME } if durationFld == nil { durationFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if durationFld.Id == utils.META_DEFAULT { durationFld.Id = utils.USAGE } if PDDFld == nil { PDDFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if PDDFld.Id == utils.META_DEFAULT { PDDFld.Id = utils.PDD } if supplierFld == nil { supplierFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if supplierFld.Id == utils.META_DEFAULT { supplierFld.Id = utils.SUPPLIER } if disconnectCauseFld == nil { disconnectCauseFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if disconnectCauseFld.Id == utils.META_DEFAULT { disconnectCauseFld.Id = utils.DISCONNECT_CAUSE } if ratedFld == nil { ratedFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if ratedFld.Id == utils.META_DEFAULT { ratedFld.Id = utils.RATED_FLD } if costFld == nil { costFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if costFld.Id == utils.META_DEFAULT { costFld.Id = utils.COST } var err error frkStorCdr := new(CDR) frkStorCdr.CGRID = cdr.CGRID frkStorCdr.ToR = cdr.ToR frkStorCdr.RunID = runId frkStorCdr.Cost = -1.0 // Default for non-rated CDR frkStorCdr.OriginID = cdr.OriginID frkStorCdr.OriginHost = cdr.OriginHost frkStorCdr.Source = cdr.Source frkStorCdr.RequestType = cdr.FieldAsString(RequestTypeFld) if primaryMandatory && len(frkStorCdr.RequestType) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, RequestTypeFld.Id) } frkStorCdr.Direction = cdr.FieldAsString(directionFld) if primaryMandatory && len(frkStorCdr.Direction) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.DIRECTION, directionFld.Id) } frkStorCdr.Tenant = cdr.FieldAsString(tenantFld) if primaryMandatory && len(frkStorCdr.Tenant) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.TENANT, tenantFld.Id) } frkStorCdr.Category = cdr.FieldAsString(categFld) if primaryMandatory && len(frkStorCdr.Category) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.CATEGORY, categFld.Id) } frkStorCdr.Account = cdr.FieldAsString(accountFld) if primaryMandatory && len(frkStorCdr.Account) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.ACCOUNT, accountFld.Id) } frkStorCdr.Subject = cdr.FieldAsString(subjectFld) if primaryMandatory && len(frkStorCdr.Subject) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.SUBJECT, subjectFld.Id) } frkStorCdr.Destination = cdr.FieldAsString(destFld) if primaryMandatory && len(frkStorCdr.Destination) == 0 && frkStorCdr.ToR == utils.VOICE { return nil, utils.NewErrMandatoryIeMissing(utils.DESTINATION, destFld.Id) } sTimeStr := cdr.FieldAsString(setupTimeFld) if primaryMandatory && len(sTimeStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.SETUP_TIME, setupTimeFld.Id) } else if frkStorCdr.SetupTime, err = utils.ParseTimeDetectLayout(sTimeStr, timezone); err != nil { return nil, err } aTimeStr := cdr.FieldAsString(answerTimeFld) if primaryMandatory && len(aTimeStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.ANSWER_TIME, answerTimeFld.Id) } else if frkStorCdr.AnswerTime, err = utils.ParseTimeDetectLayout(aTimeStr, timezone); err != nil { return nil, err } durStr := cdr.FieldAsString(durationFld) if primaryMandatory && len(durStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.USAGE, durationFld.Id) } else if frkStorCdr.Usage, err = utils.ParseDurationWithSecs(durStr); err != nil { return nil, err } PDDStr := cdr.FieldAsString(PDDFld) if primaryMandatory && len(PDDStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.PDD, PDDFld.Id) } else if frkStorCdr.PDD, err = utils.ParseDurationWithSecs(PDDStr); err != nil { return nil, err } frkStorCdr.Supplier = cdr.FieldAsString(supplierFld) frkStorCdr.DisconnectCause = cdr.FieldAsString(disconnectCauseFld) ratedStr := cdr.FieldAsString(ratedFld) if primaryMandatory && len(ratedStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.RATED_FLD, ratedFld.Id) } else if frkStorCdr.Rated, err = strconv.ParseBool(ratedStr); err != nil { return nil, err } costStr := cdr.FieldAsString(costFld) if primaryMandatory && len(costStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.COST, costFld.Id) } else if frkStorCdr.Cost, err = strconv.ParseFloat(costStr, 64); err != nil { return nil, err } frkStorCdr.ExtraFields = make(map[string]string, len(extraFlds)) for _, fld := range extraFlds { frkStorCdr.ExtraFields[fld.Id] = cdr.FieldAsString(fld) } return frkStorCdr, nil }
// Used to retrieve fields as string, primary fields are const labeled func (cdr *CDR) FieldAsString(rsrFld *utils.RSRField) string { if rsrFld.IsStatic() { // Static values do not care about headers return rsrFld.ParseValue("") } switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(cdr.CGRID) case utils.ORDERID: return rsrFld.ParseValue(strconv.FormatInt(cdr.OrderID, 10)) case utils.TOR: return rsrFld.ParseValue(cdr.ToR) case utils.ACCID: return rsrFld.ParseValue(cdr.OriginID) case utils.CDRHOST: return rsrFld.ParseValue(cdr.OriginHost) case utils.CDRSOURCE: return rsrFld.ParseValue(cdr.Source) case utils.REQTYPE: return rsrFld.ParseValue(cdr.RequestType) case utils.DIRECTION: return rsrFld.ParseValue(cdr.Direction) case utils.TENANT: return rsrFld.ParseValue(cdr.Tenant) case utils.CATEGORY: return rsrFld.ParseValue(cdr.Category) case utils.ACCOUNT: return rsrFld.ParseValue(cdr.Account) case utils.SUBJECT: return rsrFld.ParseValue(cdr.Subject) case utils.DESTINATION: return rsrFld.ParseValue(cdr.Destination) case utils.SETUP_TIME: return rsrFld.ParseValue(cdr.SetupTime.Format(time.RFC3339)) case utils.PDD: return strconv.FormatFloat(cdr.PDD.Seconds(), 'f', -1, 64) case utils.ANSWER_TIME: return rsrFld.ParseValue(cdr.AnswerTime.Format(time.RFC3339)) case utils.USAGE: return strconv.FormatFloat(cdr.Usage.Seconds(), 'f', -1, 64) case utils.SUPPLIER: return rsrFld.ParseValue(cdr.Supplier) case utils.DISCONNECT_CAUSE: return rsrFld.ParseValue(cdr.DisconnectCause) case utils.MEDI_RUNID: return rsrFld.ParseValue(cdr.RunID) case utils.RATED_FLD: return rsrFld.ParseValue(strconv.FormatBool(cdr.Rated)) case utils.COST: return rsrFld.ParseValue(strconv.FormatFloat(cdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost case utils.COST_DETAILS: return rsrFld.ParseValue(cdr.CostDetailsJson()) case utils.PartialField: return rsrFld.ParseValue(strconv.FormatBool(cdr.Partial)) default: return rsrFld.ParseValue(cdr.ExtraFields[rsrFld.Id]) } }
// Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, pddFld, answerTimeFld, durationFld, supplierFld, disconnectCauseFld *utils.RSRField, extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*StoredCdr, error) { if reqTypeFld == nil { reqTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if reqTypeFld.Id == utils.META_DEFAULT { reqTypeFld.Id = utils.REQTYPE } if directionFld == nil { directionFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if directionFld.Id == utils.META_DEFAULT { directionFld.Id = utils.DIRECTION } if tenantFld == nil { tenantFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if tenantFld.Id == utils.META_DEFAULT { tenantFld.Id = utils.TENANT } if categFld == nil { categFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if categFld.Id == utils.META_DEFAULT { categFld.Id = utils.CATEGORY } if accountFld == nil { accountFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if accountFld.Id == utils.META_DEFAULT { accountFld.Id = utils.ACCOUNT } if subjectFld == nil { subjectFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if subjectFld.Id == utils.META_DEFAULT { subjectFld.Id = utils.SUBJECT } if destFld == nil { destFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if destFld.Id == utils.META_DEFAULT { destFld.Id = utils.DESTINATION } if setupTimeFld == nil { setupTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if setupTimeFld.Id == utils.META_DEFAULT { setupTimeFld.Id = utils.SETUP_TIME } if answerTimeFld == nil { answerTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if answerTimeFld.Id == utils.META_DEFAULT { answerTimeFld.Id = utils.ANSWER_TIME } if durationFld == nil { durationFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if durationFld.Id == utils.META_DEFAULT { durationFld.Id = utils.USAGE } if pddFld == nil { pddFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if pddFld.Id == utils.META_DEFAULT { pddFld.Id = utils.PDD } if supplierFld == nil { supplierFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if supplierFld.Id == utils.META_DEFAULT { supplierFld.Id = utils.SUPPLIER } if disconnectCauseFld == nil { disconnectCauseFld, _ = utils.NewRSRField(utils.META_DEFAULT) } if disconnectCauseFld.Id == utils.META_DEFAULT { disconnectCauseFld.Id = utils.DISCONNECT_CAUSE } var err error frkStorCdr := new(StoredCdr) frkStorCdr.CgrId = storedCdr.CgrId frkStorCdr.TOR = storedCdr.TOR frkStorCdr.MediationRunId = runId frkStorCdr.Cost = -1.0 // Default for non-rated CDR frkStorCdr.AccId = storedCdr.AccId frkStorCdr.CdrHost = storedCdr.CdrHost frkStorCdr.CdrSource = storedCdr.CdrSource frkStorCdr.ReqType = storedCdr.FieldAsString(reqTypeFld) if primaryMandatory && len(frkStorCdr.ReqType) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, reqTypeFld.Id) } frkStorCdr.Direction = storedCdr.FieldAsString(directionFld) if primaryMandatory && len(frkStorCdr.Direction) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.DIRECTION, directionFld.Id) } frkStorCdr.Tenant = storedCdr.FieldAsString(tenantFld) if primaryMandatory && len(frkStorCdr.Tenant) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.TENANT, tenantFld.Id) } frkStorCdr.Category = storedCdr.FieldAsString(categFld) if primaryMandatory && len(frkStorCdr.Category) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.CATEGORY, categFld.Id) } frkStorCdr.Account = storedCdr.FieldAsString(accountFld) if primaryMandatory && len(frkStorCdr.Account) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.ACCOUNT, accountFld.Id) } frkStorCdr.Subject = storedCdr.FieldAsString(subjectFld) if primaryMandatory && len(frkStorCdr.Subject) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.SUBJECT, subjectFld.Id) } frkStorCdr.Destination = storedCdr.FieldAsString(destFld) if primaryMandatory && len(frkStorCdr.Destination) == 0 && frkStorCdr.TOR == utils.VOICE { return nil, utils.NewErrMandatoryIeMissing(utils.DESTINATION, destFld.Id) } sTimeStr := storedCdr.FieldAsString(setupTimeFld) if primaryMandatory && len(sTimeStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.SETUP_TIME, setupTimeFld.Id) } else if frkStorCdr.SetupTime, err = utils.ParseTimeDetectLayout(sTimeStr, timezone); err != nil { return nil, err } aTimeStr := storedCdr.FieldAsString(answerTimeFld) if primaryMandatory && len(aTimeStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.ANSWER_TIME, answerTimeFld.Id) } else if frkStorCdr.AnswerTime, err = utils.ParseTimeDetectLayout(aTimeStr, timezone); err != nil { return nil, err } durStr := storedCdr.FieldAsString(durationFld) if primaryMandatory && len(durStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.USAGE, durationFld.Id) } else if frkStorCdr.Usage, err = utils.ParseDurationWithSecs(durStr); err != nil { return nil, err } pddStr := storedCdr.FieldAsString(pddFld) if primaryMandatory && len(pddStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.PDD, pddFld.Id) } else if frkStorCdr.Pdd, err = utils.ParseDurationWithSecs(pddStr); err != nil { return nil, err } frkStorCdr.Supplier = storedCdr.FieldAsString(supplierFld) frkStorCdr.DisconnectCause = storedCdr.FieldAsString(disconnectCauseFld) frkStorCdr.ExtraFields = make(map[string]string, len(extraFlds)) for _, fld := range extraFlds { frkStorCdr.ExtraFields[fld.Id] = storedCdr.FieldAsString(fld) } return frkStorCdr, nil }
// Used to retrieve fields as string, primary fields are const labeled func (storedCdr *StoredCdr) FieldAsString(rsrFld *utils.RSRField) string { switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(storedCdr.CgrId) case utils.ORDERID: return rsrFld.ParseValue(strconv.FormatInt(storedCdr.OrderId, 10)) case utils.TOR: return rsrFld.ParseValue(storedCdr.TOR) case utils.ACCID: return rsrFld.ParseValue(storedCdr.AccId) case utils.CDRHOST: return rsrFld.ParseValue(storedCdr.CdrHost) case utils.CDRSOURCE: return rsrFld.ParseValue(storedCdr.CdrSource) case utils.REQTYPE: return rsrFld.ParseValue(storedCdr.ReqType) case utils.DIRECTION: return rsrFld.ParseValue(storedCdr.Direction) case utils.TENANT: return rsrFld.ParseValue(storedCdr.Tenant) case utils.CATEGORY: return rsrFld.ParseValue(storedCdr.Category) case utils.ACCOUNT: return rsrFld.ParseValue(storedCdr.Account) case utils.SUBJECT: return rsrFld.ParseValue(storedCdr.Subject) case utils.DESTINATION: return rsrFld.ParseValue(storedCdr.Destination) case utils.SETUP_TIME: return rsrFld.ParseValue(storedCdr.SetupTime.Format(time.RFC3339)) case utils.PDD: return strconv.FormatFloat(storedCdr.Pdd.Seconds(), 'f', -1, 64) case utils.ANSWER_TIME: return rsrFld.ParseValue(storedCdr.AnswerTime.Format(time.RFC3339)) case utils.USAGE: return strconv.FormatFloat(storedCdr.Usage.Seconds(), 'f', -1, 64) case utils.SUPPLIER: return rsrFld.ParseValue(storedCdr.Supplier) case utils.DISCONNECT_CAUSE: return rsrFld.ParseValue(storedCdr.DisconnectCause) case utils.MEDI_RUNID: return rsrFld.ParseValue(storedCdr.MediationRunId) case utils.RATED_ACCOUNT: return rsrFld.ParseValue(storedCdr.RatedAccount) case utils.RATED_SUBJECT: return rsrFld.ParseValue(storedCdr.RatedSubject) case utils.COST: return rsrFld.ParseValue(strconv.FormatFloat(storedCdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost case utils.COST_DETAILS: return rsrFld.ParseValue(storedCdr.CostDetailsJson()) default: return rsrFld.ParseValue(storedCdr.ExtraFields[rsrFld.Id]) } }
// Follows the implementation in the StorCdr func (self *CCR) passesFieldFilter(fieldFilter *utils.RSRField) bool { if fieldFilter == nil { return true } return fieldFilter.FilterPasses(self.eventFieldValue(utils.RSRFields{fieldFilter})) }
// Used in derived charging and sittuations when we need to run regexp on fields func (fsev FSEvent) ParseEventValue(rsrFld *utils.RSRField) string { switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(fsev.GetCgrId()) case utils.TOR: return rsrFld.ParseValue(utils.VOICE) case utils.ACCID: return rsrFld.ParseValue(fsev.GetUUID()) case utils.CDRHOST: return rsrFld.ParseValue(fsev["FreeSWITCH-IPv4"]) case utils.CDRSOURCE: return rsrFld.ParseValue("FS_EVENT") case utils.REQTYPE: return rsrFld.ParseValue(fsev.GetReqType("")) case utils.DIRECTION: return rsrFld.ParseValue(fsev.GetDirection("")) case utils.TENANT: return rsrFld.ParseValue(fsev.GetTenant("")) case utils.CATEGORY: return rsrFld.ParseValue(fsev.GetCategory("")) case utils.ACCOUNT: return rsrFld.ParseValue(fsev.GetAccount("")) case utils.SUBJECT: return rsrFld.ParseValue(fsev.GetSubject("")) case utils.DESTINATION: return rsrFld.ParseValue(fsev.GetDestination("")) case utils.SETUP_TIME: st, _ := fsev.GetSetupTime("") return rsrFld.ParseValue(st.String()) case utils.ANSWER_TIME: at, _ := fsev.GetAnswerTime("") return rsrFld.ParseValue(at.String()) case utils.USAGE: dur, _ := fsev.GetDuration("") return rsrFld.ParseValue(strconv.FormatInt(dur.Nanoseconds(), 10)) case utils.MEDI_RUNID: return rsrFld.ParseValue(utils.DEFAULT_RUNID) case utils.COST: return rsrFld.ParseValue(strconv.FormatFloat(-1, 'f', -1, 64)) // Recommended to use FormatCost default: return rsrFld.ParseValue(fsev[rsrFld.Id]) } }