// Export Cdrs to file func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *utils.ExportedFileCdrs) error { var err error cdreReloadStruct := <-self.Config.ConfigReloads[utils.CDRE] // Read the content of the channel, locking it defer func() { self.Config.ConfigReloads[utils.CDRE] <- cdreReloadStruct }() // Unlock reloads at exit exportTemplate := self.Config.CdreProfiles[utils.META_DEFAULT] if attr.ExportTemplate != nil && len(*attr.ExportTemplate) != 0 { // Export template prefered, use it var hasIt bool if exportTemplate, hasIt = self.Config.CdreProfiles[*attr.ExportTemplate]; !hasIt { return fmt.Errorf("%s:ExportTemplate", utils.ErrNotFound) } } cdrFormat := exportTemplate.CdrFormat if attr.CdrFormat != nil && len(*attr.CdrFormat) != 0 { cdrFormat = strings.ToLower(*attr.CdrFormat) } if !utils.IsSliceMember(utils.CdreCdrFormats, cdrFormat) { return utils.NewErrMandatoryIeMissing("CdrFormat") } fieldSep := exportTemplate.FieldSeparator if attr.FieldSeparator != nil && len(*attr.FieldSeparator) != 0 { fieldSep, _ = utf8.DecodeRuneInString(*attr.FieldSeparator) if fieldSep == utf8.RuneError { return fmt.Errorf("%s:FieldSeparator:%s", utils.ErrServerError, "Invalid") } } eDir := exportTemplate.ExportDirectory if attr.ExportDirectory != nil && len(*attr.ExportDirectory) != 0 { eDir = *attr.ExportDirectory } ExportID := strconv.FormatInt(time.Now().Unix(), 10) if attr.ExportID != nil && len(*attr.ExportID) != 0 { ExportID = *attr.ExportID } fileName := fmt.Sprintf("cdre_%s.%s", ExportID, cdrFormat) if attr.ExportFileName != nil && len(*attr.ExportFileName) != 0 { fileName = *attr.ExportFileName } filePath := path.Join(eDir, fileName) if cdrFormat == utils.DRYRUN { filePath = utils.DRYRUN } dataUsageMultiplyFactor := exportTemplate.DataUsageMultiplyFactor if attr.DataUsageMultiplyFactor != nil && *attr.DataUsageMultiplyFactor != 0.0 { dataUsageMultiplyFactor = *attr.DataUsageMultiplyFactor } SMSUsageMultiplyFactor := exportTemplate.SMSUsageMultiplyFactor if attr.SMSUsageMultiplyFactor != nil && *attr.SMSUsageMultiplyFactor != 0.0 { SMSUsageMultiplyFactor = *attr.SMSUsageMultiplyFactor } MMSUsageMultiplyFactor := exportTemplate.MMSUsageMultiplyFactor if attr.MMSUsageMultiplyFactor != nil && *attr.MMSUsageMultiplyFactor != 0.0 { MMSUsageMultiplyFactor = *attr.MMSUsageMultiplyFactor } genericUsageMultiplyFactor := exportTemplate.GenericUsageMultiplyFactor if attr.GenericUsageMultiplyFactor != nil && *attr.GenericUsageMultiplyFactor != 0.0 { genericUsageMultiplyFactor = *attr.GenericUsageMultiplyFactor } costMultiplyFactor := exportTemplate.CostMultiplyFactor if attr.CostMultiplyFactor != nil && *attr.CostMultiplyFactor != 0.0 { costMultiplyFactor = *attr.CostMultiplyFactor } costShiftDigits := exportTemplate.CostShiftDigits if attr.CostShiftDigits != nil { costShiftDigits = *attr.CostShiftDigits } roundingDecimals := exportTemplate.CostRoundingDecimals if attr.RoundDecimals != nil { roundingDecimals = *attr.RoundDecimals } maskDestId := exportTemplate.MaskDestinationID if attr.MaskDestinationID != nil && len(*attr.MaskDestinationID) != 0 { maskDestId = *attr.MaskDestinationID } maskLen := exportTemplate.MaskLength if attr.MaskLength != nil { maskLen = *attr.MaskLength } cdrsFltr, err := attr.RPCCDRsFilter.AsCDRsFilter(self.Config.DefaultTimezone) if err != nil { return utils.NewErrServerError(err) } cdrs, _, err := self.CdrDb.GetCDRs(cdrsFltr, false) if err != nil { return err } else if len(cdrs) == 0 { *reply = utils.ExportedFileCdrs{ExportedFilePath: ""} return nil } cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, ExportID, dataUsageMultiplyFactor, SMSUsageMultiplyFactor, MMSUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify, self.Config.DefaultTimezone) if err != nil { return utils.NewErrServerError(err) } if cdrexp.TotalExportedCdrs() == 0 { *reply = utils.ExportedFileCdrs{ExportedFilePath: ""} return nil } if err := cdrexp.WriteToFile(filePath); err != nil { return utils.NewErrServerError(err) } *reply = utils.ExportedFileCdrs{ExportedFilePath: filePath, TotalRecords: len(cdrs), TotalCost: cdrexp.TotalCost(), FirstOrderId: cdrexp.FirstOrderId(), LastOrderId: cdrexp.LastOrderId()} if !attr.Verbose { reply.ExportedCgrIds = cdrexp.PositiveExports() reply.UnexportedCgrIds = cdrexp.NegativeExports() } return nil }
// Export Cdrs to file func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.ExportedFileCdrs) error { var tStart, tEnd time.Time var err error engine.Logger.Debug(fmt.Sprintf("ExportCdrsToFile: %+v", attr)) if len(attr.TimeStart) != 0 { if tStart, err = utils.ParseTimeDetectLayout(attr.TimeStart); err != nil { return err } } if len(attr.TimeEnd) != 0 { if tEnd, err = utils.ParseTimeDetectLayout(attr.TimeEnd); err != nil { return err } } exportTemplate := self.Config.CdreDefaultInstance if attr.ExportTemplate != nil { // XML Template defined, can be field names or xml reference if strings.HasPrefix(*attr.ExportTemplate, utils.XML_PROFILE_PREFIX) { if self.Config.XmlCfgDocument == nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, "XmlDocumentNotLoaded") } expTplStr := *attr.ExportTemplate if xmlTemplates := self.Config.XmlCfgDocument.GetCdreCfgs(expTplStr[len(utils.XML_PROFILE_PREFIX):]); xmlTemplates == nil { return fmt.Errorf("%s:ExportTemplate", utils.ERR_NOT_FOUND) } else { exportTemplate = xmlTemplates[expTplStr[len(utils.XML_PROFILE_PREFIX):]].AsCdreConfig() } } else { exportTemplate, _ = config.NewDefaultCdreConfig() if contentFlds, err := config.NewCdreCdrFieldsFromIds(exportTemplate.CdrFormat == utils.CDRE_FIXED_WIDTH, strings.Split(*attr.ExportTemplate, string(utils.CSV_SEP))...); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } else { exportTemplate.ContentFields = contentFlds } } } if exportTemplate == nil { return fmt.Errorf("%s:ExportTemplate", utils.ERR_MANDATORY_IE_MISSING) } cdrFormat := exportTemplate.CdrFormat if attr.CdrFormat != nil { cdrFormat = strings.ToLower(*attr.CdrFormat) } if !utils.IsSliceMember(utils.CdreCdrFormats, cdrFormat) { return fmt.Errorf("%s:%s", utils.ERR_MANDATORY_IE_MISSING, "CdrFormat") } fieldSep := exportTemplate.FieldSeparator if attr.FieldSeparator != nil { fieldSep = *attr.FieldSeparator } exportDir := exportTemplate.ExportDir if attr.ExportDir != nil { exportDir = *attr.ExportDir } exportId := strconv.FormatInt(time.Now().Unix(), 10) if attr.ExportId != nil { exportId = *attr.ExportId } fileName := fmt.Sprintf("cdre_%s.%s", exportId, cdrFormat) if attr.ExportFileName != nil { fileName = *attr.ExportFileName } filePath := path.Join(exportDir, fileName) if cdrFormat == utils.CDRE_DRYRUN { filePath = utils.CDRE_DRYRUN } dataUsageMultiplyFactor := exportTemplate.DataUsageMultiplyFactor if attr.DataUsageMultiplyFactor != nil { dataUsageMultiplyFactor = *attr.DataUsageMultiplyFactor } costMultiplyFactor := exportTemplate.CostMultiplyFactor if attr.CostMultiplyFactor != nil { costMultiplyFactor = *attr.CostMultiplyFactor } costShiftDigits := exportTemplate.CostShiftDigits if attr.CostShiftDigits != nil { costShiftDigits = *attr.CostShiftDigits } roundingDecimals := exportTemplate.CostRoundingDecimals if attr.RoundDecimals != nil { roundingDecimals = *attr.RoundDecimals } maskDestId := exportTemplate.MaskDestId if attr.MaskDestinationId != nil { maskDestId = *attr.MaskDestinationId } maskLen := exportTemplate.MaskLength if attr.MaskLength != nil { maskLen = *attr.MaskLength } cdrs, err := self.CdrDb.GetStoredCdrs(attr.CgrIds, attr.MediationRunIds, attr.TORs, attr.CdrHosts, attr.CdrSources, attr.ReqTypes, attr.Directions, attr.Tenants, attr.Categories, attr.Accounts, attr.Subjects, attr.DestinationPrefixes, attr.RatedAccounts, attr.RatedSubjects, attr.OrderIdStart, attr.OrderIdEnd, tStart, tEnd, attr.SkipErrors, attr.SkipRated, false) if err != nil { return err } else if len(cdrs) == 0 { *reply = utils.ExportedFileCdrs{ExportedFilePath: ""} return nil } cdrexp, err := cdre.NewCdrExporter(cdrs, self.LogDb, exportTemplate, cdrFormat, fieldSep, exportId, dataUsageMultiplyFactor, costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify) if err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } if cdrexp.TotalExportedCdrs() == 0 { *reply = utils.ExportedFileCdrs{ExportedFilePath: ""} return nil } if err := cdrexp.WriteToFile(filePath); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } *reply = utils.ExportedFileCdrs{ExportedFilePath: filePath, TotalRecords: len(cdrs), TotalCost: cdrexp.TotalCost(), FirstOrderId: cdrexp.FirstOrderId(), LastOrderId: cdrexp.LastOrderId()} if !attr.SuppressCgrIds { reply.ExportedCgrIds = cdrexp.PositiveExports() reply.UnexportedCgrIds = cdrexp.NegativeExports() } return nil }