cfg: add stats/thresholds_conns to sip_agent

This commit is contained in:
ionutboangiu
2025-06-17 19:17:41 +03:00
committed by Dan Christian Bogos
parent add2ee1971
commit 2495b5c676
5 changed files with 122 additions and 60 deletions

View File

@@ -1829,6 +1829,8 @@ const CGRATES_CFG_JSON = `
"listen": "127.0.0.1:5060", // address where to listen for SIP requests <x.y.z.y:1234>
"listen_net": "udp", // network to listen on <udp|tcp|tcp-tls>
"sessions_conns": ["*internal"],
"stats_conns": [], // connections to StatS, empty to disable: <""|*internal|$rpc_conns_id>
"thresholds_conns": [], // connections to ThresholdS, empty to disable: <""|*internal|$rpc_conns_id>
"timezone": "", // timezone of the events if not specified <UTC|Local|$IANA_TZ_DB>
"retransmission_timer": "1s", // the duration to wait to receive an ACK before resending the reply
"request_processors": [] // request processors to be applied to SIP messages

File diff suppressed because one or more lines are too long

View File

@@ -586,6 +586,22 @@ func (cfg *CGRConfig) checkConfigSanity() error {
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SIPAgent, connID)
}
}
for _, connID := range cfg.sipAgentCfg.StatSConns {
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
return fmt.Errorf("<%s> not enabled but requested by <%s> component", utils.StatS, utils.SIPAgent)
}
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SIPAgent, connID)
}
}
for _, connID := range cfg.sipAgentCfg.ThresholdSConns {
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
return fmt.Errorf("<%s> not enabled but requested by <%s> component", utils.ThresholdS, utils.SIPAgent)
}
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SIPAgent, connID)
}
}
for _, req := range cfg.sipAgentCfg.RequestProcessors {
for _, field := range req.RequestFields {
if field.Type != utils.MetaNone && field.Path == utils.EmptyString {

View File

@@ -32,6 +32,8 @@ type SIPAgentCfg struct {
Listen string
ListenNet string // udp or tcp
SessionSConns []string
StatSConns []string
ThresholdSConns []string
Timezone string
RetransmissionTimer time.Duration // timeout replies if not reaching back
RequestProcessors []*RequestProcessor
@@ -53,8 +55,8 @@ func (sa *SIPAgentCfg) loadFromJSONCfg(jsnCfg *SIPAgentJsonCfg) (err error) {
if jsnCfg.Enabled != nil {
sa.Enabled = *jsnCfg.Enabled
}
if jsnCfg.Listen_net != nil {
sa.ListenNet = *jsnCfg.Listen_net
if jsnCfg.ListenNet != nil {
sa.ListenNet = *jsnCfg.ListenNet
}
if jsnCfg.Listen != nil {
sa.Listen = *jsnCfg.Listen
@@ -62,36 +64,40 @@ func (sa *SIPAgentCfg) loadFromJSONCfg(jsnCfg *SIPAgentJsonCfg) (err error) {
if jsnCfg.Timezone != nil {
sa.Timezone = *jsnCfg.Timezone
}
if jsnCfg.Sessions_conns != nil {
sa.SessionSConns = tagInternalConns(*jsnCfg.Sessions_conns, utils.MetaSessionS)
if jsnCfg.SessionSConns != nil {
sa.SessionSConns = tagInternalConns(*jsnCfg.SessionSConns, utils.MetaSessionS)
}
if jsnCfg.Retransmission_timer != nil {
if sa.RetransmissionTimer, err = utils.ParseDurationWithNanosecs(*jsnCfg.Retransmission_timer); err != nil {
if jsnCfg.StatSConns != nil {
sa.StatSConns = tagInternalConns(*jsnCfg.StatSConns, utils.MetaStats)
}
if jsnCfg.ThresholdSConns != nil {
sa.ThresholdSConns = tagInternalConns(*jsnCfg.ThresholdSConns, utils.MetaThresholds)
}
if jsnCfg.RetransmissionTimer != nil {
if sa.RetransmissionTimer, err = utils.ParseDurationWithNanosecs(*jsnCfg.RetransmissionTimer); err != nil {
return err
}
}
sa.RequestProcessors, err = appendRequestProcessors(sa.RequestProcessors, jsnCfg.Request_processors)
sa.RequestProcessors, err = appendRequestProcessors(sa.RequestProcessors, jsnCfg.RequestProcessors)
return
}
// AsMapInterface returns the config as a map[string]any
func (sa SIPAgentCfg) AsMapInterface() any {
mp := map[string]any{
utils.EnabledCfg: sa.Enabled,
utils.ListenCfg: sa.Listen,
utils.ListenNetCfg: sa.ListenNet,
utils.TimezoneCfg: sa.Timezone,
utils.RetransmissionTimerCfg: sa.RetransmissionTimer.String(),
}
requestProcessors := make([]map[string]any, len(sa.RequestProcessors))
for i, item := range sa.RequestProcessors {
requestProcessors[i] = item.AsMapInterface()
}
mp[utils.RequestProcessorsCfg] = requestProcessors
if sa.SessionSConns != nil {
mp[utils.SessionSConnsCfg] = stripInternalConns(sa.SessionSConns)
mp := map[string]any{
utils.EnabledCfg: sa.Enabled,
utils.ListenCfg: sa.Listen,
utils.ListenNetCfg: sa.ListenNet,
utils.SessionSConnsCfg: stripInternalConns(sa.SessionSConns),
utils.StatSConnsCfg: stripInternalConns(sa.StatSConns),
utils.ThresholdSConnsCfg: stripInternalConns(sa.ThresholdSConns),
utils.TimezoneCfg: sa.Timezone,
utils.RetransmissionTimerCfg: sa.RetransmissionTimer.String(),
utils.RequestProcessorsCfg: requestProcessors,
}
return mp
}
@@ -100,35 +106,37 @@ func (SIPAgentCfg) SName() string { return SIPAgentJSON }
func (sa SIPAgentCfg) CloneSection() Section { return sa.Clone() }
// Clone returns a deep copy of SIPAgentCfg
func (sa SIPAgentCfg) Clone() (cln *SIPAgentCfg) {
cln = &SIPAgentCfg{
func (sa SIPAgentCfg) Clone() *SIPAgentCfg {
clone := &SIPAgentCfg{
Enabled: sa.Enabled,
Listen: sa.Listen,
ListenNet: sa.ListenNet,
SessionSConns: slices.Clone(sa.SessionSConns),
StatSConns: slices.Clone(sa.StatSConns),
ThresholdSConns: slices.Clone(sa.ThresholdSConns),
Timezone: sa.Timezone,
RetransmissionTimer: sa.RetransmissionTimer,
}
if sa.SessionSConns != nil {
cln.SessionSConns = slices.Clone(sa.SessionSConns)
}
if sa.RequestProcessors != nil {
cln.RequestProcessors = make([]*RequestProcessor, len(sa.RequestProcessors))
clone.RequestProcessors = make([]*RequestProcessor, len(sa.RequestProcessors))
for i, rp := range sa.RequestProcessors {
cln.RequestProcessors[i] = rp.Clone()
clone.RequestProcessors[i] = rp.Clone()
}
}
return
return clone
}
// SIPAgentJsonCfg
type SIPAgentJsonCfg struct {
Enabled *bool
Listen *string
Listen_net *string
Sessions_conns *[]string
Timezone *string
Retransmission_timer *string
Request_processors *[]*ReqProcessorJsnCfg
Enabled *bool `json:"enabled"`
Listen *string `json:"listen"`
ListenNet *string `json:"listen_net"`
SessionSConns *[]string `json:"sessions_conns"`
StatSConns *[]string `json:"stats_conns"`
ThresholdSConns *[]string `json:"thresholds_conns"`
Timezone *string `json:"timezone"`
RetransmissionTimer *string `json:"retransmission_timer"`
RequestProcessors *[]*ReqProcessorJsnCfg `json:"request_processors"`
}
func diffSIPAgentJsonCfg(d *SIPAgentJsonCfg, v1, v2 *SIPAgentCfg) *SIPAgentJsonCfg {
@@ -142,17 +150,23 @@ func diffSIPAgentJsonCfg(d *SIPAgentJsonCfg, v1, v2 *SIPAgentCfg) *SIPAgentJsonC
d.Listen = utils.StringPointer(v2.Listen)
}
if v1.ListenNet != v2.ListenNet {
d.Listen_net = utils.StringPointer(v2.ListenNet)
d.ListenNet = utils.StringPointer(v2.ListenNet)
}
if !slices.Equal(v1.SessionSConns, v2.SessionSConns) {
d.Sessions_conns = utils.SliceStringPointer(stripInternalConns(v2.SessionSConns))
d.SessionSConns = utils.SliceStringPointer(stripInternalConns(v2.SessionSConns))
}
if !slices.Equal(v1.StatSConns, v2.StatSConns) {
d.StatSConns = utils.SliceStringPointer(stripInternalConns(v2.StatSConns))
}
if !slices.Equal(v1.ThresholdSConns, v2.ThresholdSConns) {
d.ThresholdSConns = utils.SliceStringPointer(stripInternalConns(v2.ThresholdSConns))
}
if v1.Timezone != v2.Timezone {
d.Timezone = utils.StringPointer(v2.Timezone)
}
if v1.RetransmissionTimer != v2.RetransmissionTimer {
d.Retransmission_timer = utils.StringPointer(v2.RetransmissionTimer.String())
d.RetransmissionTimer = utils.StringPointer(v2.RetransmissionTimer.String())
}
d.Request_processors = diffReqProcessorsJsnCfg(d.Request_processors, v1.RequestProcessors, v2.RequestProcessors)
d.RequestProcessors = diffReqProcessorsJsnCfg(d.RequestProcessors, v1.RequestProcessors, v2.RequestProcessors)
return d
}

View File

@@ -27,13 +27,15 @@ import (
func TestSIPAgentCfgloadFromJsonCfgCase1(t *testing.T) {
cfgJSONS := &SIPAgentJsonCfg{
Enabled: utils.BoolPointer(true),
Listen: utils.StringPointer("127.0.0.1:5060"),
Listen_net: utils.StringPointer("udp"),
Sessions_conns: &[]string{utils.MetaInternal},
Timezone: utils.StringPointer("local"),
Retransmission_timer: utils.StringPointer("1"),
Request_processors: &[]*ReqProcessorJsnCfg{
Enabled: utils.BoolPointer(true),
Listen: utils.StringPointer("127.0.0.1:5060"),
ListenNet: utils.StringPointer("udp"),
SessionSConns: &[]string{utils.MetaInternal},
StatSConns: &[]string{utils.MetaInternal},
ThresholdSConns: &[]string{utils.MetaInternal},
Timezone: utils.StringPointer("local"),
RetransmissionTimer: utils.StringPointer("1"),
RequestProcessors: &[]*ReqProcessorJsnCfg{
{
ID: utils.StringPointer("OutboundAUTHDryRun"),
Filters: &[]string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"},
@@ -56,6 +58,8 @@ func TestSIPAgentCfgloadFromJsonCfgCase1(t *testing.T) {
Listen: "127.0.0.1:5060",
ListenNet: "udp",
SessionSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaSessionS)},
StatSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)},
ThresholdSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds)},
Timezone: "local",
RetransmissionTimer: 1,
RequestProcessors: []*RequestProcessor{
@@ -94,7 +98,7 @@ func TestSIPAgentCfgloadFromJsonCfgCase1(t *testing.T) {
func TestSIPAgentCfgloadFromJsonCfgCase2(t *testing.T) {
cfgJSON := &SIPAgentJsonCfg{
Retransmission_timer: utils.StringPointer("1ss"),
RetransmissionTimer: utils.StringPointer("1ss"),
}
expected := "time: unknown unit \"ss\" in duration \"1ss\""
jsonCfg := NewDefaultCGRConfig()
@@ -114,7 +118,7 @@ func TestSIPAgentCfgloadFromJsonCfgCase4(t *testing.T) {
},
}`
sipAgent := &SIPAgentJsonCfg{
Request_processors: &[]*ReqProcessorJsnCfg{{
RequestProcessors: &[]*ReqProcessorJsnCfg{{
ID: utils.StringPointer("randomID"),
}},
}
@@ -136,7 +140,7 @@ func TestSIPAgentCfgloadFromJsonCfgCase4(t *testing.T) {
func TestSIPAgentCfgloadFromJsonCfgCase5(t *testing.T) {
sipAgent := &SIPAgentJsonCfg{
Request_processors: &[]*ReqProcessorJsnCfg{{
RequestProcessors: &[]*ReqProcessorJsnCfg{{
Tenant: utils.StringPointer("a{*"),
}},
}
@@ -154,6 +158,8 @@ func TestSIPAgentCfgAsMapInterface(t *testing.T) {
"listen": "127.0.0.1:5060",
"listen_net": "udp",
"sessions_conns": ["*internal"],
"stats_conns": ["*internal"],
"thresholds_conns": ["*internal"],
"timezone": "",
"retransmission_timer": "2s",
"request_processors": [
@@ -165,6 +171,8 @@ func TestSIPAgentCfgAsMapInterface(t *testing.T) {
utils.ListenCfg: "127.0.0.1:5060",
utils.ListenNetCfg: "udp",
utils.SessionSConnsCfg: []string{"*internal"},
utils.StatSConnsCfg: []string{"*internal"},
utils.ThresholdSConnsCfg: []string{"*internal"},
utils.TimezoneCfg: "",
utils.RetransmissionTimerCfg: "2s",
utils.RequestProcessorsCfg: []map[string]any{},
@@ -183,6 +191,8 @@ func TestSIPAgentCfgAsMapInterface1(t *testing.T) {
"listen": "127.0.0.1:5060",
"listen_net": "udp",
"sessions_conns": ["*internal"],
"stats_conns": ["*internal"],
"thresholds_conns": ["*internal"],
"timezone": "UTC",
"retransmission_timer": "5s",
"request_processors": [
@@ -215,6 +225,8 @@ func TestSIPAgentCfgAsMapInterface1(t *testing.T) {
utils.ListenCfg: "127.0.0.1:5060",
utils.ListenNetCfg: "udp",
utils.SessionSConnsCfg: []string{"*internal"},
utils.StatSConnsCfg: []string{"*internal"},
utils.ThresholdSConnsCfg: []string{"*internal"},
utils.TimezoneCfg: "UTC",
utils.RetransmissionTimerCfg: "5s",
utils.RequestProcessorsCfg: []map[string]any{
@@ -248,6 +260,8 @@ func TestSIPAgentCfgAsMapInterface2(t *testing.T) {
"enabled": true,
"listen": "",
"sessions_conns": ["*conn1", "*conn2"],
"stats_conns": ["*conn1", "*conn2"],
"thresholds_conns": ["*conn1", "*conn2"],
"request_processors": [
{
"id": "Register",
@@ -269,6 +283,8 @@ func TestSIPAgentCfgAsMapInterface2(t *testing.T) {
utils.ListenCfg: "",
utils.ListenNetCfg: "udp",
utils.SessionSConnsCfg: []string{"*conn1", "*conn2"},
utils.StatSConnsCfg: []string{"*conn1", "*conn2"},
utils.ThresholdSConnsCfg: []string{"*conn1", "*conn2"},
utils.TimezoneCfg: "",
utils.RetransmissionTimerCfg: "1s",
utils.RequestProcessorsCfg: []map[string]any{
@@ -339,6 +355,8 @@ func TestDiffSIPAgentJsonCfg(t *testing.T) {
Listen: "localhost:8080",
ListenNet: "tcp",
SessionSConns: []string{"*localhost"},
StatSConns: []string{"*localhost"},
ThresholdSConns: []string{"*localhost"},
Timezone: "UTC",
RetransmissionTimer: 1 * time.Second,
RequestProcessors: []*RequestProcessor{
@@ -352,20 +370,24 @@ func TestDiffSIPAgentJsonCfg(t *testing.T) {
Enabled: true,
Listen: "localhost:8037",
ListenNet: "udp",
SessionSConns: []string{"*birpc"},
SessionSConns: []string{"*internal"},
StatSConns: []string{"*internal"},
ThresholdSConns: []string{"*internal"},
Timezone: "EEST",
RetransmissionTimer: 2 * time.Second,
RequestProcessors: []*RequestProcessor{},
}
expected := &SIPAgentJsonCfg{
Enabled: utils.BoolPointer(true),
Listen: utils.StringPointer("localhost:8037"),
Listen_net: utils.StringPointer("udp"),
Sessions_conns: &[]string{"*birpc"},
Timezone: utils.StringPointer("EEST"),
Retransmission_timer: utils.StringPointer("2s"),
Request_processors: &[]*ReqProcessorJsnCfg{},
Enabled: utils.BoolPointer(true),
Listen: utils.StringPointer("localhost:8037"),
ListenNet: utils.StringPointer("udp"),
SessionSConns: &[]string{"*internal"},
StatSConns: &[]string{"*internal"},
ThresholdSConns: &[]string{"*internal"},
Timezone: utils.StringPointer("EEST"),
RetransmissionTimer: utils.StringPointer("2s"),
RequestProcessors: &[]*ReqProcessorJsnCfg{},
}
rcv := diffSIPAgentJsonCfg(d, v1, v2)
@@ -375,7 +397,7 @@ func TestDiffSIPAgentJsonCfg(t *testing.T) {
v1 = v2
expected = &SIPAgentJsonCfg{
Request_processors: &[]*ReqProcessorJsnCfg{},
RequestProcessors: &[]*ReqProcessorJsnCfg{},
}
rcv = diffSIPAgentJsonCfg(d, v1, v2)
if !reflect.DeepEqual(rcv, expected) {
@@ -389,6 +411,8 @@ func TestSipAgentCloneSection(t *testing.T) {
Listen: "localhost:8080",
ListenNet: "tcp",
SessionSConns: []string{"*localhost"},
StatSConns: []string{"*localhost"},
ThresholdSConns: []string{"*localhost"},
Timezone: "UTC",
RetransmissionTimer: 1 * time.Second,
RequestProcessors: []*RequestProcessor{
@@ -403,6 +427,8 @@ func TestSipAgentCloneSection(t *testing.T) {
Listen: "localhost:8080",
ListenNet: "tcp",
SessionSConns: []string{"*localhost"},
StatSConns: []string{"*localhost"},
ThresholdSConns: []string{"*localhost"},
Timezone: "UTC",
RetransmissionTimer: 1 * time.Second,
RequestProcessors: []*RequestProcessor{