mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
CdrExporter with configurable field separator, counters for sms and data usage
This commit is contained in:
@@ -77,6 +77,10 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
|
||||
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
|
||||
@@ -125,7 +129,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
|
||||
*reply = utils.ExportedFileCdrs{ExportedFilePath: ""}
|
||||
return nil
|
||||
}
|
||||
cdrexp, err := cdre.NewCdrExporter(cdrs, self.LogDb, exportTemplate, cdrFormat, exportId,
|
||||
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())
|
||||
|
||||
@@ -47,6 +47,8 @@ const (
|
||||
META_LASTCDRATIME = "last_cdr_atime"
|
||||
META_NRCDRS = "cdrs_number"
|
||||
META_DURCDRS = "cdrs_duration"
|
||||
META_SMSUSAGE = "sms_usage"
|
||||
META_DATAUSAGE = "data_usage"
|
||||
META_COSTCDRS = "cdrs_cost"
|
||||
META_MASKDESTINATION = "mask_destination"
|
||||
META_FORMATCOST = "format_cost"
|
||||
@@ -54,7 +56,7 @@ const (
|
||||
|
||||
var err error
|
||||
|
||||
func NewCdrExporter(cdrs []*utils.StoredCdr, logDb engine.LogStorage, exportTpl *config.CdreConfig, cdrFormat, exportId string,
|
||||
func NewCdrExporter(cdrs []*utils.StoredCdr, logDb engine.LogStorage, exportTpl *config.CdreConfig, cdrFormat string, fieldSeparator rune, exportId string,
|
||||
dataUsageMultiplyFactor, costMultiplyFactor float64, costShiftDigits, roundDecimals, cgrPrecision int, maskDestId string, maskLen int, httpSkipTlsCheck bool) (*CdrExporter, error) {
|
||||
if len(cdrs) == 0 { // Nothing to export
|
||||
return nil, nil
|
||||
@@ -64,6 +66,7 @@ func NewCdrExporter(cdrs []*utils.StoredCdr, logDb engine.LogStorage, exportTpl
|
||||
logDb: logDb,
|
||||
exportTemplate: exportTpl,
|
||||
cdrFormat: cdrFormat,
|
||||
fieldSeparator: fieldSeparator,
|
||||
exportId: exportId,
|
||||
dataUsageMultiplyFactor: dataUsageMultiplyFactor,
|
||||
costMultiplyFactor: costMultiplyFactor,
|
||||
@@ -86,6 +89,7 @@ type CdrExporter struct {
|
||||
logDb engine.LogStorage // Used to extract cost_details if these are requested
|
||||
exportTemplate *config.CdreConfig
|
||||
cdrFormat string // csv, fwv
|
||||
fieldSeparator rune
|
||||
exportId string // Unique identifier or this export
|
||||
dataUsageMultiplyFactor, costMultiplyFactor float64
|
||||
costShiftDigits, roundDecimals, cgrPrecision int
|
||||
@@ -96,11 +100,12 @@ type CdrExporter struct {
|
||||
content [][]string // Rows of cdr fields
|
||||
firstCdrATime, lastCdrATime time.Time
|
||||
numberOfRecords int
|
||||
totalDuration time.Duration
|
||||
totalCost float64
|
||||
firstExpOrderId, lastExpOrderId int64
|
||||
positiveExports []string // CGRIds of successfully exported CDRs
|
||||
negativeExports map[string]string // CgrIds of failed exports
|
||||
totalDuration, totalDataUsage, totalSmsUsage time.Duration
|
||||
|
||||
totalCost float64
|
||||
firstExpOrderId, lastExpOrderId int64
|
||||
positiveExports []string // CGRIds of successfully exported CDRs
|
||||
negativeExports map[string]string // CgrIds of failed exports
|
||||
}
|
||||
|
||||
// Return Json marshaled callCost attached to
|
||||
@@ -207,7 +212,17 @@ func (cdre *CdrExporter) metaHandler(tag, arg string) (string, error) {
|
||||
case META_NRCDRS:
|
||||
return strconv.Itoa(cdre.numberOfRecords), nil
|
||||
case META_DURCDRS:
|
||||
return strconv.FormatFloat(cdre.totalDuration.Seconds(), 'f', -1, 64), nil
|
||||
//return strconv.FormatFloat(cdre.totalDuration.Seconds(), 'f', -1, 64), nil
|
||||
emulatedCdr := &utils.StoredCdr{TOR: utils.VOICE, Usage: cdre.totalDuration}
|
||||
return emulatedCdr.FormatUsage(arg), nil
|
||||
case META_SMSUSAGE:
|
||||
//return strconv.FormatFloat(cdre.totalDuration.Seconds(), 'f', -1, 64), nil
|
||||
emulatedCdr := &utils.StoredCdr{TOR: utils.SMS, Usage: cdre.totalSmsUsage}
|
||||
return emulatedCdr.FormatUsage(arg), nil
|
||||
case META_DATAUSAGE:
|
||||
//return strconv.FormatFloat(cdre.totalDuration.Seconds(), 'f', -1, 64), nil
|
||||
emulatedCdr := &utils.StoredCdr{TOR: utils.DATA, Usage: cdre.totalDataUsage}
|
||||
return emulatedCdr.FormatUsage(arg), nil
|
||||
case META_COSTCDRS:
|
||||
return strconv.FormatFloat(utils.Round(cdre.totalCost, cdre.roundDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64), nil
|
||||
case META_MASKDESTINATION:
|
||||
@@ -353,9 +368,15 @@ func (cdre *CdrExporter) processCdr(cdr *utils.StoredCdr) error {
|
||||
cdre.lastCdrATime = cdr.AnswerTime
|
||||
}
|
||||
cdre.numberOfRecords += 1
|
||||
if !utils.IsSliceMember([]string{utils.DATA, utils.SMS}, cdr.TOR) { // Only count duration for non data cdrs
|
||||
if cdr.TOR == utils.VOICE { // Only count duration for non data cdrs
|
||||
cdre.totalDuration += cdr.Usage
|
||||
}
|
||||
if cdr.TOR == utils.SMS { // Count usage for SMS
|
||||
cdre.totalSmsUsage += cdr.Usage
|
||||
}
|
||||
if cdr.TOR == utils.DATA { // Count usage for SMS
|
||||
cdre.totalDataUsage += cdr.Usage
|
||||
}
|
||||
if cdr.Cost != -1 {
|
||||
cdre.totalCost += cdr.Cost
|
||||
cdre.totalCost = utils.Round(cdre.totalCost, cdre.roundDecimals, utils.ROUNDING_MIDDLE)
|
||||
@@ -420,6 +441,7 @@ func (cdre *CdrExporter) writeOut(ioWriter io.Writer) error {
|
||||
|
||||
// csvWriter specific method
|
||||
func (cdre *CdrExporter) writeCsv(csvWriter *csv.Writer) error {
|
||||
csvWriter.Comma = cdre.fieldSeparator
|
||||
if len(cdre.header) != 0 {
|
||||
if err := csvWriter.Write(cdre.header); err != nil {
|
||||
return err
|
||||
|
||||
@@ -52,8 +52,8 @@ func TestCdreGetCombimedCdrFieldVal(t *testing.T) {
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: "RETAIL1", Cost: 5.01},
|
||||
}
|
||||
|
||||
cdre, err := NewCdrExporter(cdrs, logDb, cfg.CdreDefaultInstance, cfg.CdreDefaultInstance.CdrFormat, "firstexport", 0.0, 0.0, 0, 4,
|
||||
cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
|
||||
cdre, err := NewCdrExporter(cdrs, logDb, cfg.CdreDefaultInstance, cfg.CdreDefaultInstance.CdrFormat, cfg.CdreDefaultInstance.FieldSeparator,
|
||||
"firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestCsvCdrWriter(t *testing.T) {
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID,
|
||||
ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01,
|
||||
}
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{storedCdr1}, logDb, cfg.CdreDefaultInstance, utils.CSV, "firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{storedCdr1}, logDb, cfg.CdreDefaultInstance, utils.CSV, ',', "firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
}
|
||||
@@ -56,3 +56,31 @@ func TestCsvCdrWriter(t *testing.T) {
|
||||
t.Error("Unexpected TotalCost: ", cdre.TotalCost())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlternativeFieldSeparator(t *testing.T) {
|
||||
writer := &bytes.Buffer{}
|
||||
cfg, _ := config.NewDefaultCGRConfig()
|
||||
logDb, _ := engine.NewMapStorage()
|
||||
storedCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID,
|
||||
ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01,
|
||||
}
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{storedCdr1}, logDb, cfg.CdreDefaultInstance, utils.CSV, '|', "firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
}
|
||||
csvWriter := csv.NewWriter(writer)
|
||||
if err := cdre.writeCsv(csvWriter); err != nil {
|
||||
t.Error("Unexpected error: ", err)
|
||||
}
|
||||
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|default|*voice|dsafdsaf|rated|*out|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10000000000|1.0100`
|
||||
result := strings.TrimSpace(writer.String())
|
||||
if result != expected {
|
||||
t.Errorf("Expected: \n%s received: \n%s.", expected, result)
|
||||
}
|
||||
if cdre.TotalCost() != 1.01 {
|
||||
t.Error("Unexpected TotalCost: ", cdre.TotalCost())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ var trailerCfgFlds = []*config.CgrXmlCfgCdrField{
|
||||
&config.CgrXmlCfgCdrField{Name: "DistributorCode", Type: CONSTANT, Value: "VOI", Width: 3},
|
||||
&config.CgrXmlCfgCdrField{Name: "FileSeqNr", Type: METATAG, Value: META_EXPORTID, Width: 5, Strip: "right", Padding: "zeroleft"},
|
||||
&config.CgrXmlCfgCdrField{Name: "NumberOfRecords", Type: METATAG, Value: META_NRCDRS, Width: 6, Padding: "zeroleft"},
|
||||
&config.CgrXmlCfgCdrField{Name: "CdrsDuration", Type: METATAG, Value: META_DURCDRS, Width: 8, Padding: "zeroleft"},
|
||||
&config.CgrXmlCfgCdrField{Name: "CdrsDuration", Type: METATAG, Value: META_DURCDRS, Width: 8, Padding: "zeroleft", Layout: "seconds"},
|
||||
&config.CgrXmlCfgCdrField{Name: "FirstCdrTime", Type: METATAG, Value: META_FIRSTCDRATIME, Width: 12, Layout: "020106150400"},
|
||||
&config.CgrXmlCfgCdrField{Name: "LastCdrTime", Type: METATAG, Value: META_LASTCDRATIME, Width: 12, Layout: "020106150400"},
|
||||
&config.CgrXmlCfgCdrField{Name: "Filler2", Type: FILLER, Width: 93},
|
||||
@@ -86,7 +86,8 @@ func TestWriteCdr(t *testing.T) {
|
||||
Content: &config.CgrXmlCfgCdrContent{Fields: contentCfgFlds},
|
||||
Trailer: &config.CgrXmlCfgCdrTrailer{Fields: trailerCfgFlds},
|
||||
}
|
||||
cdr := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 1, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
cdr := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()),
|
||||
TOR: utils.VOICE, OrderId: 1, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC),
|
||||
@@ -94,7 +95,7 @@ func TestWriteCdr(t *testing.T) {
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 2.34567,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
|
||||
}
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr}, logDb, exportTpl.AsCdreConfig(), utils.CDRE_FIXED_WIDTH, "fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify)
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr}, logDb, exportTpl.AsCdreConfig(), utils.CDRE_FIXED_WIDTH, ',', "fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -144,14 +145,16 @@ func TestWriteCdrs(t *testing.T) {
|
||||
Content: &config.CgrXmlCfgCdrContent{Fields: contentCfgFlds},
|
||||
Trailer: &config.CgrXmlCfgCdrTrailer{Fields: trailerCfgFlds},
|
||||
}
|
||||
cdr1 := &utils.StoredCdr{CgrId: utils.Sha1("aaa1", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 2, AccId: "aaa1", CdrHost: "192.168.1.1", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
cdr1 := &utils.StoredCdr{CgrId: utils.Sha1("aaa1", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()),
|
||||
TOR: utils.VOICE, OrderId: 2, AccId: "aaa1", CdrHost: "192.168.1.1", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1001", Subject: "1001", Destination: "1010",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC),
|
||||
AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 2.25,
|
||||
ExtraFields: map[string]string{"productnumber": "12341", "fieldextr2": "valextr2"},
|
||||
}
|
||||
cdr2 := &utils.StoredCdr{CgrId: utils.Sha1("aaa2", time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String()), OrderId: 4, AccId: "aaa2", CdrHost: "192.168.1.2", ReqType: "prepaid", Direction: "*out", Tenant: "cgrates.org",
|
||||
cdr2 := &utils.StoredCdr{CgrId: utils.Sha1("aaa2", time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String()),
|
||||
TOR: utils.VOICE, OrderId: 4, AccId: "aaa2", CdrHost: "192.168.1.2", ReqType: "prepaid", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1002", Subject: "1002", Destination: "1011",
|
||||
SetupTime: time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC),
|
||||
AnswerTime: time.Date(2013, 11, 7, 7, 42, 26, 0, time.UTC),
|
||||
@@ -159,7 +162,8 @@ func TestWriteCdrs(t *testing.T) {
|
||||
ExtraFields: map[string]string{"productnumber": "12342", "fieldextr2": "valextr2"},
|
||||
}
|
||||
cdr3 := &utils.StoredCdr{}
|
||||
cdr4 := &utils.StoredCdr{CgrId: utils.Sha1("aaa3", time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC).String()), OrderId: 3, AccId: "aaa4", CdrHost: "192.168.1.4", ReqType: "postpaid", Direction: "*out", Tenant: "cgrates.org",
|
||||
cdr4 := &utils.StoredCdr{CgrId: utils.Sha1("aaa3", time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC).String()),
|
||||
TOR: utils.VOICE, OrderId: 3, AccId: "aaa4", CdrHost: "192.168.1.4", ReqType: "postpaid", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1004", Subject: "1004", Destination: "1013",
|
||||
SetupTime: time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC),
|
||||
AnswerTime: time.Date(2013, 11, 7, 9, 42, 26, 0, time.UTC),
|
||||
@@ -167,7 +171,7 @@ func TestWriteCdrs(t *testing.T) {
|
||||
ExtraFields: map[string]string{"productnumber": "12344", "fieldextr2": "valextr2"},
|
||||
}
|
||||
cfg, _ := config.NewDefaultCGRConfig()
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr1, cdr2, cdr3, cdr4}, logDb, exportTpl.AsCdreConfig(), utils.CDRE_FIXED_WIDTH,
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr1, cdr2, cdr3, cdr4}, logDb, exportTpl.AsCdreConfig(), utils.CDRE_FIXED_WIDTH, ',',
|
||||
"fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -52,6 +52,7 @@ func NewDefaultCdreConfig() (*CdreConfig, error) {
|
||||
// One instance of CdrExporter
|
||||
type CdreConfig struct {
|
||||
CdrFormat string
|
||||
FieldSeparator rune
|
||||
DataUsageMultiplyFactor float64
|
||||
CostMultiplyFactor float64
|
||||
CostRoundingDecimals int
|
||||
@@ -67,6 +68,7 @@ type CdreConfig struct {
|
||||
// Set here defaults
|
||||
func (cdreCfg *CdreConfig) setDefaults() error {
|
||||
cdreCfg.CdrFormat = utils.CSV
|
||||
cdreCfg.FieldSeparator = utils.CSV_SEP
|
||||
cdreCfg.DataUsageMultiplyFactor = 0.0
|
||||
cdreCfg.CostMultiplyFactor = 0.0
|
||||
cdreCfg.CostRoundingDecimals = -1
|
||||
|
||||
@@ -74,6 +74,7 @@ func TestCdreCfgValueAsRSRField(t *testing.T) {
|
||||
func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
eCdreCfg := new(CdreConfig)
|
||||
eCdreCfg.CdrFormat = utils.CSV
|
||||
eCdreCfg.FieldSeparator = utils.CSV_SEP
|
||||
eCdreCfg.DataUsageMultiplyFactor = 0.0
|
||||
eCdreCfg.CostMultiplyFactor = 0.0
|
||||
eCdreCfg.CostRoundingDecimals = -1
|
||||
|
||||
@@ -207,6 +207,7 @@ func TestConfigFromFile(t *testing.T) {
|
||||
eCfg.CDRSMediator = "test"
|
||||
eCfg.CdreDefaultInstance = &CdreConfig{
|
||||
CdrFormat: "test",
|
||||
FieldSeparator: utils.CSV_SEP,
|
||||
DataUsageMultiplyFactor: 99.0,
|
||||
CostMultiplyFactor: 99.0,
|
||||
CostRoundingDecimals: 99,
|
||||
@@ -308,7 +309,7 @@ export_template = cgrid,mediation_runid,accid
|
||||
&CdreCdrField{Name: "accid", Type: utils.CDRFIELD, Value: "accid", valueAsRsrField: &utils.RSRField{Id: "accid"},
|
||||
Mandatory: true},
|
||||
}
|
||||
expCdreCfg := &CdreConfig{CdrFormat: utils.CSV, CostRoundingDecimals: -1, ExportDir: "/var/log/cgrates/cdre", ContentFields: expectedFlds}
|
||||
expCdreCfg := &CdreConfig{CdrFormat: utils.CSV, FieldSeparator: utils.CSV_SEP, CostRoundingDecimals: -1, ExportDir: "/var/log/cgrates/cdre", ContentFields: expectedFlds}
|
||||
if cfg, err := NewCGRConfigFromBytes(eFieldsCfg); err != nil {
|
||||
t.Error("Could not parse the config", err.Error())
|
||||
} else if !reflect.DeepEqual(cfg.CdreDefaultInstance, expCdreCfg) {
|
||||
|
||||
@@ -24,14 +24,14 @@ import (
|
||||
)
|
||||
|
||||
type CgrXmlCdrcCfg struct {
|
||||
Enabled bool `xml:"enabled"` // Enable/Disable the
|
||||
CdrsAddress string `xml:"cdrs_address"` // The address where CDRs can be reached
|
||||
CdrType string `xml:"cdr_type"` // The type of CDR to process <csv>
|
||||
CsvSeparator string `xml:"csv_separator"` // The separator to use when reading csvs
|
||||
RunDelay int64 `xml:"run_delay"` // Delay between runs
|
||||
CdrInDir string `xml:"cdr_in_dir"` // Folder to process CDRs from
|
||||
CdrOutDir string `xml:"cdr_out_dir"` // Folder to move processed CDRs to
|
||||
CdrSourceId string `xml:"cdr_source_id"` // Source identifier for the processed CDRs
|
||||
Enabled bool `xml:"enabled"` // Enable/Disable the
|
||||
CdrsAddress string `xml:"cdrs_address"` // The address where CDRs can be reached
|
||||
CdrType string `xml:"cdr_type"` // The type of CDR to process <csv>
|
||||
CsvSeparator string `xml:"field_separator"` // The separator to use when reading csvs
|
||||
RunDelay int64 `xml:"run_delay"` // Delay between runs
|
||||
CdrInDir string `xml:"cdr_in_dir"` // Folder to process CDRs from
|
||||
CdrOutDir string `xml:"cdr_out_dir"` // Folder to move processed CDRs to
|
||||
CdrSourceId string `xml:"cdr_source_id"` // Source identifier for the processed CDRs
|
||||
CdrFields []*CdrcField `xml:"fields>field"`
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
// The CdrExporter configuration instance
|
||||
type CgrXmlCdreCfg struct {
|
||||
CdrFormat *string `xml:"cdr_format"`
|
||||
FieldSeparator *string `xml:"field_separator"`
|
||||
DataUsageMultiplyFactor *float64 `xml:"data_usage_multiply_factor"`
|
||||
CostMultiplyFactor *float64 `xml:"cost_multiply_factor"`
|
||||
CostRoundingDecimals *int `xml:"cost_rounding_decimals"`
|
||||
@@ -43,6 +44,10 @@ func (xmlCdreCfg *CgrXmlCdreCfg) AsCdreConfig() *CdreConfig {
|
||||
if xmlCdreCfg.CdrFormat != nil {
|
||||
cdreCfg.CdrFormat = *xmlCdreCfg.CdrFormat
|
||||
}
|
||||
if xmlCdreCfg.FieldSeparator != nil && len(*xmlCdreCfg.FieldSeparator) == 1 {
|
||||
sepStr := *xmlCdreCfg.FieldSeparator
|
||||
cdreCfg.FieldSeparator = rune(sepStr[0])
|
||||
}
|
||||
if xmlCdreCfg.DataUsageMultiplyFactor != nil {
|
||||
cdreCfg.DataUsageMultiplyFactor = *xmlCdreCfg.DataUsageMultiplyFactor
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ func TestXmlCdreCfgAsCdreConfig(t *testing.T) {
|
||||
<document type="cgrates/xml">
|
||||
<configuration section="cdre" type="fixed_width" id="CDRE-FW2">
|
||||
<cdr_format>fwv</cdr_format>
|
||||
<field_separator>;</field_separator>
|
||||
<data_usage_multiply_factor>1024.0</data_usage_multiply_factor>
|
||||
<cost_multiply_factor>1.19</cost_multiply_factor>
|
||||
<cost_rounding_decimals>-1</cost_rounding_decimals>
|
||||
@@ -212,6 +213,7 @@ func TestXmlCdreCfgAsCdreConfig(t *testing.T) {
|
||||
}
|
||||
eCdreCfg := &CdreConfig{
|
||||
CdrFormat: "fwv",
|
||||
FieldSeparator: ';',
|
||||
DataUsageMultiplyFactor: 1024.0,
|
||||
CostMultiplyFactor: 1.19,
|
||||
CostRoundingDecimals: -1,
|
||||
|
||||
@@ -328,6 +328,7 @@ type CachedItemAge struct {
|
||||
|
||||
type AttrExpFileCdrs struct {
|
||||
CdrFormat *string // Cdr output file format <utils.CdreCdrFormats>
|
||||
FieldSeparator *rune // Separator used between fields
|
||||
ExportId *string // Optional exportid
|
||||
ExportDir *string // If provided it overwrites the configured export directory
|
||||
ExportFileName *string // If provided the output filename will be set to this
|
||||
|
||||
Reference in New Issue
Block a user