mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Implemented service,config and api for Sars
This commit is contained in:
committed by
Dan Christian Bogos
parent
ed9ac8965f
commit
86df598920
36
apier/v1/sars.go
Normal file
36
apier/v1/sars.go
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func NewSArSv1() *SaRSv1 {
|
||||
return &SaRSv1{}
|
||||
}
|
||||
|
||||
type SaRSv1 struct {
|
||||
}
|
||||
|
||||
func (sa *SaRSv1) Ping(ctx *context.Context, ign *utils.CGREvent, reply *string) error {
|
||||
*reply = utils.Pong
|
||||
return nil
|
||||
}
|
||||
@@ -154,6 +154,7 @@ func newCGRConfig(config []byte) (cfg *CGRConfig, err error) {
|
||||
cfg.chargerSCfg = new(ChargerSCfg)
|
||||
cfg.resourceSCfg = &ResourceSConfig{Opts: &ResourcesOpts{}}
|
||||
cfg.statsCfg = &StatSCfg{Opts: &StatsOpts{}}
|
||||
cfg.sarsCfg = new(SarSCfg)
|
||||
cfg.thresholdSCfg = &ThresholdSCfg{Opts: &ThresholdsOpts{}}
|
||||
cfg.routeSCfg = &RouteSCfg{Opts: &RoutesOpts{}}
|
||||
cfg.sureTaxCfg = new(SureTaxCfg)
|
||||
@@ -313,6 +314,7 @@ type CGRConfig struct {
|
||||
chargerSCfg *ChargerSCfg // ChargerS config
|
||||
resourceSCfg *ResourceSConfig // ResourceS config
|
||||
statsCfg *StatSCfg // StatS config
|
||||
sarsCfg *SarSCfg //SarS config
|
||||
thresholdSCfg *ThresholdSCfg // ThresholdS config
|
||||
routeSCfg *RouteSCfg // RouteS config
|
||||
sureTaxCfg *SureTaxCfg // SureTax config
|
||||
@@ -363,7 +365,7 @@ func (cfg *CGRConfig) loadFromJSONCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
cfg.loadFreeswitchAgentCfg, cfg.loadKamAgentCfg,
|
||||
cfg.loadAsteriskAgentCfg, cfg.loadDiameterAgentCfg, cfg.loadRadiusAgentCfg,
|
||||
cfg.loadDNSAgentCfg, cfg.loadHTTPAgentCfg, cfg.loadAttributeSCfg,
|
||||
cfg.loadChargerSCfg, cfg.loadResourceSCfg, cfg.loadStatSCfg,
|
||||
cfg.loadChargerSCfg, cfg.loadResourceSCfg, cfg.loadStatSCfg, cfg.loadSarSCfg,
|
||||
cfg.loadThresholdSCfg, cfg.loadRouteSCfg, cfg.loadLoaderSCfg,
|
||||
cfg.loadMailerCfg, cfg.loadSureTaxCfg, cfg.loadDispatcherSCfg,
|
||||
cfg.loadLoaderCgrCfg, cfg.loadMigratorCgrCfg, cfg.loadTLSCgrCfg,
|
||||
@@ -633,6 +635,15 @@ func (cfg *CGRConfig) loadStatSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
return cfg.statsCfg.loadFromJSONCfg(jsnStatSCfg)
|
||||
}
|
||||
|
||||
// loadSarSCfg loads the SarS section of the configuration
|
||||
func (cfg *CGRConfig) loadSarSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
var jsnSarSCfg *SarsJsonCfg
|
||||
if jsnSarSCfg, err = jsnCfg.SarsJsonCfg(); err != nil {
|
||||
return
|
||||
}
|
||||
return cfg.sarsCfg.loadFromJSONCfg(jsnSarSCfg)
|
||||
}
|
||||
|
||||
// loadThresholdSCfg loads the ThresholdS section of the configuration
|
||||
func (cfg *CGRConfig) loadThresholdSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
var jsnThresholdSCfg *ThresholdSJsonCfg
|
||||
@@ -887,6 +898,13 @@ func (cfg *CGRConfig) StatSCfg() *StatSCfg { // not done
|
||||
return cfg.statsCfg
|
||||
}
|
||||
|
||||
// SarSCfg returns the config for SarS
|
||||
func (cfg *CGRConfig) SarSCfg() *SarSCfg {
|
||||
cfg.lks[SARS_JSON].Lock()
|
||||
defer cfg.lks[SARS_JSON].Unlock()
|
||||
return cfg.sarsCfg
|
||||
}
|
||||
|
||||
// ThresholdSCfg returns the config for ThresholdS
|
||||
func (cfg *CGRConfig) ThresholdSCfg() *ThresholdSCfg {
|
||||
cfg.lks[THRESHOLDS_JSON].Lock()
|
||||
@@ -1236,6 +1254,7 @@ func (cfg *CGRConfig) getLoadFunctions() map[string]func(*CgrJsonCfg) error {
|
||||
ChargerSCfgJson: cfg.loadChargerSCfg,
|
||||
RESOURCES_JSON: cfg.loadResourceSCfg,
|
||||
STATS_JSON: cfg.loadStatSCfg,
|
||||
SARS_JSON: cfg.loadSarSCfg,
|
||||
THRESHOLDS_JSON: cfg.loadThresholdSCfg,
|
||||
RouteSJson: cfg.loadRouteSCfg,
|
||||
LoaderJson: cfg.loadLoaderSCfg,
|
||||
@@ -1486,6 +1505,8 @@ func (cfg *CGRConfig) reloadSections(sections ...string) {
|
||||
cfg.rldChans[RESOURCES_JSON] <- struct{}{}
|
||||
case STATS_JSON:
|
||||
cfg.rldChans[STATS_JSON] <- struct{}{}
|
||||
case SARS_JSON:
|
||||
cfg.rldChans[SARS_JSON] <- struct{}{}
|
||||
case THRESHOLDS_JSON:
|
||||
cfg.rldChans[THRESHOLDS_JSON] <- struct{}{}
|
||||
case RouteSJson:
|
||||
@@ -1538,6 +1559,7 @@ func (cfg *CGRConfig) AsMapInterface(separator string) (mp map[string]any) {
|
||||
ChargerSCfgJson: cfg.chargerSCfg.AsMapInterface(),
|
||||
RESOURCES_JSON: cfg.resourceSCfg.AsMapInterface(),
|
||||
STATS_JSON: cfg.statsCfg.AsMapInterface(),
|
||||
SARS_JSON: cfg.sarsCfg.AsMapInterface(),
|
||||
THRESHOLDS_JSON: cfg.thresholdSCfg.AsMapInterface(),
|
||||
RouteSJson: cfg.routeSCfg.AsMapInterface(),
|
||||
SURETAX_JSON: cfg.sureTaxCfg.AsMapInterface(separator),
|
||||
@@ -1676,6 +1698,8 @@ func (cfg *CGRConfig) V1GetConfig(ctx *context.Context, args *SectionWithAPIOpts
|
||||
mp = cfg.ResourceSCfg().AsMapInterface()
|
||||
case STATS_JSON:
|
||||
mp = cfg.StatSCfg().AsMapInterface()
|
||||
case SARS_JSON:
|
||||
mp = cfg.SarSCfg().AsMapInterface()
|
||||
case THRESHOLDS_JSON:
|
||||
mp = cfg.ThresholdSCfg().AsMapInterface()
|
||||
case RouteSJson:
|
||||
@@ -1844,6 +1868,8 @@ func (cfg *CGRConfig) V1GetConfigAsJSON(ctx *context.Context, args *SectionWithA
|
||||
mp = cfg.ResourceSCfg().AsMapInterface()
|
||||
case STATS_JSON:
|
||||
mp = cfg.StatSCfg().AsMapInterface()
|
||||
case SARS_JSON:
|
||||
mp = cfg.SarSCfg().AsMapInterface()
|
||||
case THRESHOLDS_JSON:
|
||||
mp = cfg.ThresholdSCfg().AsMapInterface()
|
||||
case RouteSJson:
|
||||
@@ -1967,6 +1993,7 @@ func (cfg *CGRConfig) Clone() (cln *CGRConfig) {
|
||||
chargerSCfg: cfg.chargerSCfg.Clone(),
|
||||
resourceSCfg: cfg.resourceSCfg.Clone(),
|
||||
statsCfg: cfg.statsCfg.Clone(),
|
||||
sarsCfg: cfg.sarsCfg.Clone(),
|
||||
thresholdSCfg: cfg.thresholdSCfg.Clone(),
|
||||
routeSCfg: cfg.routeSCfg.Clone(),
|
||||
sureTaxCfg: cfg.sureTaxCfg.Clone(),
|
||||
|
||||
@@ -822,6 +822,10 @@ const CGRATES_CFG_JSON = `
|
||||
},
|
||||
},
|
||||
|
||||
"sars":{ // SaRS config
|
||||
"enabled": false, // starts SaRS service: <true|false>.
|
||||
"stats_conns": [], // connections to StatS ,empty to disable stats functionality: <""|*internal|$rpc_conns_id>
|
||||
},
|
||||
|
||||
"thresholds": { // ThresholdS
|
||||
"enabled": false, // starts ThresholdS service: <true|false>.
|
||||
|
||||
@@ -44,6 +44,7 @@ const (
|
||||
RESOURCES_JSON = "resources"
|
||||
STATS_JSON = "stats"
|
||||
THRESHOLDS_JSON = "thresholds"
|
||||
SARS_JSON = "sars"
|
||||
RouteSJson = "routes"
|
||||
LoaderJson = "loaders"
|
||||
MAILER_JSN = "mailer"
|
||||
@@ -72,7 +73,7 @@ const (
|
||||
var (
|
||||
sortedCfgSections = []string{GENERAL_JSN, RPCConnsJsonName, DATADB_JSN, STORDB_JSN, LISTEN_JSN, TlsCfgJson, HTTP_JSN, SCHEDULER_JSN,
|
||||
CACHE_JSN, FilterSjsn, RALS_JSN, CDRS_JSN, ERsJson, SessionSJson, AsteriskAgentJSN, FreeSWITCHAgentJSN,
|
||||
KamailioAgentJSN, DA_JSN, RA_JSN, HttpAgentJson, DNSAgentJson, ATTRIBUTE_JSN, ChargerSCfgJson, RESOURCES_JSON, STATS_JSON,
|
||||
KamailioAgentJSN, DA_JSN, RA_JSN, HttpAgentJson, DNSAgentJson, ATTRIBUTE_JSN, ChargerSCfgJson, RESOURCES_JSON, STATS_JSON, SARS_JSON,
|
||||
THRESHOLDS_JSON, RouteSJson, LoaderJson, MAILER_JSN, SURETAX_JSON, CgrLoaderCfgJson, CgrMigratorCfgJson, DispatcherSJson, JanusAgentJson,
|
||||
AnalyzerCfgJson, ApierS, EEsJson, SIPAgentJson, RegistrarCJson, TemplatesJson, ConfigSJson, APIBanCfgJson, SentryPeerCfgJson, CoreSCfgJson}
|
||||
)
|
||||
@@ -369,6 +370,18 @@ func (jsnCfg CgrJsonCfg) StatSJsonCfg() (*StatServJsonCfg, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (jsnCfg CgrJsonCfg) SarsJsonCfg() (*SarsJsonCfg, error) {
|
||||
rawCfg, hasKey := jsnCfg[SARS_JSON]
|
||||
if !hasKey {
|
||||
return nil, nil
|
||||
}
|
||||
cfg := new(SarsJsonCfg)
|
||||
if err := json.Unmarshal(*rawCfg, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (jsnCfg CgrJsonCfg) ThresholdSJsonCfg() (*ThresholdSJsonCfg, error) {
|
||||
rawCfg, hasKey := jsnCfg[THRESHOLDS_JSON]
|
||||
if !hasKey {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -628,6 +628,17 @@ func (cfg *CGRConfig) checkConfigSanity() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
//SarS checks
|
||||
if cfg.sarsCfg.Enabled {
|
||||
for _, connID := range cfg.sarsCfg.StatSConns {
|
||||
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
||||
return fmt.Errorf("<%s> not enabled but requested by <%s> component", utils.StatS, utils.SaRS)
|
||||
}
|
||||
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
||||
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SaRS, connID)
|
||||
}
|
||||
}
|
||||
}
|
||||
// RouteS checks
|
||||
if cfg.routeSCfg.Enabled {
|
||||
for _, connID := range cfg.routeSCfg.AttributeSConns {
|
||||
|
||||
@@ -664,6 +664,11 @@ type StatServJsonCfg struct {
|
||||
Opts *StatsOptsJson
|
||||
}
|
||||
|
||||
type SarsJsonCfg struct {
|
||||
Enabled *bool
|
||||
Stats_conns *[]string
|
||||
}
|
||||
|
||||
type ThresholdsOptsJson struct {
|
||||
ProfileIDs *[]string `json:"*profileIDs"`
|
||||
ProfileIgnoreFilters *bool `json:"*profileIgnoreFilters"`
|
||||
|
||||
74
config/sarscfg.go
Normal file
74
config/sarscfg.go
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 SarSCfg struct {
|
||||
Enabled bool
|
||||
StatSConns []string
|
||||
}
|
||||
|
||||
func (sa *SarSCfg) loadFromJSONCfg(jsnCfg *SarsJsonCfg) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
sa.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.Stats_conns != nil {
|
||||
sa.StatSConns = make([]string, len(*jsnCfg.Stats_conns))
|
||||
for idx, conn := range *jsnCfg.Stats_conns {
|
||||
sa.StatSConns[idx] = conn
|
||||
if conn == utils.MetaInternal {
|
||||
sa.StatSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sa *SarSCfg) AsMapInterface() (initialMP map[string]any) {
|
||||
initialMP = map[string]any{
|
||||
utils.EnabledCfg: sa.Enabled,
|
||||
}
|
||||
if sa.StatSConns != nil {
|
||||
statSConns := make([]string, len(sa.StatSConns))
|
||||
for i, item := range sa.StatSConns {
|
||||
statSConns[i] = item
|
||||
if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats) {
|
||||
statSConns[i] = utils.MetaInternal
|
||||
}
|
||||
}
|
||||
initialMP[utils.StatSConnsCfg] = statSConns
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sa *SarSCfg) Clone() (cln *SarSCfg) {
|
||||
cln = &SarSCfg{
|
||||
Enabled: sa.Enabled,
|
||||
}
|
||||
if sa.StatSConns != nil {
|
||||
cln.StatSConns = make([]string, len(sa.StatSConns))
|
||||
copy(cln.StatSConns, sa.StatSConns)
|
||||
}
|
||||
return
|
||||
}
|
||||
105
services/sars.go
Normal file
105
services/sars.go
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
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 services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/cgrates/birpc"
|
||||
v1 "github.com/cgrates/cgrates/apier/v1"
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/cores"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type SaRService struct {
|
||||
sync.RWMutex
|
||||
cfg *config.CGRConfig
|
||||
dm *DataDBService
|
||||
cacheS *engine.CacheS
|
||||
filterSChan chan *engine.FilterS
|
||||
server *cores.Server
|
||||
connMgr *engine.ConnManager
|
||||
|
||||
connChan chan birpc.ClientConnector
|
||||
anz *AnalyzerService
|
||||
srvDep map[string]*sync.WaitGroup
|
||||
}
|
||||
|
||||
// Start should handle the sercive start
|
||||
func (sa *SaRService) Start() error {
|
||||
if sa.IsRunning() {
|
||||
return utils.ErrServiceAlreadyRunning
|
||||
}
|
||||
sa.srvDep[utils.DataDB].Add(1)
|
||||
<-sa.cacheS.GetPrecacheChannel(utils.CacheStatFilterIndexes)
|
||||
|
||||
filterS := <-sa.filterSChan
|
||||
sa.filterSChan <- filterS
|
||||
dbchan := sa.dm.GetDMChan()
|
||||
datadb := <-dbchan
|
||||
dbchan <- datadb
|
||||
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> starting <%s> subsystem",
|
||||
utils.CoreS, utils.SaRS))
|
||||
srv, err := engine.NewService(v1.NewSArSv1())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !sa.cfg.DispatcherSCfg().Enabled {
|
||||
for _, s := range srv {
|
||||
sa.server.RpcRegister(s)
|
||||
}
|
||||
}
|
||||
sa.connChan <- sa.anz.GetInternalCodec(srv, utils.StatS)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reload handles the change of config
|
||||
func (sa *SaRService) Reload() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Shutdown stops the service
|
||||
func (sa *SaRService) Shutdown() (err error) {
|
||||
defer sa.srvDep[utils.DataDB].Done()
|
||||
sa.Lock()
|
||||
defer sa.Unlock()
|
||||
<-sa.connChan
|
||||
return
|
||||
}
|
||||
|
||||
// IsRunning returns if the service is running
|
||||
func (sa *SaRService) IsRunning() bool {
|
||||
sa.RLock()
|
||||
defer sa.RUnlock()
|
||||
return false
|
||||
}
|
||||
|
||||
// ServiceName returns the service name
|
||||
func (sa *SaRService) ServiceName() string {
|
||||
return utils.SaRS
|
||||
}
|
||||
|
||||
// ShouldRun returns if the service should be running
|
||||
func (sa *SaRService) ShouldRun() bool {
|
||||
return sa.cfg.SarSCfg().Enabled
|
||||
}
|
||||
@@ -195,6 +195,8 @@ func (srvMngr *ServiceManager) handleReload() {
|
||||
go srvMngr.reloadService(utils.ThresholdS)
|
||||
case <-srvMngr.GetConfig().GetReloadChan(config.STATS_JSON):
|
||||
go srvMngr.reloadService(utils.StatS)
|
||||
case <-srvMngr.GetConfig().GetReloadChan(config.SARS_JSON):
|
||||
go srvMngr.reloadService(utils.SaRS)
|
||||
case <-srvMngr.GetConfig().GetReloadChan(config.RESOURCES_JSON):
|
||||
go srvMngr.reloadService(utils.ResourceS)
|
||||
case <-srvMngr.GetConfig().GetReloadChan(config.RouteSJson):
|
||||
|
||||
@@ -1014,6 +1014,7 @@ const (
|
||||
RouteS = "RouteS"
|
||||
SessionS = "SessionS"
|
||||
StatService = "StatS"
|
||||
SaRS = "SaRS"
|
||||
ThresholdS = "ThresholdS"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user