Skip to content

Commit

Permalink
Add current trunkgroup limit and cps metrics (#6)
Browse files Browse the repository at this point in the history
Prviously only trunkgroups with active useage would appear in the
metrics.  This change adds two new metrics that track the current
configuration even if there's no traffic.

closes [ch-3334]
  • Loading branch information
tjdavis3 authored Sep 23, 2020
1 parent ba2dc37 commit 040aacb
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 9 deletions.
63 changes: 55 additions & 8 deletions collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
"time"
"unicode"

"github.com/magna5/sansay_exporter/models"

"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/hooklift/gowsdl/soap"
Expand Down Expand Up @@ -149,7 +151,7 @@ func (c collector) Describe(ch chan<- *prometheus.Desc) {

// Collect implements Prometheus.Collector.
func (c collector) Collect(ch chan<- prometheus.Metric) {
paths := []string{"realtime", "resource", "media_server"}
paths := []string{"stats/realtime", "stats/resource", "stats/media_server", "download/resource"}
var wg sync.WaitGroup
var err error
start := time.Now()
Expand All @@ -168,6 +170,9 @@ func (c collector) Collect(ch chan<- prometheus.Metric) {
case XBMediaServerRealTimeStatList:
err = nil
c.processMediaCollection(ch, obj)
case models.XBResourceList:
err = nil
c.processXBResourceList(ch, obj)
case error:
err = obj
default:
Expand Down Expand Up @@ -208,6 +213,17 @@ func (c collector) processMediaCollection(ch chan<- prometheus.Metric, media XBM
}
}

// processXBResourceList creates the metrics for the resource configurations.
func (c collector) processXBResourceList(ch chan<- prometheus.Metric, resources models.XBResourceList) {
labels := []string{"trunkgroup", "alias"}
var labelValues []string
for _, resource := range resources.XBResource {
labelValues = []string{resource.TrunkId, resource.Name}
addLabeledMetric(ch, "config_trunk_sessions_max", resource.Capacity, labels, labelValues)
addLabeledMetric(ch, "config_trunk_cps_max", resource.CpsLimit, labels, labelValues)
}
}

func (c collector) processCollection(ch chan<- prometheus.Metric, sansay Sansay) {
for _, table := range sansay.Database.Table {
var direction string
Expand Down Expand Up @@ -278,6 +294,7 @@ func ScrapeTarget(c collector, path string, result chan<- interface{}, wg *sync.
var obj interface{}
var sansay Sansay
var media XBMediaServerRealTimeStatList
var resourceList models.XBResourceList
var body []byte
var err error

Expand All @@ -299,12 +316,15 @@ func ScrapeTarget(c collector, path string, result chan<- interface{}, wg *sync.
if strings.HasSuffix(path, "media_server") {
err = xml.Unmarshal(body, &media)
obj = media
} else if strings.HasSuffix(path, "download/resource") {
err = xml.Unmarshal(body, &resourceList)
obj = resourceList
} else {
err = xml.Unmarshal(body, &sansay)
obj = sansay
}
if err != nil {
level.Error(logger).Log("msg", "Error parsing XML", "err", err)
level.Error(logger).Log("msg", "Error parsing XML", "path", path, "err", err)
result <- err
wg.Done()
return
Expand Down Expand Up @@ -366,23 +386,50 @@ func callRestAPI(c collector, path string) ([]byte, error) {

// callSoapAPI makes a SOAP call to the Sansay SBC -- used for older OS versions
func callSoapAPI(c collector, path string) ([]byte, error) {
var err error
var response []byte
var statName string

// Determine the stat name by splitting the path
paths := strings.Split(path, "/")
if len(paths) == 1 {
statName = paths[0]
} else {
statName = paths[len(paths)-1]
}

target := fmt.Sprintf("%s%s", c.target, "/SSConfig/SansayWS")
if !strings.HasPrefix(target, "http://") && !strings.HasPrefix(target, "https://") {
target = "http://" + target
}
client := soap.NewClient(target, soap.WithTLS(&tls.Config{InsecureSkipVerify: true}))
service := NewSansayWS(client)
params := &RealTimeStatsParams{
Username: c.username,
Password: c.password,
StatName: path,
if strings.HasSuffix(path, "download/resource") {
params := &DownloadParams{
Username: c.username,
Password: c.password,
Page: 0,
Table: "resource",
}

if reply, err := service.DoDownloadXmlFile(params); err == nil {
response = []byte(reply.Xmlfile)
}
} else {
params := &RealTimeStatsParams{
Username: c.username,
Password: c.password,
StatName: statName,
}
if reply, err := service.DoRealTimeStats(params); err == nil {
response = []byte(reply.Xmlfile)
}
}
reply, err := service.DoRealTimeStats(params)
if err != nil {
level.Error(c.logger).Log("msg", "Error calling SOAP API", "err", err)
return nil, err
}
return []byte(reply.Xmlfile), nil
return response, nil
}

func addMetric(ch chan<- prometheus.Metric, name string, value string) error {
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
"gopkg.in/alecthomas/kingpin.v2"
)

const targetPath = "/SSConfig/webresources/stats/"
const targetPath = "/SSConfig/webresources/"

var Version = "dev"

Expand Down
130 changes: 130 additions & 0 deletions models/xbresource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package models

import "encoding/xml"

// XBResourceList represents the DownloadXML data for a resource
type XBResourceList struct {
XMLName xml.Name `xml:"XBResourceList"`
Text string `xml:",chardata"`
XBResource []struct {
Text string `xml:",chardata"`
Protocol string `xml:"protocol"`
TypeSIPgw struct {
Text string `xml:",chardata"`
PortAddress string `xml:"portAddress"`
ServiceState string `xml:"serviceState"`
Direction string `xml:"direction"`
NAT string `xml:"NAT"`
AllowDirectMedia string `xml:"allowDirectMedia"`
SipProfileIndex string `xml:"sipProfileIndex"`
OptionPoll string `xml:"optionPoll"`
AuthorizedRPS string `xml:"authorizedRPS"`
UnauthorizedRPS string `xml:"unauthorizedRPS"`
} `xml:"typeSIPgw"`
Name string `xml:"name"`
CompanyName string `xml:"companyName"`
TrunkId string `xml:"trunkId"`
SgId string `xml:"sgId"`
Capacity string `xml:"capacity"`
CpsLimit string `xml:"cpsLimit"`
Node struct {
Text string `xml:",chardata"`
Fqdn string `xml:"fqdn"`
Netmask string `xml:"netmask"`
Capacity string `xml:"capacity"`
CpsLimit string `xml:"cpsLimit"`
CacProfileId string `xml:"cacProfileId"`
} `xml:"node"`
Rtid string `xml:"rtid"`
Ingress1 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"ingress1"`
Ingress2 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"ingress2"`
Egress1 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"egress1"`
Egress2 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"egress2"`
OutboundANI string `xml:"outboundANI"`
TechPrefix string `xml:"techPrefix"`
RnIngress1 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"rnIngress1"`
RnIngress2 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"rnIngress2"`
RnEgress1 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"rnEgress1"`
RnEgress2 struct {
Text string `xml:",chardata"`
Match string `xml:"match"`
Action1 string `xml:"action1"`
Digits1 string `xml:"digits1"`
Action2 string `xml:"action2"`
Digits2 string `xml:"digits2"`
} `xml:"rnEgress2"`
CodecPolicy string `xml:"codecPolicy"`
GroupPolicy string `xml:"groupPolicy"`
Dtid string `xml:"dtid"`
T38 string `xml:"t38"`
Rfc2833 string `xml:"rfc2833"`
PayloadType string `xml:"payloadType"`
Tos string `xml:"tos"`
SvcPortIndex string `xml:"svcPortIndex"`
RadiusAuthGrpIndex string `xml:"radiusAuthGrpIndex"`
RadiusAcctGrpIndex string `xml:"radiusAcctGrpIndex"`
LnpGrpIndex string `xml:"lnpGrpIndex"`
TeleblockGrpIndex string `xml:"teleblockGrpIndex"`
CnamGrpIndex string `xml:"cnamGrpIndex"`
ErsGrpIndex string `xml:"ersGrpIndex"`
MaxCallDuration string `xml:"maxCallDuration"`
MinCallDuration string `xml:"minCallDuration"`
NoAnswerTimeout string `xml:"noAnswerTimeout"`
NoRingTimeout string `xml:"noRingTimeout"`
CauseCodeProfile string `xml:"causeCodeProfile"`
StopRouteProfile string `xml:"stopRouteProfile"`
PaiAction string `xml:"paiAction"`
PaiString string `xml:"paiString"`
InheritedGenericHeader string `xml:"inheritedGenericHeader"`
OutSMCProfileId string `xml:"outSMCProfileId"`
} `xml:"XBResource"`
}

0 comments on commit 040aacb

Please sign in to comment.