CDRC config changes: renaming cdr_fields into content_fields, adding new header_fields and trailer_fields options

This commit is contained in:
DanB
2015-07-27 13:09:54 +02:00
parent 67ec46ccd9
commit 6d1076870f
17 changed files with 87 additions and 45 deletions

View File

@@ -130,7 +130,7 @@ func NewCdrc(cdrcCfgs map[string]*config.CdrcConfig, httpSkipTlsCheck bool, cdrs
cdrc.cdrSourceIds[idx] = cfg.CdrSourceId
cdrc.duMultiplyFactors[idx] = cfg.DataUsageMultiplyFactor
cdrc.cdrFilters[idx] = cfg.CdrFilter
cdrc.cdrFields[idx] = cfg.CdrFields
cdrc.cdrFields[idx] = cfg.ContentFields
idx += 1
}
// Before processing, make sure in and out folders exist
@@ -249,6 +249,8 @@ func (self *Cdrc) processFile(filePath string) error {
csvReader.Comma = self.csvSep
recordsProcessor = NewCsvRecordsProcessor(csvReader, self.cdrFormat, fn, self.failedCallsPrefix,
self.cdrSourceIds, self.duMultiplyFactors, self.cdrFilters, self.cdrFields, self.httpSkipTlsCheck, self.partialRecordsCache)
} else if self.cdrFormat == utils.FWV {
recordsProcessor = NewFwvRecordsProcessor(file)
}
procRowNr := 0
timeStart := time.Now()

View File

