Adding FieldMultiplyFactor so we can clone it centralized

This commit is contained in:
DanB
2017-02-12 19:19:47 +01:00
parent bf968fed21
commit 393c1acbd0
13 changed files with 170 additions and 257 deletions

View File

@@ -1,18 +0,0 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package cdre

View File

@@ -17,19 +17,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package config
import (
"github.com/cgrates/cgrates/utils"
)
// One instance of CdrExporter
type CdreConfig struct {
CdrFormat string
FieldSeparator rune
DataUsageMultiplyFactor float64
SMSUsageMultiplyFactor float64
MMSUsageMultiplyFactor float64
GenericUsageMultiplyFactor float64
CostMultiplyFactor float64
ExportDirectory string
HeaderFields []*CfgCdrField
ContentFields []*CfgCdrField
TrailerFields []*CfgCdrField
ExportFormat string
ExportPath string
Synchronous bool
Attempts int
FieldSeparator rune
UsageMultiplyFactor utils.FieldMultiplyFactor
CostMultiplyFactor float64
HeaderFields []*CfgCdrField
ContentFields []*CfgCdrField
TrailerFields []*CfgCdrField
}
func (self *CdreConfig) loadFromJsonCfg(jsnCfg *CdreJsonCfg) error {
@@ -37,31 +40,33 @@ func (self *CdreConfig) loadFromJsonCfg(jsnCfg *CdreJsonCfg) error {
return nil
}
var err error
if jsnCfg.Cdr_format != nil {
self.CdrFormat = *jsnCfg.Cdr_format
if jsnCfg.Export_format != nil {
self.ExportFormat = *jsnCfg.Export_format
}
if jsnCfg.Export_path != nil {
self.ExportPath = *jsnCfg.Export_path
}
if jsnCfg.Synchronous != nil {
self.Synchronous = *jsnCfg.Synchronous
}
if jsnCfg.Attempts != nil {
self.Attempts = *jsnCfg.Attempts
}
if jsnCfg.Field_separator != nil && len(*jsnCfg.Field_separator) > 0 { // Make sure we got at least one character so we don't get panic here
sepStr := *jsnCfg.Field_separator
self.FieldSeparator = rune(sepStr[0])
}
if jsnCfg.Data_usage_multiply_factor != nil {
self.DataUsageMultiplyFactor = *jsnCfg.Data_usage_multiply_factor
}
if jsnCfg.Sms_usage_multiply_factor != nil {
self.SMSUsageMultiplyFactor = *jsnCfg.Sms_usage_multiply_factor
}
if jsnCfg.Mms_usage_multiply_factor != nil {
self.MMSUsageMultiplyFactor = *jsnCfg.Mms_usage_multiply_factor
}
if jsnCfg.Generic_usage_multiply_factor != nil {
self.GenericUsageMultiplyFactor = *jsnCfg.Generic_usage_multiply_factor
if jsnCfg.Usage_multiply_factor != nil {
if self.UsageMultiplyFactor == nil { // not yet initialized
self.UsageMultiplyFactor = make(map[string]float64, len(*jsnCfg.Usage_multiply_factor))
}
for k, v := range *jsnCfg.Usage_multiply_factor {
self.UsageMultiplyFactor[k] = v
}
}
if jsnCfg.Cost_multiply_factor != nil {
self.CostMultiplyFactor = *jsnCfg.Cost_multiply_factor
}
if jsnCfg.Export_directory != nil {
self.ExportDirectory = *jsnCfg.Export_directory
}
if jsnCfg.Header_fields != nil {
if self.HeaderFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Header_fields); err != nil {
return err
@@ -83,14 +88,16 @@ func (self *CdreConfig) loadFromJsonCfg(jsnCfg *CdreJsonCfg) error {
// Clone itself into a new CdreConfig
func (self *CdreConfig) Clone() *CdreConfig {
clnCdre := new(CdreConfig)
clnCdre.CdrFormat = self.CdrFormat
clnCdre.ExportFormat = self.ExportFormat
clnCdre.ExportPath = self.ExportPath
clnCdre.Synchronous = self.Synchronous
clnCdre.Attempts = self.Attempts
clnCdre.FieldSeparator = self.FieldSeparator
clnCdre.DataUsageMultiplyFactor = self.DataUsageMultiplyFactor
clnCdre.SMSUsageMultiplyFactor = self.SMSUsageMultiplyFactor
clnCdre.MMSUsageMultiplyFactor = self.MMSUsageMultiplyFactor
clnCdre.GenericUsageMultiplyFactor = self.GenericUsageMultiplyFactor
clnCdre.UsageMultiplyFactor = make(map[string]float64, len(self.UsageMultiplyFactor))
for k, v := range self.UsageMultiplyFactor {
clnCdre.UsageMultiplyFactor[k] = v
}
clnCdre.CostMultiplyFactor = self.CostMultiplyFactor
clnCdre.ExportDirectory = self.ExportDirectory
clnCdre.HeaderFields = make([]*CfgCdrField, len(self.HeaderFields))
for idx, fld := range self.HeaderFields {
clonedVal := *fld

View File

@@ -25,8 +25,8 @@ import (
)
func TestCdreCfgClone(t *testing.T) {
cgrIdRsrs, _ := utils.ParseRSRFields("cgrid", utils.INFIELD_SEP)
runIdRsrs, _ := utils.ParseRSRFields("mediation_runid", utils.INFIELD_SEP)
cgrIdRsrs := utils.ParseRSRFieldsMustCompile("cgrid", utils.INFIELD_SEP)
runIdRsrs := utils.ParseRSRFieldsMustCompile("runid", utils.INFIELD_SEP)
emptyFields := []*CfgCdrField{}
initContentFlds := []*CfgCdrField{
&CfgCdrField{Tag: "CgrId",
@@ -35,16 +35,21 @@ func TestCdreCfgClone(t *testing.T) {
Value: cgrIdRsrs},
&CfgCdrField{Tag: "RunId",
Type: "*composed",
FieldId: "mediation_runid",
FieldId: "runid",
Value: runIdRsrs},
}
initCdreCfg := &CdreConfig{
CdrFormat: "csv",
FieldSeparator: rune(','),
DataUsageMultiplyFactor: 1.0,
CostMultiplyFactor: 1.0,
ExportDirectory: "/var/spool/cgrates/cdre",
ContentFields: initContentFlds,
ExportFormat: utils.MetaFileCSV,
ExportPath: "/var/spool/cgrates/cdre",
Synchronous: true,
Attempts: 2,
FieldSeparator: rune(','),
UsageMultiplyFactor: map[string]float64{
utils.ANY: 1.0,
utils.DATA: 1024,
},
CostMultiplyFactor: 1.0,
ContentFields: initContentFlds,
}
eClnContentFlds := []*CfgCdrField{
&CfgCdrField{Tag: "CgrId",
@@ -53,24 +58,29 @@ func TestCdreCfgClone(t *testing.T) {
Value: cgrIdRsrs},
&CfgCdrField{Tag: "RunId",
Type: "*composed",
FieldId: "mediation_runid",
FieldId: "runid",
Value: runIdRsrs},
}
eClnCdreCfg := &CdreConfig{
CdrFormat: "csv",
FieldSeparator: rune(','),
DataUsageMultiplyFactor: 1.0,
CostMultiplyFactor: 1.0,
ExportDirectory: "/var/spool/cgrates/cdre",
HeaderFields: emptyFields,
ContentFields: eClnContentFlds,
TrailerFields: emptyFields,
ExportFormat: utils.MetaFileCSV,
ExportPath: "/var/spool/cgrates/cdre",
Synchronous: true,
Attempts: 2,
FieldSeparator: rune(','),
UsageMultiplyFactor: map[string]float64{
utils.ANY: 1.0,
utils.DATA: 1024.0,
},
CostMultiplyFactor: 1.0,
HeaderFields: emptyFields,
ContentFields: eClnContentFlds,
TrailerFields: emptyFields,
}
clnCdreCfg := initCdreCfg.Clone()
if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) {
t.Errorf("Cloned result: %+v", clnCdreCfg)
}
initCdreCfg.DataUsageMultiplyFactor = 1024.0
initCdreCfg.UsageMultiplyFactor[utils.DATA] = 2048.0
if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
t.Errorf("Cloned result: %+v", clnCdreCfg)
}

View File

@@ -1,44 +0,0 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package config
import (
"github.com/cgrates/cgrates/utils"
)
type CDRReplicationCfg struct {
Transport string
Address string
Synchronous bool
Attempts int // Number of attempts if not success
CdrFilter utils.RSRFields // Only replicate if the filters here are matching
ContentFields []*CfgCdrField
}
func (rplCfg CDRReplicationCfg) FallbackFileName() string {
fileSuffix := ".txt"
switch rplCfg.Transport {
case utils.MetaHTTPjsonCDR, utils.MetaHTTPjsonMap, utils.MetaAMQPjsonCDR, utils.MetaAMQPjsonMap:
fileSuffix = ".json"
case utils.META_HTTP_POST:
fileSuffix = ".form"
}
ffn := &utils.FallbackFileName{Module: "cdr", Transport: rplCfg.Transport, Address: rplCfg.Address,
RequestID: utils.GenUUID(), FileSuffix: fileSuffix}
return ffn.AsString()
}

View File

@@ -241,14 +241,14 @@ type CGRConfig struct {
CDRSStoreCdrs bool // store cdrs in storDb
CDRScdrAccountSummary bool
CDRSSMCostRetries int
CDRSRaterConns []*HaPoolConfig // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234>
CDRSPubSubSConns []*HaPoolConfig // address where to reach the pubsub service: <""|internal|x.y.z.y:1234>
CDRSUserSConns []*HaPoolConfig // address where to reach the users service: <""|internal|x.y.z.y:1234>
CDRSAliaseSConns []*HaPoolConfig // address where to reach the aliases service: <""|internal|x.y.z.y:1234>
CDRSStatSConns []*HaPoolConfig // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234>
CDRSCdrReplication []*CDRReplicationCfg // Replicate raw CDRs to a number of servers
CDRStatsEnabled bool // Enable CDR Stats service
CDRStatsSaveInterval time.Duration // Save interval duration
CDRSRaterConns []*HaPoolConfig // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234>
CDRSPubSubSConns []*HaPoolConfig // address where to reach the pubsub service: <""|internal|x.y.z.y:1234>
CDRSUserSConns []*HaPoolConfig // address where to reach the users service: <""|internal|x.y.z.y:1234>
CDRSAliaseSConns []*HaPoolConfig // address where to reach the aliases service: <""|internal|x.y.z.y:1234>
CDRSStatSConns []*HaPoolConfig // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234>
CDRSOnlineCDRExports []string // list of CDRE templates to use for real-time CDR exports
CDRStatsEnabled bool // Enable CDR Stats service
CDRStatsSaveInterval time.Duration // Save interval duration
CdreProfiles map[string]*CdreConfig
CdrcProfiles map[string][]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath][]{Configs}
SmGenericConfig *SmGenericConfig
@@ -336,10 +336,9 @@ func (self *CGRConfig) checkConfigSanity() error {
return errors.New("CDRStatS not enabled but requested by CDRS component.")
}
}
for _, rplCfg := range self.CDRSCdrReplication {
if utils.IsSliceMember([]string{utils.MetaHTTPjsonMap, utils.META_HTTP_POST}, rplCfg.Transport) &&
len(rplCfg.ContentFields) == 0 {
return fmt.Errorf("<CDRS> No content fields defined for replication to address: <%s>", rplCfg.Address)
for _, cdrePrfl := range self.CDRSOnlineCDRExports {
if _, hasIt := self.CdreProfiles[cdrePrfl]; !hasIt {
return fmt.Errorf("<CDRS> Cannot find CDR export template with ID: <%s>", cdrePrfl)
}
}
}
@@ -922,33 +921,9 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
self.CDRSStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Cdr_replication != nil {
self.CDRSCdrReplication = make([]*CDRReplicationCfg, len(*jsnCdrsCfg.Cdr_replication))
for idx, rplJsonCfg := range *jsnCdrsCfg.Cdr_replication {
self.CDRSCdrReplication[idx] = new(CDRReplicationCfg)
if rplJsonCfg.Transport != nil {
self.CDRSCdrReplication[idx].Transport = *rplJsonCfg.Transport
}
if rplJsonCfg.Address != nil {
self.CDRSCdrReplication[idx].Address = *rplJsonCfg.Address
}
if rplJsonCfg.Synchronous != nil {
self.CDRSCdrReplication[idx].Synchronous = *rplJsonCfg.Synchronous
}
self.CDRSCdrReplication[idx].Attempts = 1
if rplJsonCfg.Attempts != nil {
self.CDRSCdrReplication[idx].Attempts = *rplJsonCfg.Attempts
}
if rplJsonCfg.Cdr_filter != nil {
if self.CDRSCdrReplication[idx].CdrFilter, err = utils.ParseRSRFields(*rplJsonCfg.Cdr_filter, utils.INFIELD_SEP); err != nil {
return err
}
}
if rplJsonCfg.Content_fields != nil {
if self.CDRSCdrReplication[idx].ContentFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*rplJsonCfg.Content_fields); err != nil {
return err
}
}
if jsnCdrsCfg.Online_cdr_exports != nil {
for _, expProfile := range *jsnCdrsCfg.Online_cdr_exports {
self.CDRSOnlineCDRExports = append(self.CDRSOnlineCDRExports, expProfile)
}
}
}

View File

@@ -153,31 +153,42 @@ const CGRATES_CFG_JSON = `
"users_conns": [], // address where to reach the user service, empty to disable user profile functionality: <""|*internal|x.y.z.y:1234>
"aliases_conns": [], // address where to reach the aliases service, empty to disable aliases functionality: <""|*internal|x.y.z.y:1234>
"cdrstats_conns": [], // address where to reach the cdrstats service, empty to disable stats functionality<""|*internal|x.y.z.y:1234>
"cdr_replication":[
// { // sample replication, not configured by default
// "transport": "*amqp_json_map", // mechanism to use when replicating
// "address": "http://127.0.0.1:12080/cdr_json_map", // address where to replicate
// "attempts": 1, // number of attempts for POST before failing on file
// "cdr_filter": "", // filter the CDRs being replicated
// "content_fields": [ // template of the replicated content fields
// {"tag": "CGRID", "type": "*composed", "value": "CGRID", "field_id": "CGRID"},
// {"tag":"RunID", "type": "*composed", "value": "RunID", "field_id": "RunID"},
// {"tag":"TOR", "type": "*composed", "value": "ToR", "field_id": "ToR"},
// {"tag":"OriginID", "type": "*composed", "value": "OriginID", "field_id": "OriginID"},
// {"tag":"RequestType", "type": "*composed", "value": "RequestType", "field_id": "RequestType"},
// {"tag":"Direction", "type": "*composed", "value": "Direction", "field_id": "Direction"},
// {"tag":"Tenant", "type": "*composed", "value": "Tenant", "field_id": "Tenant"},
// {"tag":"Category", "type": "*composed", "value": "Category", "field_id": "Category"},
// {"tag":"Account", "type": "*composed", "value": "Account", "field_id": "Account"},
// {"tag":"Subject", "type": "*composed", "value": "Subject", "field_id": "Subject"},
// {"tag":"Destination", "type": "*composed", "value": "Destination", "field_id": "Destination"},
// {"tag":"SetupTime", "type": "*composed", "value": "SetupTime", "layout": "2006-01-02T15:04:05Z07:00", "field_id": "SetupTime"},
// {"tag":"AnswerTime", "type": "*composed", "value": "AnswerTime", "layout": "2006-01-02T15:04:05Z07:00", "field_id": "AnswerTime"},
// {"tag":"Usage", "type": "*composed", "value": "Usage", "field_id": "Usage"},
// {"tag":"Cost", "type": "*composed", "value": "Cost", "field_id": "Cost"},
// ],
// },
]
"online_cdr_exports":[], // list of CDRE profiles to use for real-time CDR exports
},
"cdre": {
"*default": {
"export_format": "*file_csv", // exported CDRs format <*file_csv|*file_fwv|*http_post|*http_json_cdr|*http_json_map|*amqp_json_cdr|*amqp_json_map>
"export_path": "/var/spool/cgrates/cdre", // path where the exported CDRs will be placed
"cdr_filter": "", // filter CDRs exported by this template
"synchronous": false, // block processing until export has a result
"attempts": 1, // Number of attempts if not success
"field_separator": ",", // used field separator in some export formats, eg: *file_csv
"usage_multiply_factor": {
"*any": 1 // multiply usage based on ToR field or *any for all
},
"cost_multiply_factor": 1, // multiply cost before export, eg: add VAT
"header_fields": [], // template of the exported header fields
"content_fields": [ // template of the exported content fields
{"tag": "CGRID", "type": "*composed", "value": "CGRID"},
{"tag":"RunID", "type": "*composed", "value": "RunID"},
{"tag":"TOR", "type": "*composed", "value": "ToR"},
{"tag":"OriginID", "type": "*composed", "value": "OriginID"},
{"tag":"RequestType", "type": "*composed", "value": "RequestType"},
{"tag":"Direction", "type": "*composed", "value": "Direction"},
{"tag":"Tenant", "type": "*composed", "value": "Tenant"},
{"tag":"Category", "type": "*composed", "value": "Category"},
{"tag":"Account", "type": "*composed", "value": "Account"},
{"tag":"Subject", "type": "*composed", "value": "Subject"},
{"tag":"Destination", "type": "*composed", "value": "Destination"},
{"tag":"SetupTime", "type": "*composed", "value": "SetupTime", "layout": "2006-01-02T15:04:05Z07:00"},
{"tag":"AnswerTime", "type": "*composed", "value": "AnswerTime", "layout": "2006-01-02T15:04:05Z07:00"},
{"tag":"Usage", "type": "*composed", "value": "Usage"},
{"tag":"Cost", "type": "*composed", "value": "Cost", "rounding_decimals": 4},
],
"trailer_fields": [], // template of the exported trailer fields
},
},
@@ -247,39 +258,6 @@ const CGRATES_CFG_JSON = `
],
"cdre": {
"*default": {
"cdr_format": "csv", // exported CDRs format <csv>
"field_separator": ",",
"data_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from KBytes to Bytes)
"sms_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from SMS unit to call duration in some billing systems)
"mms_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from MMS unit to call duration in some billing systems)
"generic_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from GENERIC unit to call duration in some billing systems)
"cost_multiply_factor": 1, // multiply cost before export, eg: add VAT
"export_directory": "/var/spool/cgrates/cdre", // path where the exported CDRs will be placed
"header_fields": [], // template of the exported header fields
"content_fields": [ // template of the exported content fields
{"tag": "CGRID", "type": "*composed", "value": "CGRID"},
{"tag":"RunID", "type": "*composed", "value": "RunID"},
{"tag":"TOR", "type": "*composed", "value": "ToR"},
{"tag":"OriginID", "type": "*composed", "value": "OriginID"},
{"tag":"RequestType", "type": "*composed", "value": "RequestType"},
{"tag":"Direction", "type": "*composed", "value": "Direction"},
{"tag":"Tenant", "type": "*composed", "value": "Tenant"},
{"tag":"Category", "type": "*composed", "value": "Category"},
{"tag":"Account", "type": "*composed", "value": "Account"},
{"tag":"Subject", "type": "*composed", "value": "Subject"},
{"tag":"Destination", "type": "*composed", "value": "Destination"},
{"tag":"SetupTime", "type": "*composed", "value": "SetupTime", "layout": "2006-01-02T15:04:05Z07:00"},
{"tag":"AnswerTime", "type": "*composed", "value": "AnswerTime", "layout": "2006-01-02T15:04:05Z07:00"},
{"tag":"Usage", "type": "*composed", "value": "Usage"},
{"tag":"Cost", "type": "*composed", "value": "Cost", "rounding_decimals": 4},
],
"trailer_fields": [], // template of the exported trailer fields
},
},
"sm_generic": {
"enabled": false, // starts SessionManager service: <true|false>
"listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests

View File

@@ -203,11 +203,11 @@ func TestDfCdrsJsonCfg(t *testing.T) {
&HaPoolJsonCfg{
Address: utils.StringPointer("*internal"),
}},
Pubsubs_conns: &[]*HaPoolJsonCfg{},
Users_conns: &[]*HaPoolJsonCfg{},
Aliases_conns: &[]*HaPoolJsonCfg{},
Cdrstats_conns: &[]*HaPoolJsonCfg{},
Cdr_replication: &[]*CdrReplicationJsonCfg{},
Pubsubs_conns: &[]*HaPoolJsonCfg{},
Users_conns: &[]*HaPoolJsonCfg{},
Aliases_conns: &[]*HaPoolJsonCfg{},
Cdrstats_conns: &[]*HaPoolJsonCfg{},
Online_cdr_exports: &[]string{},
}
if cfg, err := dfCgrJsonCfg.CdrsJsonCfg(); err != nil {
t.Error(err)
@@ -282,17 +282,16 @@ func TestDfCdreJsonCfgs(t *testing.T) {
}
eCfg := map[string]*CdreJsonCfg{
utils.META_DEFAULT: &CdreJsonCfg{
Cdr_format: utils.StringPointer("csv"),
Field_separator: utils.StringPointer(","),
Data_usage_multiply_factor: utils.Float64Pointer(1.0),
Sms_usage_multiply_factor: utils.Float64Pointer(1.0),
Mms_usage_multiply_factor: utils.Float64Pointer(1.0),
Generic_usage_multiply_factor: utils.Float64Pointer(1.0),
Cost_multiply_factor: utils.Float64Pointer(1.0),
Export_directory: utils.StringPointer("/var/spool/cgrates/cdre"),
Header_fields: &eFields,
Content_fields: &eContentFlds,
Trailer_fields: &eFields,
Export_format: utils.StringPointer(utils.MetaFileCSV),
Export_path: utils.StringPointer("/var/spool/cgrates/cdre"),
Synchronous: utils.BoolPointer(false),
Attempts: utils.IntPointer(1),
Field_separator: utils.StringPointer(","),
Usage_multiply_factor: &map[string]float64{utils.ANY: 1.0},
Cost_multiply_factor: utils.Float64Pointer(1.0),
Header_fields: &eFields,
Content_fields: &eContentFlds,
Trailer_fields: &eFields,
},
}
if cfg, err := dfCgrJsonCfg.CdreJsonCfgs(); err != nil {

View File

@@ -330,10 +330,7 @@ func TestCgrCfgJSONDefaultsScheduler(t *testing.T) {
func TestCgrCfgJSONDefaultsCDRS(t *testing.T) {
eHaPoolCfg := []*HaPoolConfig{}
eCDRReCfg := []*CDRReplicationCfg{}
iHaPoolCfg := []*HaPoolConfig{&HaPoolConfig{Address: "*internal"}}
var eCdrExtr []*utils.RSRField
if cgrCfg.CDRSEnabled != false {
t.Error(cgrCfg.CDRSEnabled)
}
@@ -349,7 +346,7 @@ func TestCgrCfgJSONDefaultsCDRS(t *testing.T) {
if cgrCfg.CDRSSMCostRetries != 5 {
t.Error(cgrCfg.CDRSSMCostRetries)
}
if !reflect.DeepEqual(cgrCfg.CDRSRaterConns, iHaPoolCfg) {
if !reflect.DeepEqual(cgrCfg.CDRSRaterConns, []*HaPoolConfig{&HaPoolConfig{Address: "*internal"}}) {
t.Error(cgrCfg.CDRSRaterConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSPubSubSConns, eHaPoolCfg) {
@@ -364,8 +361,8 @@ func TestCgrCfgJSONDefaultsCDRS(t *testing.T) {
if !reflect.DeepEqual(cgrCfg.CDRSStatSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSStatSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSCdrReplication, eCDRReCfg) {
t.Error(cgrCfg.CDRSCdrReplication)
if cgrCfg.CDRSOnlineCDRExports != nil {
t.Error(cgrCfg.CDRSOnlineCDRExports)
}
}
@@ -399,20 +396,18 @@ func TestCgrCfgJSONDefaultsCdreProfiles(t *testing.T) {
}
eCdreCfg := map[string]*CdreConfig{
"*default": {
CdrFormat: "csv",
FieldSeparator: ',',
DataUsageMultiplyFactor: 1,
SMSUsageMultiplyFactor: 1,
MMSUsageMultiplyFactor: 1,
GenericUsageMultiplyFactor: 1,
CostMultiplyFactor: 1,
ExportDirectory: "/var/spool/cgrates/cdre",
HeaderFields: eFields,
ContentFields: eContentFlds,
TrailerFields: eFields,
ExportFormat: utils.MetaFileCSV,
ExportPath: "/var/spool/cgrates/cdre",
Synchronous: false,
Attempts: 1,
FieldSeparator: ',',
UsageMultiplyFactor: map[string]float64{utils.ANY: 1.0},
CostMultiplyFactor: 1.0,
HeaderFields: eFields,
ContentFields: eContentFlds,
TrailerFields: eFields,
},
}
if !reflect.DeepEqual(cgrCfg.CdreProfiles, eCdreCfg) {
t.Errorf("received: %+v, expecting: %+v", cgrCfg.CdreProfiles, eCdreCfg)
}

View File

@@ -104,7 +104,7 @@ type CdrsJsonCfg struct {
Users_conns *[]*HaPoolJsonCfg
Aliases_conns *[]*HaPoolJsonCfg
Cdrstats_conns *[]*HaPoolJsonCfg
Cdr_replication *[]*CdrReplicationJsonCfg
Online_cdr_exports *[]string
}
type CdrReplicationJsonCfg struct {
@@ -145,17 +145,16 @@ type CdrFieldJsonCfg struct {
// Cdre config section
type CdreJsonCfg struct {
Cdr_format *string
Field_separator *string
Data_usage_multiply_factor *float64
Sms_usage_multiply_factor *float64
Mms_usage_multiply_factor *float64
Generic_usage_multiply_factor *float64
Cost_multiply_factor *float64
Export_directory *string
Header_fields *[]*CdrFieldJsonCfg
Content_fields *[]*CdrFieldJsonCfg
Trailer_fields *[]*CdrFieldJsonCfg
Export_format *string
Export_path *string
Synchronous *bool
Attempts *int
Field_separator *string
Usage_multiply_factor *map[string]float64
Cost_multiply_factor *float64
Header_fields *[]*CdrFieldJsonCfg
Content_fields *[]*CdrFieldJsonCfg
Trailer_fields *[]*CdrFieldJsonCfg
}
// Cdrc config section

View File

@@ -205,3 +205,15 @@ func MergeMapsStringIface(mps ...map[string]interface{}) (outMp map[string]inter
}
return
}
// FieldMultiplyFactor defines multiply factors for different field values
// original defined for CDRE component
type FieldMultiplyFactor map[string]float64
func (fmp FieldMultiplyFactor) Clone() (cln FieldMultiplyFactor) {
cln = make(FieldMultiplyFactor, len(fmp))
for k, v := range fmp {
cln[k] = v
}
return
}