// Converts a record (header or normal) to CDR func (self *FwvRecordsProcessor) recordToStoredCdr(record string, cdrcCfg *config.CdrcConfig, cfgKey string) (*engine.CDR, error) { var err error var lazyHttpFields []*config.CfgCdrField var cfgFields []*config.CfgCdrField var duMultiplyFactor float64 var storedCdr *engine.CDR if self.headerCdr != nil { // Clone the header CDR so we can use it as base to future processing (inherit fields defined there) storedCdr = self.headerCdr.Clone() } else { storedCdr = &engine.CDR{OriginHost: "0.0.0.0", ExtraFields: make(map[string]string), Cost: -1} } if cfgKey == "*header" { cfgFields = cdrcCfg.HeaderFields storedCdr.Source = cdrcCfg.CdrSourceId duMultiplyFactor = cdrcCfg.DataUsageMultiplyFactor } else { cfgFields = cdrcCfg.ContentFields storedCdr.Source = cdrcCfg.CdrSourceId duMultiplyFactor = cdrcCfg.DataUsageMultiplyFactor } for _, cdrFldCfg := range cfgFields { var fieldVal string switch cdrFldCfg.Type { case utils.META_COMPOSED: for _, cfgFieldRSR := range cdrFldCfg.Value { if cfgFieldRSR.IsStatic() { fieldVal += cfgFieldRSR.ParseValue("") } else { // Dynamic value extracted using index if cfgFieldIdx, _ := strconv.Atoi(cfgFieldRSR.Id); len(record) <= cfgFieldIdx { return nil, fmt.Errorf("Ignoring record: %v - cannot extract field %s", record, cdrFldCfg.Tag) } else { fieldVal += cfgFieldRSR.ParseValue(fwvValue(record, cfgFieldIdx, cdrFldCfg.Width, cdrFldCfg.Padding)) } } } case utils.META_HTTP_POST: lazyHttpFields = append(lazyHttpFields, cdrFldCfg) // Will process later so we can send an estimation of storedCdr to http server default: //return nil, fmt.Errorf("Unsupported field type: %s", cdrFldCfg.Type) continue // Don't do anything for unsupported fields } if err := storedCdr.ParseFieldValue(cdrFldCfg.FieldId, fieldVal, self.timezone); err != nil { return nil, err } } if storedCdr.CGRID == "" && storedCdr.OriginID != "" && cfgKey != "*header" { storedCdr.CGRID = utils.Sha1(storedCdr.OriginID, storedCdr.SetupTime.UTC().String()) } if storedCdr.ToR == utils.DATA && duMultiplyFactor != 0 { storedCdr.Usage = time.Duration(float64(storedCdr.Usage.Nanoseconds()) * duMultiplyFactor) } for _, httpFieldCfg := range lazyHttpFields { // Lazy process the http fields var outValByte []byte var fieldVal, httpAddr string for _, rsrFld := range httpFieldCfg.Value { httpAddr += rsrFld.ParseValue("") } var jsn []byte jsn, err = json.Marshal(storedCdr) if err != nil { return nil, err } if outValByte, err = utils.HttpJsonPost(httpAddr, self.httpSkipTlsCheck, jsn); err != nil && httpFieldCfg.Mandatory { return nil, err } else { fieldVal = string(outValByte) if len(fieldVal) == 0 && httpFieldCfg.Mandatory { return nil, fmt.Errorf("MandatoryIeMissing: Empty result for http_post field: %s", httpFieldCfg.Tag) } if err := storedCdr.ParseFieldValue(httpFieldCfg.FieldId, fieldVal, self.timezone); err != nil { return nil, err } } } return storedCdr, nil }