@@ -31,10 +31,10 @@ import (
func TestCsvRecordForkCdr(t *testing.T) {
cgrConfig, _ := config.NewDefaultCGRConfig()
cdrcConfig := cgrConfig.CdrcProfiles["/var/log/cgrates/cdrc/in"][utils.META_DEFAULT]
cdrcConfig.CdrFields = append(cdrcConfig.CdrFields, &config.CfgCdrField{Tag: "SupplierTest", Type: utils.CDRFIELD, CdrFieldId: "supplier", Value: []*utils.RSRField{&utils.RSRField{Id: "14"}}})
cdrcConfig.CdrFields = append(cdrcConfig.CdrFields, &config.CfgCdrField{Tag: "DisconnectCauseTest", Type: utils.CDRFIELD, CdrFieldId: utils.DISCONNECT_CAUSE,
cdrcConfig.ContentFields = append(cdrcConfig.ContentFields, &config.CfgCdrField{Tag: "SupplierTest", Type: utils.CDRFIELD, CdrFieldId: "supplier", Value: []*utils.RSRField{&utils.RSRField{Id: "14"}}})
cdrcConfig.ContentFields = append(cdrcConfig.ContentFields, &config.CfgCdrField{Tag: "DisconnectCauseTest", Type: utils.CDRFIELD, CdrFieldId: utils.DISCONNECT_CAUSE,
Value: []*utils.RSRField{&utils.RSRField{Id: "16"}}})
csvProcessor := &CsvRecordsProcessor{cdrFormat: CSV, cdrSourceIds: []string{"TEST_CDRC"}, cdrFields: [][]*config.CfgCdrField{cdrcConfig.CdrFields}}
csvProcessor := &CsvRecordsProcessor{cdrFormat: CSV, cdrSourceIds: []string{"TEST_CDRC"}, cdrFields: [][]*config.CfgCdrField{cdrcConfig.ContentFields}}
cdrRow := []string{"firstField", "secondField"}
_, err := csvProcessor.recordToStoredCdr(cdrRow, 0)
if err == nil {

View File

@@ -38,7 +38,9 @@ type CdrcConfig struct {
CdrSourceId string // Source identifier for the processed CDRs
CdrFilter utils.RSRFields // Filter CDR records to import
PartialRecordCache time.Duration // Duration to cache partial records when not pairing
CdrFields []*CfgCdrField // List of fields to be processed
HeaderFields []*CfgCdrField
ContentFields []*CfgCdrField
TrailerFields []*CfgCdrField
}
func (self *CdrcConfig) loadFromJsonCfg(jsnCfg *CdrcJsonCfg) error {
@@ -90,8 +92,18 @@ func (self *CdrcConfig) loadFromJsonCfg(jsnCfg *CdrcJsonCfg) error {
return err
}
}
if jsnCfg.Cdr_fields != nil {
if self.CdrFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Cdr_fields); err != nil {
if jsnCfg.Header_fields != nil {
if self.HeaderFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Header_fields); err != nil {
return err
}
}
if jsnCfg.Content_fields != nil {
if self.ContentFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Content_fields); err != nil {
return err
}
}
if jsnCfg.Trailer_fields != nil {
if self.TrailerFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Trailer_fields); err != nil {
return err
}
}
@@ -111,10 +123,20 @@ func (self *CdrcConfig) Clone() *CdrcConfig {
clnCdrc.CdrInDir = self.CdrInDir
clnCdrc.CdrOutDir = self.CdrOutDir
clnCdrc.CdrSourceId = self.CdrSourceId
clnCdrc.CdrFields = make([]*CfgCdrField, len(self.CdrFields))
for idx, fld := range self.CdrFields {
clnCdrc.HeaderFields = make([]*CfgCdrField, len(self.HeaderFields))
clnCdrc.ContentFields = make([]*CfgCdrField, len(self.ContentFields))
clnCdrc.TrailerFields = make([]*CfgCdrField, len(self.TrailerFields))
for idx, fld := range self.HeaderFields {
clonedVal := *fld
clnCdrc.CdrFields[idx] = &clonedVal
clnCdrc.HeaderFields[idx] = &clonedVal
}
for idx, fld := range self.ContentFields {
clonedVal := *fld
clnCdrc.ContentFields[idx] = &clonedVal
}
for idx, fld := range self.TrailerFields {
clonedVal := *fld
clnCdrc.TrailerFields[idx] = &clonedVal
}
return clnCdrc
}

View File

@@ -32,7 +32,7 @@
"data_usage_multiply_factor": 0.000976563,
"run_delay": 1,
"cdr_source_id": "csv2", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"cdr_field_id": "tor", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
{"cdr_field_id": "answer_time", "value": "1"},
{"cdr_field_id": "usage", "value": "~9:s/^(\\d+)$/${1}s/"},

View File

@@ -7,7 +7,7 @@
"cdr_out_dir": "/tmp/cgrates/cdrc2/out", // absolute path towards the directory where processed CDRs will be moved
"data_usage_multiply_factor": 0.000976563,
"cdr_source_id": "csv2", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"cdr_field_id": "tor", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
{"cdr_field_id": "answer_time", "value": "2"},
],

View File

@@ -273,11 +273,11 @@ func (self *CGRConfig) checkConfigSanity() error {
} else if cdrcInst.Cdrs == utils.INTERNAL && !self.CDRSEnabled {
return errors.New("CDRS not enabled but referenced from CDRC")
}
if len(cdrcInst.CdrFields) == 0 {
if len(cdrcInst.ContentFields) == 0 {
return errors.New("CdrC enabled but no fields to be processed defined!")
}
if cdrcInst.CdrFormat == utils.CSV {
for _, cdrFld := range cdrcInst.CdrFields {
for _, cdrFld := range cdrcInst.ContentFields {
for _, rsrFld := range cdrFld.Value {
if _, errConv := strconv.Atoi(rsrFld.Id); errConv != nil && !rsrFld.IsStatic() {
return fmt.Errorf("CDR fields must be indices in case of .csv files, have instead: %s", rsrFld.Id)

View File

@@ -168,7 +168,8 @@ const CGRATES_CFG_JSON = `
"cdr_source_id": "freeswitch_csv", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_filter": "", // filter CDR records to import
"partial_record_cache": "10s", // duration to cache partial records when not pairing
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"header_fields": [], // template of the import header fields
"content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"tag": "tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "2", "mandatory": true},
{"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "3", "mandatory": true},
{"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "4", "mandatory": true},
@@ -182,6 +183,7 @@ const CGRATES_CFG_JSON = `
{"tag": "answer_time", "cdr_field_id": "answer_time", "type": "cdrfield", "value": "12", "mandatory": true},
{"tag": "usage", "cdr_field_id": "usage", "type": "cdrfield", "value": "13", "mandatory": true},
],
"trailer_fields": [], // template of the import trailer fields
}
},

View File

@@ -259,6 +259,7 @@ func TestDfCdreJsonCfgs(t *testing.T) {
}
func TestDfCdrcJsonCfg(t *testing.T) {
eFields := []*CdrFieldJsonCfg{}
cdrFields := []*CdrFieldJsonCfg{
&CdrFieldJsonCfg{Tag: utils.StringPointer("tor"), Cdr_field_id: utils.StringPointer("tor"), Type: utils.StringPointer(utils.CDRFIELD),
Value: utils.StringPointer("2"), Mandatory: utils.BoolPointer(true)},
@@ -300,13 +301,15 @@ func TestDfCdrcJsonCfg(t *testing.T) {
Cdr_source_id: utils.StringPointer("freeswitch_csv"),
Cdr_filter: utils.StringPointer(""),
Partial_record_cache: utils.StringPointer("10s"),
Cdr_fields: &cdrFields,
Header_fields: &eFields,
Content_fields: &cdrFields,
Trailer_fields: &eFields,
},
}
if cfg, err := dfCgrJsonCfg.CdrcJsonCfg(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCfg, cfg) {
t.Error("Received: ", cfg)
t.Error("Received: ", cfg["*default"])
}
}
@@ -423,6 +426,7 @@ func TestDfUserServJsonCfg(t *testing.T) {
}
func TestDfMailerJsonCfg(t *testing.T) {
eCfg := &MailerJsonCfg{
Server: utils.StringPointer("localhost"),
Auth_user: utils.StringPointer("cgrates"),
@@ -466,15 +470,14 @@ func TestNewCgrJsonCfgFromFile(t *testing.T) {
Cdr_in_dir: utils.StringPointer("/tmp/cgrates/cdrc2/in"),
Cdr_out_dir: utils.StringPointer("/tmp/cgrates/cdrc2/out"),
Cdr_source_id: utils.StringPointer("csv2"),
Cdr_fields: &cdrFields,
Content_fields: &cdrFields,
},
}
if cfg, err := cgrJsonCfg.CdrcJsonCfg(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCfgCdrc, cfg) {
t.Error("Received: ", cfg)
t.Error("Received: ", cfg["CDRC-CSV2"])
}
eCfgSmFs := &SmFsJsonCfg{
Enabled: utils.BoolPointer(true),
Connections: &[]*FsConnJsonCfg{

View File

@@ -49,7 +49,8 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
CdrSourceId: "freeswitch_csv",
CdrFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP),
PartialRecordCache: time.Duration(10) * time.Second,
CdrFields: []*CfgCdrField{
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
&CfgCdrField{Tag: "tor", Type: "cdrfield", CdrFieldId: "tor", Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
&CfgCdrField{Tag: "accid", Type: "cdrfield", CdrFieldId: "accid", Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
@@ -75,6 +76,7 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
&CfgCdrField{Tag: "usage", Type: "cdrfield", CdrFieldId: "usage", Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
},
TrailerFields: make([]*CfgCdrField, 0),
},
}
eCgrCfg.CdrcProfiles["/tmp/cgrates/cdrc1/in"] = map[string]*CdrcConfig{
@@ -90,7 +92,8 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
CdrOutDir: "/tmp/cgrates/cdrc1/out",
CdrSourceId: "csv1",
CdrFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP),
CdrFields: []*CfgCdrField{
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
&CfgCdrField{Tag: "tor", Type: "cdrfield", CdrFieldId: "tor", Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
&CfgCdrField{Tag: "accid", Type: "cdrfield", CdrFieldId: "accid", Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
@@ -116,6 +119,7 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
&CfgCdrField{Tag: "usage", Type: "cdrfield", CdrFieldId: "usage", Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
},
TrailerFields: make([]*CfgCdrField, 0),
},
}
eCgrCfg.CdrcProfiles["/tmp/cgrates/cdrc2/in"] = map[string]*CdrcConfig{
@@ -131,12 +135,14 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
CdrOutDir: "/tmp/cgrates/cdrc2/out",
CdrSourceId: "csv2",
CdrFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP),
CdrFields: []*CfgCdrField{
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
&CfgCdrField{Tag: "", Type: "", CdrFieldId: "tor", Value: utils.ParseRSRFieldsMustCompile("~7:s/^(voice|data|sms|generic)$/*$1/", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false},
&CfgCdrField{Tag: "", Type: "", CdrFieldId: "answer_time", Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false},
},
TrailerFields: make([]*CfgCdrField, 0),
},
}
eCgrCfg.CdrcProfiles["/tmp/cgrates/cdrc3/in"] = map[string]*CdrcConfig{
@@ -152,7 +158,8 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
CdrOutDir: "/tmp/cgrates/cdrc3/out",
CdrSourceId: "csv3",
CdrFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP),
CdrFields: []*CfgCdrField{
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
&CfgCdrField{Tag: "tor", Type: "cdrfield", CdrFieldId: "tor", Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
&CfgCdrField{Tag: "accid", Type: "cdrfield", CdrFieldId: "accid", Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
@@ -178,6 +185,7 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
&CfgCdrField{Tag: "usage", Type: "cdrfield", CdrFieldId: "usage", Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
},
TrailerFields: make([]*CfgCdrField, 0),
},
}
if !reflect.DeepEqual(eCgrCfg.CdrcProfiles, cgrCfg.CdrcProfiles) {

View File

@@ -139,7 +139,9 @@ type CdrcJsonCfg struct {
Cdr_filter *string
Max_open_files *int
Partial_record_cache *string
Cdr_fields *[]*CdrFieldJsonCfg
Header_fields *[]*CdrFieldJsonCfg
Content_fields *[]*CdrFieldJsonCfg
Trailer_fields *[]*CdrFieldJsonCfg
}
// SM-FreeSWITCH config section

View File

@@ -148,7 +148,8 @@
// "cdr_source_id": "freeswitch_csv", // free form field, tag identifying the source of the CDRs within CDRS database
// "cdr_filter": "", // filter CDR records to import
// "partial_record_cache": "10s", // duration to cache partial records when not pairing
// "cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
// "header_fields": [], // template of the import header fields
// "content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
// {"tag": "tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "2", "mandatory": true},
// {"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "3", "mandatory": true},
// {"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "4", "mandatory": true},
@@ -162,7 +163,8 @@
// {"tag": "answer_time", "cdr_field_id": "answer_time", "type": "cdrfield", "value": "12", "mandatory": true},
// {"tag": "usage", "cdr_field_id": "usage", "type": "cdrfield", "value": "13", "mandatory": true},
// ],
// },
// "trailer_fields": [], // template of the import trailer fields
// }
//},

View File

@@ -24,20 +24,20 @@
"cdrc": {
"FLATSTORE": {
"enabled": true, // enable CDR client functionality
"cdrs": "internal", // address where to reach CDR server. <internal|x.y.z.y:1234>
"cdr_format": "opensips_flatstore", // CDR file format <csv|freeswitch_csv|fwv|opensips_flatstore>
"field_separator": "|", // separator used in case of csv files
"run_delay": 0, // sleep interval in seconds between consecutive runs, 0 to use automation via inotify
"max_open_files": 1024, // maximum simultaneous files to process
"data_usage_multiply_factor": 1024, // conversion factor for data usage
"cdr_in_dir": "/tmp/cgr_flatstore/cdrc/in", // absolute path towards the directory where the CDRs are stored
"enabled": true, // enable CDR client functionality
"cdrs": "internal", // address where to reach CDR server. <internal|x.y.z.y:1234>
"cdr_format": "opensips_flatstore", // CDR file format <csv|freeswitch_csv|fwv|opensips_flatstore>
"field_separator": "|", // separator used in case of csv files
"run_delay": 0, // sleep interval in seconds between consecutive runs, 0 to use automation via inotify
"max_open_files": 1024, // maximum simultaneous files to process
"data_usage_multiply_factor": 1024, // conversion factor for data usage
"cdr_in_dir": "/tmp/cgr_flatstore/cdrc/in", // absolute path towards the directory where the CDRs are stored
"cdr_out_dir": "/tmp/cgr_flatstore/cdrc/out", // absolute path towards the directory where processed CDRs will be moved
"failed_calls_prefix": "missed_calls", // used in case of flatstore CDRs to avoid searching for BYE records
"cdr_source_id": "flatstore", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_filter": "", // filter CDR records to import
"partial_record_cache": "1s", // duration to cache partial records when not pairing
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"failed_calls_prefix": "missed_calls", // used in case of flatstore CDRs to avoid searching for BYE records
"cdr_source_id": "flatstore", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_filter": "", // filter CDR records to import
"partial_record_cache": "1s", // duration to cache partial records when not pairing
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"tag": "Tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "^*voice", "mandatory": true},
{"tag": "AccId", "cdr_field_id": "accid", "type": "cdrfield", "mandatory": true},
{"tag": "ReqType", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "7", "mandatory": true},

View File

@@ -7,7 +7,7 @@
"cdr_in_dir": "/tmp/cgrates/cdrc_fs/in", // absolute path towards the directory where the CDRs are stored
"cdr_out_dir": "/tmp/cgrates/cdrc_fs/out", // absolute path towards the directory where processed CDRs will be moved
"cdr_source_id": "fs_csv", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"tag": "tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "^*voice", "mandatory": true},
{"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "10", "mandatory": true},
{"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "^rated", "mandatory": true},

View File

@@ -29,7 +29,7 @@
"cdr_in_dir": "/tmp/cgrates/cdrc2/in", // absolute path towards the directory where the CDRs are stored
"cdr_out_dir": "/tmp/cgrates/cdrc2/out", // absolute path towards the directory where processed CDRs will be moved
"cdr_source_id": "csv2", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"cdr_field_id": "tor", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
{"cdr_field_id": "accid", "value": "0"},
{"cdr_field_id": "reqtype", "value": "^rated"},
@@ -50,7 +50,7 @@
"cdr_in_dir": "/tmp/cgrates/cdrc3/in", // absolute path towards the directory where the CDRs are stored
"cdr_out_dir": "/tmp/cgrates/cdrc3/out", // absolute path towards the directory where processed CDRs will be moved
"cdr_source_id": "csv3", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"cdr_field_id": "tor", "value": "^*voice"},
{"cdr_field_id": "accid", "value": "~3:s/^(\\d{2})\\.(\\d{2})\\.(\\d{4})\\s{2}(\\d{2}):(\\d{2}):(\\d{2})$/$1$2$3$4$5$6/"},
{"cdr_field_id": "reqtype", "value": "^rated"},

View File

@@ -7,7 +7,7 @@
"cdr_in_dir": "/tmp/cgr_fsevsock/cgrates/cdrc/in", // absolute path towards the directory where the CDRs are stored
"cdr_out_dir": "/tmp/cgr_fsevsock/cgrates/cdrc/out", // absolute path towards the directory where processed CDRs will be moved
"cdr_source_id": "fs_csv", // free form field, tag identifying the source of the CDRs within CDRS database
"cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
{"tag": "tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "^*voice", "mandatory": true},
{"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "10", "mandatory": true},
{"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "^*pseudoprepaid", "mandatory": true},

View File

@@ -184,7 +184,7 @@
// "cdr_out_dir": "/var/log/cgrates/cdrc/out", // absolute path towards the directory where processed CDRs will be moved
// "cdr_source_id": "freeswitch_csv", // free form field, tag identifying the source of the CDRs within CDRS database
// "cdr_filter": "", // Filter CDR records to import
// "cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
// "content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
// {"tag": "tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "2", "mandatory": true},
// {"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "3", "mandatory": true},
// {"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "4", "mandatory": true},

View File

@@ -123,6 +123,7 @@ const (
META_DEFAULT = "*default"
STATIC_VALUE_PREFIX = "^"
CSV = "csv"
FWV = "fwv"
DRYRUN = "dry_run"
COMBIMED = "combimed"
INTERNAL = "internal"