Browse Source

split upnp into seperate package

pull/1/head
Nils Decker 9 years ago
parent
commit
05c803b465
  1. 1
      .gitignore
  2. 50
      fritzbox_upnp/upnp.go
  3. 67
      fritzbox_upnp/values.go
  4. 152
      main.go

1
.gitignore

@ -0,0 +1 @@
fritzbox_exporter

50
upnp.go → fritzbox_upnp/upnp.go

@ -1,4 +1,4 @@
package main
package fritzbox_upnp
import (
"bytes"
@ -7,10 +7,11 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
)
const TEXT_XML = `text/xml; charset="utf-8"`
const text_xml = `text/xml; charset="utf-8"`
var (
ErrResultNotFound = errors.New("result not found")
@ -27,14 +28,17 @@ var (
// </s:Body> </s:Envelope>"
type UpnpValue struct {
path string
service string
method string
ret_tag string
Path string
Service string
Method string
RetTag string
ShortName string
Help string
}
func (v *UpnpValue) Query(device string) (string, error) {
url := fmt.Sprintf("http://%s:49000%s", device, v.path)
func (v *UpnpValue) query(device string, port uint16) (string, error) {
url := fmt.Sprintf("http://%s:%d%s", device, port, v.Path)
bodystr := fmt.Sprintf(`
<?xml version='1.0' encoding='utf-8'?>
@ -43,7 +47,7 @@ func (v *UpnpValue) Query(device string) (string, error) {
<u:%s xmlns:u='urn:schemas-upnp-org:service:%s' />
</s:Body>
</s:Envelope>
`, v.method, v.service)
`, v.Method, v.Service)
body := strings.NewReader(bodystr)
@ -52,9 +56,9 @@ func (v *UpnpValue) Query(device string) (string, error) {
return "", err
}
action := fmt.Sprintf("urn:schemas-upnp-org:service:%s#%s", v.service, v.method)
action := fmt.Sprintf("urn:schemas-upnp-org:service:%s#%s", v.Service, v.Method)
req.Header["Content-Type"] = []string{TEXT_XML}
req.Header["Content-Type"] = []string{text_xml}
req.Header["SoapAction"] = []string{action}
resp, err := http.DefaultClient.Do(req)
@ -80,7 +84,7 @@ func (v *UpnpValue) Query(device string) (string, error) {
}
if se, ok := t.(xml.StartElement); ok {
if se.Name.Local == v.ret_tag {
if se.Name.Local == v.RetTag {
t2, err := dec.Token()
if err != nil {
return "", err
@ -96,3 +100,25 @@ func (v *UpnpValue) Query(device string) (string, error) {
}
}
type UpnpValueString struct{ UpnpValue }
func (v *UpnpValueString) Query(device string, port uint16) (string, error) {
return v.query(device, port)
}
type UpnpValueUint struct{ UpnpValue }
func (v *UpnpValueUint) Query(device string, port uint16) (uint64, error) {
strval, err := v.query(device, port)
if err != nil {
return 0, err
}
val, err := strconv.ParseUint(strval, 10, 64)
if err != nil {
return 0, err
}
return val, nil
}

67
fritzbox_upnp/values.go

@ -0,0 +1,67 @@
package fritzbox_upnp
// curl http://fritz.box:49000/igddesc.xml
// curl http://fritz.box:49000/any.xml
// curl http://fritz.box:49000/igdconnSCPD.xml
// curl http://fritz.box:49000/igdicfgSCPD.xml
// curl http://fritz.box:49000/igddslSCPD.xml
// curl http://fritz.box:49000/igd2ipv6fwcSCPD.xml
var (
WAN_IP = UpnpValueString{UpnpValue{
Path: "/igdupnp/control/WANIPConn1",
Service: "WANIPConnection:1",
Method: "GetExternalIPAddress",
RetTag: "NewExternalIPAddress",
ShortName: "wan_ip",
Help: "WAN IP Adress",
}}
WAN_Packets_Received = UpnpValueUint{UpnpValue{
Path: "/igdupnp/control/WANCommonIFC1",
Service: "WANCommonInterfaceConfig:1",
Method: "GetTotalPacketsReceived",
RetTag: "NewTotalPacketsReceived",
ShortName: "packets_received",
Help: "packets received on gateway WAN interface",
}}
WAN_Packets_Sent = UpnpValueUint{UpnpValue{
Path: "/igdupnp/control/WANCommonIFC1",
Service: "WANCommonInterfaceConfig:1",
Method: "GetTotalPacketsSent",
RetTag: "NewTotalPacketsSent",
ShortName: "packets_sent",
Help: "packets sent on gateway WAN interface",
}}
WAN_Bytes_Received = UpnpValueUint{UpnpValue{
Path: "/igdupnp/control/WANCommonIFC1",
Service: "WANCommonInterfaceConfig:1",
Method: "GetAddonInfos",
RetTag: "NewTotalBytesReceived",
ShortName: "bytes_received",
Help: "bytes received on gateway WAN interface",
}}
WAN_Bytes_Sent = UpnpValueUint{UpnpValue{
Path: "/igdupnp/control/WANCommonIFC1",
Service: "WANCommonInterfaceConfig:1",
Method: "GetAddonInfos",
RetTag: "NewTotalBytesSent",
ShortName: "bytes_sent",
Help: "bytes sent on gateway WAN interface",
}}
)
var Values = []UpnpValueUint{
WAN_Packets_Received,
WAN_Packets_Sent,
WAN_Bytes_Received,
WAN_Bytes_Sent,
}

152
main.go

@ -2,74 +2,40 @@ package main
import (
"flag"
"fmt"
"net/http"
"strconv"
"github.com/prometheus/client_golang/prometheus"
upnp "github.com/ndecker/fritzbox_exporter/fritzbox_upnp"
)
var (
flag_test = flag.Bool("test", false, "print all available metrics to stdout")
flag_addr = flag.String("listen-address", ":9111", "The address to listen on for HTTP requests.")
flag_dev_address = flag.String("device-address", "fritz.box", "The URL of the upnp service")
flag_gateway_address = flag.String("gateway-address", "fritz.box", "The URL of the upnp service")
flag_gateway_port = flag.Int("gateway-port", 49000, "The URL of the upnp service")
)
var (
WAN_IP = UpnpValue{
path: "/igdupnp/control/WANIPConn1",
service: "WANIPConnection:1",
method: "GetExternalIPAddress",
ret_tag: "NewExternalIPAddress",
}
WAN_Packets_Received = UpnpValue{
path: "/igdupnp/control/WANCommonIFC1",
service: "WANCommonInterfaceConfig:1",
method: "GetTotalPacketsReceived",
ret_tag: "NewTotalPacketsReceived",
}
WAN_Packets_Sent = UpnpValue{
path: "/igdupnp/control/WANCommonIFC1",
service: "WANCommonInterfaceConfig:1",
method: "GetTotalPacketsSent",
ret_tag: "NewTotalPacketsSent",
}
WAN_Bytes_Received = UpnpValue{
path: "/igdupnp/control/WANCommonIFC1",
service: "WANCommonInterfaceConfig:1",
method: "GetAddonInfos",
ret_tag: "NewTotalBytesReceived",
}
WAN_Bytes_Sent = UpnpValue{
path: "/igdupnp/control/WANCommonIFC1",
service: "WANCommonInterfaceConfig:1",
method: "GetAddonInfos",
ret_tag: "NewTotalBytesSent",
}
collect_errors = prometheus.NewCounter(prometheus.CounterOpts{
Name: "fritzbox_exporter_collect_errors",
Help: "Number of collection errors.",
})
)
type Metric struct {
UpnpValue
type UpnpMetric struct {
upnp.UpnpValueUint
*prometheus.Desc
}
func (m Metric) Value() (uint64, error) {
strval, err := m.Query(*flag_dev_address)
if err != nil {
return 0, err
}
return strconv.ParseUint(strval, 10, 64)
}
func (m Metric) Describe(ch chan<- *prometheus.Desc) {
func (m UpnpMetric) Describe(ch chan<- *prometheus.Desc) {
ch <- m.Desc
}
func (m Metric) Collect(ch chan<- prometheus.Metric) error {
val, err := m.Value()
func (m UpnpMetric) Collect(gateway string, port uint16, ch chan<- prometheus.Metric) error {
val, err := m.Query(gateway, port)
if err != nil {
return err
}
@ -78,72 +44,68 @@ func (m Metric) Collect(ch chan<- prometheus.Metric) error {
m.Desc,
prometheus.CounterValue,
float64(val),
gateway,
)
return nil
}
var (
packets_sent = Metric{
WAN_Packets_Sent,
prometheus.NewDesc(
prometheus.BuildFQName("gateway", "wan", "packets_sent"),
"packets sent on gateway wan interface",
nil,
prometheus.Labels{"gateway": *flag_dev_address},
),
}
packets_received = Metric{
WAN_Packets_Received,
prometheus.NewDesc(
prometheus.BuildFQName("gateway", "wan", "packets_received"),
"packets received on gateway wan interface",
nil,
prometheus.Labels{"gateway": *flag_dev_address},
),
}
bytes_sent = Metric{
WAN_Bytes_Sent,
func NewUpnpMetric(v upnp.UpnpValueUint) UpnpMetric {
return UpnpMetric{
v,
prometheus.NewDesc(
prometheus.BuildFQName("gateway", "wan", "bytes_sent"),
"bytes sent on gateway wan interface",
prometheus.BuildFQName("gateway", "wan", v.ShortName),
v.Help,
[]string{"gateway"},
nil,
prometheus.Labels{"gateway": *flag_dev_address},
),
}
bytes_received = Metric{
WAN_Bytes_Received,
prometheus.NewDesc(
prometheus.BuildFQName("gateway", "wan", "bytes_received"),
"bytes received on gateway wan interface",
nil,
prometheus.Labels{"gateway": *flag_dev_address},
),
}
)
}
type FritzboxCollector struct {
gateway string
port uint16
metrics []UpnpMetric
}
func (fc *FritzboxCollector) Describe(ch chan<- *prometheus.Desc) {
packets_sent.Describe(ch)
packets_received.Describe(ch)
bytes_sent.Describe(ch)
bytes_received.Describe(ch)
for _, m := range fc.metrics {
m.Describe(ch)
}
}
func (fc *FritzboxCollector) Collect(ch chan<- prometheus.Metric) {
packets_sent.Collect(ch)
packets_received.Collect(ch)
bytes_sent.Collect(ch)
bytes_received.Collect(ch)
for _, m := range fc.metrics {
err := m.Collect(fc.gateway, fc.port, ch)
if err != nil {
collect_errors.Inc()
}
}
}
func main() {
flag.Parse()
prometheus.MustRegister(&FritzboxCollector{})
if *flag_test {
for _, v := range upnp.Values {
res, err := v.Query(*flag_gateway_address, uint16(*flag_gateway_port))
if err != nil {
panic(err)
}
fmt.Printf("%s: %d\n", v.ShortName, res)
}
return
}
metrics := make([]UpnpMetric, len(upnp.Values))
for _, v := range upnp.Values {
metrics = append(metrics, NewUpnpMetric(v))
}
prometheus.MustRegister(&FritzboxCollector{
*flag_gateway_address,
uint16(*flag_gateway_port),
metrics,
})
// Since we are dealing with custom Collector implementations, it might
// be a good idea to enable the collect checks in the registry.
prometheus.EnableCollectChecks(true)

Loading…
Cancel
Save