Mediator refactoring to support CDR as imput instead of csv row - adding separation of names and indexes, StartTime->AnswerTime, adding reqtype=rated

This commit is contained in:
DanB
2013-06-06 12:37:36 +02:00
parent fbbb26fab3
commit a75c2e7324
27 changed files with 523 additions and 461 deletions

View File

@@ -22,6 +22,7 @@ import (
"code.google.com/p/goconf/conf"
"errors"
"fmt"
"github.com/cgrates/cgrates/utils"
)
const (
@@ -67,7 +68,8 @@ type CGRConfig struct {
SchedulerEnabled bool
CDRSListen string // CDRS's listening interface: <x.y.z.y:1234>.
CDRSfsJSONEnabled bool // Enable the handler for FreeSWITCH JSON CDRs: <enabled|disabled>.
CDRSMediator string // Address where to reach the Mediator. Empty for disabling mediation. <""|internal>
CDRSMediator string // Address where to reach the Mediator. Empty for disabling mediation. <""|internal>
CDRSExtraFields []string //Extra fields to store in CDRs
SMEnabled bool
SMSwitchType string
SMRater string // address where to access rater. Can be internal, direct rater address or the address of a balancer
@@ -79,15 +81,15 @@ type CGRConfig struct {
MediatorRaterReconnects int // Number of reconnects to rater before giving up.
MediatorCDRType string // CDR type <freeswitch_http_json|freeswitch_file_csv>.
MediatorAccIdField string // Name of field identifying accounting id used during mediation. Use index number in case of .csv cdrs.
MediatorSubjectFields string // Name of subject fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorReqTypeFields string // Name of request type fields to be used during mediation. Use index number in case of .csv cdrs.
MediatorDirectionFields string // Name of direction fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorTenantFields string // Name of tenant fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorTORFields string // Name of tor fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorAccountFields string // Name of account fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorDestFields string // Name of destination fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorTimeStartFields string // Name of time_start fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorDurationFields string // Name of duration fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorSubjectFields []string // Name of subject fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorReqTypeFields []string // Name of request type fields to be used during mediation. Use index number in case of .csv cdrs.
MediatorDirectionFields []string // Name of direction fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorTenantFields []string // Name of tenant fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorTORFields []string // Name of tor fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorAccountFields []string // Name of account fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorDestFields []string // Name of destination fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorTimeAnswerFields []string // Name of time_start fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorDurationFields []string // Name of duration fields to be used during mediation. Use index numbers in case of .csv cdrs.
MediatorCDRInDir string // Absolute path towards the directory where the CDRs are kept (file stored CDRs).
MediatorCDROutDir string // Absolute path towards the directory where processed CDRs will be exported (file stored CDRs).
FreeswitchServer string // freeswitch address host:port
@@ -122,21 +124,22 @@ func ( self *CGRConfig ) setDefaults() error {
self.CDRSListen = "127.0.0.1:2022"
self.CDRSfsJSONEnabled = false
self.CDRSMediator = INTERNAL
self.CDRSExtraFields = []string{}
self.MediatorEnabled = false
self.MediatorListen = "127.0.0.1:2032"
self.MediatorRater = "127.0.0.1:2012"
self.MediatorRaterReconnects = 3
self.MediatorCDRType = "freeswitch_http_json"
self.MediatorCDRType = utils.FSCDR_HTTP_JSON
self.MediatorAccIdField = "accid"
self.MediatorSubjectFields = "subject"
self.MediatorReqTypeFields = "reqtype"
self.MediatorDirectionFields = "direction"
self.MediatorTenantFields = "tenant"
self.MediatorTORFields = "tor"
self.MediatorAccountFields = "account"
self.MediatorDestFields = "destination"
self.MediatorTimeStartFields = "time_start"
self.MediatorDurationFields = "duration"
self.MediatorSubjectFields = []string{"subject"}
self.MediatorReqTypeFields = []string{"reqtype"}
self.MediatorDirectionFields = []string{"direction"}
self.MediatorTenantFields = []string{"tenant"}
self.MediatorTORFields = []string{"tor"}
self.MediatorAccountFields = []string{"account"}
self.MediatorDestFields = []string{"destination"}
self.MediatorTimeAnswerFields = []string{"time_answer"}
self.MediatorDurationFields = []string{"duration"}
self.MediatorCDRInDir = "/var/log/freeswitch/cdr-csv"
self.MediatorCDROutDir = "/var/log/cgrates/cdr/out/freeswitch/csv"
self.SMEnabled = false
@@ -173,6 +176,7 @@ func loadConfig(c *conf.ConfigFile) (*CGRConfig, error) {
cfg := &CGRConfig{}
cfg.setDefaults()
var hasOpt bool
var errParse error
if hasOpt = c.HasOption("global", "datadb_type"); hasOpt {
cfg.DataDBType, _ = c.GetString("global", "datadb_type")
}
@@ -251,6 +255,11 @@ func loadConfig(c *conf.ConfigFile) (*CGRConfig, error) {
if hasOpt = c.HasOption("cdrs", "mediator"); hasOpt {
cfg.CDRSMediator, _ = c.GetString("cdrs", "mediator")
}
if hasOpt = c.HasOption("cdrs", "extra_fields"); hasOpt {
if cfg.CDRSExtraFields, errParse = ConfigSlice( c, "cdrs", "extra_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "enabled"); hasOpt {
cfg.MediatorEnabled, _ = c.GetBool("mediator", "enabled")
}
@@ -270,31 +279,49 @@ func loadConfig(c *conf.ConfigFile) (*CGRConfig, error) {
cfg.MediatorAccIdField, _ = c.GetString("mediator", "accid_field")
}
if hasOpt = c.HasOption("mediator", "subject_fields"); hasOpt {
cfg.MediatorSubjectFields, _ = c.GetString("mediator", "subject_fields")
if cfg.MediatorSubjectFields, errParse = ConfigSlice( c, "mediator", "subject_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "reqtype_fields"); hasOpt {
cfg.MediatorReqTypeFields, _ = c.GetString("mediator", "reqtype_fields")
if cfg.MediatorReqTypeFields, errParse = ConfigSlice( c, "mediator", "reqtype_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "direction_fields"); hasOpt {
cfg.MediatorDirectionFields, _ = c.GetString("mediator", "direction_fields")
if cfg.MediatorDirectionFields, errParse = ConfigSlice( c, "mediator", "direction_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "tenant_fields"); hasOpt {
cfg.MediatorTenantFields, _ = c.GetString("mediator", "tenant_fields")
if cfg.MediatorTenantFields, errParse = ConfigSlice( c, "mediator", "tenant_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "tor_fields"); hasOpt {
cfg.MediatorTORFields, _ = c.GetString("mediator", "tor_fields")
if cfg.MediatorTORFields, errParse = ConfigSlice( c, "mediator", "tor_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "account_fields"); hasOpt {
cfg.MediatorAccountFields, _ = c.GetString("mediator", "account_fields")
if cfg.MediatorAccountFields, errParse = ConfigSlice( c, "mediator", "account_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "destination_fields"); hasOpt {
cfg.MediatorDestFields, _ = c.GetString("mediator", "destination_fields")
if cfg.MediatorDestFields, errParse = ConfigSlice( c, "mediator", "destination_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "time_start_fields"); hasOpt {
cfg.MediatorTimeStartFields, _ = c.GetString("mediator", "time_start_fields")
if hasOpt = c.HasOption("mediator", "time_answer_fields"); hasOpt {
if cfg.MediatorTimeAnswerFields, errParse = ConfigSlice( c, "mediator", "time_answer_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "duration_fields"); hasOpt {
cfg.MediatorDurationFields, _ = c.GetString("mediator", "duration_fields")
if cfg.MediatorDurationFields, errParse = ConfigSlice( c, "mediator", "duration_fields"); errParse!=nil {
return nil, errParse
}
}
if hasOpt = c.HasOption("mediator", "cdr_in_dir"); hasOpt {
cfg.MediatorCDRInDir, _ = c.GetString("mediator", "cdr_in_dir")

View File

@@ -58,22 +58,23 @@ func TestDefaults(t *testing.T) {
eCfg.SchedulerEnabled = false
eCfg.CDRSListen = "127.0.0.1:2022"
eCfg.CDRSfsJSONEnabled = false
eCfg.CDRSMediator = INTERNAL
eCfg.CDRSMediator = INTERNAL
eCfg.CDRSExtraFields = []string{}
eCfg.MediatorEnabled = false
eCfg.MediatorListen = "127.0.0.1:2032"
eCfg.MediatorRater = "127.0.0.1:2012"
eCfg.MediatorRaterReconnects = 3
eCfg.MediatorCDRType = "freeswitch_http_json"
eCfg.MediatorAccIdField = "accid"
eCfg.MediatorSubjectFields = "subject"
eCfg.MediatorReqTypeFields = "reqtype"
eCfg.MediatorDirectionFields = "direction"
eCfg.MediatorTenantFields = "tenant"
eCfg.MediatorTORFields = "tor"
eCfg.MediatorAccountFields = "account"
eCfg.MediatorDestFields = "destination"
eCfg.MediatorTimeStartFields = "time_start"
eCfg.MediatorDurationFields = "duration"
eCfg.MediatorSubjectFields = []string{"subject"}
eCfg.MediatorReqTypeFields = []string{"reqtype"}
eCfg.MediatorDirectionFields = []string{"direction"}
eCfg.MediatorTenantFields = []string{"tenant"}
eCfg.MediatorTORFields = []string{"tor"}
eCfg.MediatorAccountFields = []string{"account"}
eCfg.MediatorDestFields = []string{"destination"}
eCfg.MediatorTimeAnswerFields = []string{"time_answer"}
eCfg.MediatorDurationFields = []string{"duration"}
eCfg.MediatorCDRInDir = "/var/log/freeswitch/cdr-csv"
eCfg.MediatorCDROutDir = "/var/log/cgrates/cdr/out/freeswitch/csv"
eCfg.SMEnabled = false
@@ -146,21 +147,22 @@ func TestConfigFromFile(t *testing.T) {
eCfg.CDRSListen = "test"
eCfg.CDRSfsJSONEnabled = true
eCfg.CDRSMediator = "test"
eCfg.CDRSExtraFields = []string{"test"}
eCfg.MediatorEnabled = true
eCfg.MediatorListen = "test"
eCfg.MediatorRater = "test"
eCfg.MediatorRaterReconnects = 99
eCfg.MediatorCDRType = "test"
eCfg.MediatorAccIdField = "test"
eCfg.MediatorSubjectFields = "test"
eCfg.MediatorReqTypeFields = "test"
eCfg.MediatorDirectionFields = "test"
eCfg.MediatorTenantFields = "test"
eCfg.MediatorTORFields = "test"
eCfg.MediatorAccountFields = "test"
eCfg.MediatorDestFields = "test"
eCfg.MediatorTimeStartFields = "test"
eCfg.MediatorDurationFields = "test"
eCfg.MediatorSubjectFields = []string{"test"}
eCfg.MediatorReqTypeFields = []string{"test"}
eCfg.MediatorDirectionFields = []string{"test"}
eCfg.MediatorTenantFields = []string{"test"}
eCfg.MediatorTORFields = []string{"test"}
eCfg.MediatorAccountFields = []string{"test"}
eCfg.MediatorDestFields = []string{"test"}
eCfg.MediatorTimeAnswerFields = []string{"test"}
eCfg.MediatorDurationFields = []string{"test"}
eCfg.MediatorCDRInDir = "test"
eCfg.MediatorCDROutDir = "test"
eCfg.SMEnabled = true

45
config/helpers.go Normal file
View File

@@ -0,0 +1,45 @@
/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2013 ITsysCOM
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 (
"code.google.com/p/goconf/conf"
"errors"
"strings"
)
// Adds support for slice values in config
func ConfigSlice( c *conf.ConfigFile, section, valName string ) ([]string, error) {
sliceStr, errGet := c.GetString(section, valName)
if errGet != nil {
return nil, errGet
}
cfgValStrs := strings.Split(sliceStr, ",") // If need arrises, we can make the separator configurable
if len(cfgValStrs)==1 && cfgValStrs[0]=="" { // Prevents returning iterable with empty value
return []string{}, nil
}
for _,elm := range cfgValStrs {
if elm == "" { //One empty element is presented when splitting empty string
return nil, errors.New("Empty values in config slice")
}
}
return cfgValStrs, nil
}

View File

@@ -1,71 +1,72 @@
# Test Data.
# NOT A REAL CONFIGURATION FILE
# TEST DATA - NOT FOR PRODUCTION USAGE
#
[global]
datadb_type = test # The main database: <redis>.
datadb_host = test # Database host address.
datadb_host = test # Database host address.
datadb_port = test # Port to reach the database.
datadb_name = test # The name of the database to connect to.
datadb_user = test # Username to use when connecting to database.
datadb_passwd = test # Password to use when connecting to database.
logdb_type = test # Log/stored database type to use: <same|postgres|mongo|redis>
logdb_host = test # The host to connect to. Values that start with / are for UNIX domain sockets.
datadb_passwd = test # Password to use when connecting to database.
logdb_type = test # Log/stored database type to use: <same|postgres|mongo|redis>
logdb_host = test # The host to connect to. Values that start with / are for UNIX domain sockets.
logdb_port = test # The port to reach the logdb.
logdb_name = test # The name of the log database to connect to.
logdb_user = test # Username to use when connecting to logdb.
logdb_user = test # Username to use when connecting to logdb.
logdb_passwd = test # Password to use when connecting to logdb.
rpc_encoding = test # RPC encoding used on APIs: <gob|json>.
default_reqtype = test # Default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated>.
default_reqtype = test # Default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated>.
default_tor = test # Default Type of Record to consider when missing from requests.
default_tenant = test # Default Tenant to consider when missing from requests.
default_subject = test # Default rating Subject to consider when missing from requests.
[balancer]
enabled = true # Start Balancer service: <true|false>.
listen = test # Balancer listen interface: <disabled|x.y.z.y:1234>.
enabled = true # Start Balancer service: <true|false>.
listen = test # Balancer listen interface: <disabled|x.y.z.y:1234>.
[rater]
enabled = true # Enable Rater service: <true|false>.
enabled = true # Enable Rater service: <true|false>.
balancer = test # Register to Balancer as worker: <enabled|disabled>.
listen = test # Rater's listening interface: <internal|x.y.z.y:1234>.
listen = test # Rater's listening interface: <internal|x.y.z.y:1234>.
[scheduler]
enabled = true # Starts Scheduler service: <true|false>.
enabled = true # Starts Scheduler service: <true|false>.
[cdrs]
listen = test # CDRS's listening interface: <x.y.z.y:1234>.
freeswitch_json_enabled = true # Enable the handler for FreeSWITCH JSON CDRs: <true|false>.
mediator = test # Address where to reach the Mediator. Empty for disabling mediation. <""|internal>
listen=test # CDRS's listening interface: <x.y.z.y:1234>.
freeswitch_json_enabled=true # Enable the handler for FreeSWITCH JSON CDRs: <true|false>.
mediator = test # Address where to reach the Mediator. Empty for disabling mediation. <""|internal>
extra_fields = test # Extra fields to store in CDRs
[mediator]
enabled = true # Starts Mediator service: <true|false>.
listen = test # Mediator's listening interface: <internal>.
rater = test # Address where to reach the Rater: <internal|x.y.z.y:1234>
enabled = true # Starts Mediator service: <true|false>.
listen=test # Mediator's listening interface: <internal>.
rater = test # Address where to reach the Rater: <internal|x.y.z.y:1234>
rater_reconnects = 99 # Number of reconnects to rater before giving up.
cdr_type = test # CDR type <freeswitch_http_json|freeswitch_file_csv>.
cdr_type = test # CDR type <freeswitch_http_json|freeswitch_file_csv>.
accid_field = test # Name of field identifying accounting id used during mediation. Use index number in case of .csv cdrs.
subject_fields = test # Name of subject fields to be used during mediation. Use index numbers in case of .csv cdrs.
subject_fields = test # Name of subject fields to be used during mediation. Use index numbers in case of .csv cdrs.
reqtype_fields = test # Name of request type fields to be used during mediation. Use index number in case of .csv cdrs.
direction_fields = test # Name of direction fields to be used during mediation. Use index numbers in case of .csv cdrs.
tenant_fields = test # Name of tenant fields to be used during mediation. Use index numbers in case of .csv cdrs.
direction_fields = test # Name of direction fields to be used during mediation. Use index numbers in case of .csv cdrs.
tenant_fields = test # Name of tenant fields to be used during mediation. Use index numbers in case of .csv cdrs.
tor_fields = test # Name of tor fields to be used during mediation. Use index numbers in case of .csv cdrs.
account_fields = test # Name of account fields to be used during mediation. Use index numbers in case of .csv cdrs.
destination_fields = test # Name of destination fields to be used during mediation. Use index numbers in case of .csv cdrs.
time_start_fields = test # Name of time_start fields to be used during mediation. Use index numbers in case of .csv cdrs.
duration_fields = test # Name of duration fields to be used during mediation. Use index numbers in case of .csv cdrs.
cdr_in_dir = test # Absolute path towards the directory where the CDRs are kept (file stored CDRs).
cdr_out_dir = test # Absolute path towards the directory where processed CDRs will be exported (file stored CDRs).
account_fields = test # Name of account fields to be used during mediation. Use index numbers in case of .csv cdrs.
destination_fields = test # Name of destination fields to be used during mediation. Use index numbers in case of .csv cdrs.
time_answer_fields = test # Name of time_answer fields to be used during mediation. Use index numbers in case of .csv cdrs.
duration_fields = test # Name of duration fields to be used during mediation. Use index numbers in case of .csv cdrs.
cdr_in_dir = test # Absolute path towards the directory where the CDRs are kept (file stored CDRs).
cdr_out_dir = test # Absolute path towards the directory where processed CDRs will be exported (file stored CDRs).
[session_manager]
enabled = true # Starts SessionManager service: <true|false>.
switch_type = test # Defines the type of switch behind: <freeswitch>.
rater = test # Address where to reach the Rater.
enabled = true # Starts SessionManager service: <true|false>.
switch_type = test # Defines the type of switch behind: <freeswitch>.
rater = test # Address where to reach the Rater.
rater_reconnects = 99 # Number of reconnects to rater before giving up.
debit_interval = 99 # Interval to perform debits on.
[freeswitch]
server = test # Adress where to connect to FreeSWITCH socket.
passwd = test # FreeSWITCH socket password.
reconnects = 99 # Number of attempts on connect failure.
server = test # Adress where to connect to FreeSWITCH socket.
passwd = test # FreeSWITCH socket password.
reconnects = 99 # Number of attempts on connect failure.