Merge pull request #13 from czerwonk/v1.0

V1.0
This commit is contained in:
Daniel Czerwonk 2017-12-01 14:42:24 +01:00 committed by GitHub
commit cb0aad31a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 305 additions and 231 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.idea
*.iml
bird_exporter

View File

@ -13,6 +13,28 @@ To get meaningful uptime information bird has to be configured this way:
timeformat protocol "%s";
```
## Metric formats
In version 1.0 a new metric format was added.
To prevent a breaking change the new format is optional and can be enabled by using the ```-format.new``` flag.
The new format handles protocols more generic and allows a better query structure.
In both formats protocol specific metrics are prefixed with the protocol name (e.g. OSPF running metric).
This is a short example of the different formats:
### old format
```
bgp4_session_prefix_count_import{name="bgp1"} 600000
bgp6_session_prefix_count_import{name="bgp1"} 50000
ospfv3_running{name="ospf1"} 1
```
### new format
```
bird_protocol_prefix_import_count{name="bgp1",proto="BGP",ip_version="4"} 600000
bird_protocol_prefix_import_count{name="bgp1",proto="BGP",ip_version="6"} 50000
bird_ospfv3_running{name="ospf1"} 1
```
### Default Port
In version 0.7.1 the default port changed to 9324 since port 9200 is the default port of elasticsearch. The new port is now registered in the default port allocation list (https://github.com/prometheus/prometheus/wiki/Default-port-allocations)
@ -24,6 +46,11 @@ In version 0.8 communication to bird changed to sockets. The default socket path
go get -u github.com/czerwonk/bird_exporter
```
## Usage
```
bird_exporter -format.new=true
```
## Features
* BGP session state
* imported / exported / filtered prefix counts / route state changes (BGP, OSPF, Kernel, Static, Device, Direct)

View File

@ -1,26 +0,0 @@
package bgp
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
var exporter map[int]*protocol.GenericProtocolMetricExporter
type BgpMetricExporter struct {
}
func init() {
exporter = make(map[int]*protocol.GenericProtocolMetricExporter)
exporter[4] = protocol.NewGenericProtocolMetricExporter("bgp4_session")
exporter[6] = protocol.NewGenericProtocolMetricExporter("bgp6_session")
}
func (*BgpMetricExporter) Describe(ch chan<- *prometheus.Desc) {
exporter[4].Describe(ch)
exporter[6].Describe(ch)
}
func (*BgpMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
exporter[p.IpVersion].Export(p, ch)
}

View File

@ -3,6 +3,7 @@ package main
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/czerwonk/bird_socket"
"github.com/czerwonk/bird_exporter/parser"
)
func getProtocols() ([]*protocol.Protocol, error) {
@ -33,5 +34,5 @@ func getProtocolsFromBird(socketPath string, ipVersion int) ([]*protocol.Protoco
return nil, err
}
return parseOutput(b, ipVersion), nil
return parser.Parse(b, ipVersion), nil
}

View File

@ -1,26 +0,0 @@
package device
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
var exporter map[int]*protocol.GenericProtocolMetricExporter
type DeviceMetricExporter struct {
}
func init() {
exporter = make(map[int]*protocol.GenericProtocolMetricExporter)
exporter[4] = protocol.NewGenericProtocolMetricExporter("device4")
exporter[6] = protocol.NewGenericProtocolMetricExporter("device6")
}
func (m *DeviceMetricExporter) Describe(ch chan<- *prometheus.Desc) {
exporter[4].Describe(ch)
exporter[6].Describe(ch)
}
func (m *DeviceMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
exporter[p.IpVersion].Export(p, ch)
}

View File

@ -1,26 +0,0 @@
package direct
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
var exporter map[int]*protocol.GenericProtocolMetricExporter
type DirectMetricExporter struct {
}
func init() {
exporter = make(map[int]*protocol.GenericProtocolMetricExporter)
exporter[4] = protocol.NewGenericProtocolMetricExporter("direct4")
exporter[6] = protocol.NewGenericProtocolMetricExporter("direct6")
}
func (*DirectMetricExporter) Describe(ch chan<- *prometheus.Desc) {
exporter[4].Describe(ch)
exporter[6].Describe(ch)
}
func (*DirectMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
exporter[p.IpVersion].Export(p, ch)
}

View File

@ -1,26 +0,0 @@
package kernel
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
var exporter map[int]*protocol.GenericProtocolMetricExporter
type KernelMetricExporter struct {
}
func init() {
exporter = make(map[int]*protocol.GenericProtocolMetricExporter)
exporter[4] = protocol.NewGenericProtocolMetricExporter("kernel4")
exporter[6] = protocol.NewGenericProtocolMetricExporter("kernel6")
}
func (*KernelMetricExporter) Describe(ch chan<- *prometheus.Desc) {
exporter[4].Describe(ch)
exporter[6].Describe(ch)
}
func (*KernelMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
exporter[p.IpVersion].Export(p, ch)
}

42
main.go
View File

@ -6,12 +6,13 @@ import (
"net/http"
"os"
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/log"
)
const version string = "0.9.0"
const version string = "1.0.0"
var (
showVersion = flag.Bool("version", false, "Print version information.")
@ -21,6 +22,13 @@ var (
bird6Socket = flag.String("bird.socket6", "/var/run/bird6.ctl", "Socket to communicate with bird6 routing daemon")
birdEnabled = flag.Bool("bird.ipv4", true, "Get protocols from bird")
bird6Enabled = flag.Bool("bird.ipv6", true, "Get protocols from bird6")
newFormat = flag.Bool("format.new", false, "New metric format (more convinient / generic)")
enableBgp = flag.Bool("proto.bgp", true, "Enables metrics for protocol BGP")
enableOspf = flag.Bool("proto.ospf", true, "Enables metrics for protocol OSPF")
enableKernel = flag.Bool("proto.kernel", true, "Enables metrics for protocol Kernel")
enableStatic = flag.Bool("proto.static", true, "Enables metrics for protocol Static")
enableDevice = flag.Bool("proto.device", true, "Enables metrics for protocol Device")
enableDirect = flag.Bool("proto.direct", true, "Enables metrics for protocol Direct")
)
func init() {
@ -51,6 +59,11 @@ func printVersion() {
func startServer() {
log.Infof("Starting bird exporter (Version: %s)\n", version)
if !*newFormat {
log.Info("INFO: You are using the old metric format. Please consider using the new (more convinient one) by setting -format.new=true.")
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`<html>
<head><title>Bird Routing Daemon Exporter (Version ` + version + `)</title></head>
@ -87,7 +100,8 @@ func handleMetricsRequest(w http.ResponseWriter, r *http.Request) error {
if len(protocols) > 0 {
reg := prometheus.NewRegistry()
c := NewMetricCollectorForProtocols(protocols)
p := enabledProtocols()
c := NewMetricCollectorForProtocols(protocols, *newFormat, p)
reg.MustRegister(c)
promhttp.HandlerFor(reg, promhttp.HandlerOpts{
@ -97,3 +111,27 @@ func handleMetricsRequest(w http.ResponseWriter, r *http.Request) error {
return nil
}
func enabledProtocols() int {
res := 0
if *enableBgp {
res |= protocol.BGP
}
if *enableOspf {
res |= protocol.OSPF
}
if *enableKernel {
res |= protocol.Kernel
}
if *enableStatic {
res |= protocol.Static
}
if *enableDevice {
res |= protocol.Device
}
if *enableDirect {
res |= protocol.Direct
}
return res
}

View File

@ -1,49 +1,73 @@
package main
import (
"github.com/czerwonk/bird_exporter/bgp"
"github.com/czerwonk/bird_exporter/device"
"github.com/czerwonk/bird_exporter/direct"
"github.com/czerwonk/bird_exporter/kernel"
"github.com/czerwonk/bird_exporter/metrics"
"github.com/czerwonk/bird_exporter/ospf"
"github.com/czerwonk/bird_exporter/protocol"
"github.com/czerwonk/bird_exporter/static"
"github.com/prometheus/client_golang/prometheus"
)
type MetricExporter interface {
Describe(ch chan<- *prometheus.Desc)
Export(p *protocol.Protocol, ch chan<- prometheus.Metric)
}
type MetricCollector struct {
protocols []*protocol.Protocol
exporters map[int]MetricExporter
protocols []*protocol.Protocol
exporters map[int][]metrics.MetricExporter
enabledProtocols int
}
func NewMetricCollectorForProtocols(protocols []*protocol.Protocol) *MetricCollector {
e := map[int]MetricExporter{
protocol.BGP: &bgp.BgpMetricExporter{},
protocol.Device: &device.DeviceMetricExporter{},
protocol.Direct: &direct.DirectMetricExporter{},
protocol.Kernel: &kernel.KernelMetricExporter{},
protocol.OSPF: &ospf.OspfMetricExporter{},
protocol.Static: &static.StaticMetricExporter{},
func NewMetricCollectorForProtocols(protocols []*protocol.Protocol, newFormat bool, enabledProtocols int) *MetricCollector {
var e map[int][]metrics.MetricExporter
if newFormat {
e = exportersForDefault()
} else {
e = exportersForLegacy()
}
return &MetricCollector{protocols: protocols, exporters: e}
return &MetricCollector{protocols: protocols, exporters: e, enabledProtocols: enabledProtocols}
}
func exportersForLegacy() map[int][]metrics.MetricExporter {
l := &metrics.LegacyLabelStrategy{}
return map[int][]metrics.MetricExporter{
protocol.BGP: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("bgp4_session", "bgp6_session", l)},
protocol.Device: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("device4", "device6", l)},
protocol.Direct: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("direct4", "direct6", l)},
protocol.Kernel: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("kernel4", "kernel6", l)},
protocol.OSPF: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("ospf", "ospfv3", l), ospf.NewExporter("")},
protocol.Static: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("static4", "static6", l)},
}
}
func exportersForDefault() map[int][]metrics.MetricExporter {
l := &metrics.DefaultLabelStrategy{}
e := metrics.NewGenericProtocolMetricExporter("bird_protocol", true, l)
return map[int][]metrics.MetricExporter{
protocol.BGP: []metrics.MetricExporter{e},
protocol.Device: []metrics.MetricExporter{e},
protocol.Direct: []metrics.MetricExporter{e},
protocol.Kernel: []metrics.MetricExporter{e},
protocol.OSPF: []metrics.MetricExporter{e, ospf.NewExporter("bird_")},
protocol.Static: []metrics.MetricExporter{e},
}
}
func (m *MetricCollector) Describe(ch chan<- *prometheus.Desc) {
for _, v := range m.exporters {
v.Describe(ch)
for _, e := range v {
e.Describe(ch)
}
}
}
func (m *MetricCollector) Collect(ch chan<- prometheus.Metric) {
for _, p := range m.protocols {
if p.Proto != protocol.PROTO_UNKNOWN {
m.exporters[p.Proto].Export(p, ch)
if p.Proto == protocol.PROTO_UNKNOWN || (m.enabledProtocols & p.Proto != p.Proto) {
continue
}
for _, e := range m.exporters[p.Proto] {
e.Export(p, ch)
}
}
}

View File

@ -0,0 +1,39 @@
package metrics
import (
"github.com/czerwonk/bird_exporter/protocol"
"strconv"
)
type DefaultLabelStrategy struct {
}
func (*DefaultLabelStrategy) labelNames() []string {
return []string{"name", "proto", "ip_version"}
}
func (*DefaultLabelStrategy) labelValues(p *protocol.Protocol) []string {
return []string{p.Name, protoString(p), strconv.Itoa(p.IpVersion)}
}
func protoString(p *protocol.Protocol) string {
switch p.Proto {
case protocol.BGP:
return "BGP"
case protocol.OSPF:
if p.IpVersion == 4 {
return "OSPF"
} else {
return "OSPFv3"
}
case protocol.Static:
return "Static"
case protocol.Kernel:
return "Kernel"
case protocol.Device:
return "Device"
case protocol.Direct:
return "Direct"
}
return ""
}

View File

@ -1,8 +1,12 @@
package protocol
package metrics
import "github.com/prometheus/client_golang/prometheus"
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
type GenericProtocolMetricExporter struct {
labelStrategy LabelStrategy
upDesc *prometheus.Desc
importCountDesc *prometheus.Desc
exportCountDesc *prometheus.Desc
@ -31,20 +35,29 @@ type GenericProtocolMetricExporter struct {
withdrawsExportAcceptCountDesc *prometheus.Desc
}
func NewGenericProtocolMetricExporter(prefix string) *GenericProtocolMetricExporter {
m := &GenericProtocolMetricExporter{}
m.initDesc(prefix)
func NewGenericProtocolMetricExporter(prefix string, newNaming bool, labelStrategy LabelStrategy) *GenericProtocolMetricExporter {
m := &GenericProtocolMetricExporter{labelStrategy: labelStrategy}
m.initDesc(prefix, newNaming)
return m
}
func (m *GenericProtocolMetricExporter) initDesc(prefix string) {
labels := []string{"name"}
func (m *GenericProtocolMetricExporter) initDesc(prefix string, newNaming bool) {
labels := m.labelStrategy.labelNames()
m.upDesc = prometheus.NewDesc(prefix+"_up", "Protocol is up", labels, nil)
m.importCountDesc = prometheus.NewDesc(prefix+"_prefix_count_import", "Number of imported routes", labels, nil)
m.exportCountDesc = prometheus.NewDesc(prefix+"_prefix_count_export", "Number of exported routes", labels, nil)
m.filterCountDesc = prometheus.NewDesc(prefix+"_prefix_count_filter", "Number of filtered routes", labels, nil)
m.preferredCountDesc = prometheus.NewDesc(prefix+"_prefix_count_preferred", "Number of preferred routes", labels, nil)
if newNaming {
m.importCountDesc = prometheus.NewDesc(prefix+"_prefix_import_count", "Number of imported routes", labels, nil)
m.exportCountDesc = prometheus.NewDesc(prefix+"_prefix_export_count", "Number of exported routes", labels, nil)
m.filterCountDesc = prometheus.NewDesc(prefix+"_prefix_filter_count", "Number of filtered routes", labels, nil)
m.preferredCountDesc = prometheus.NewDesc(prefix+"_prefix_preferred_count", "Number of preferred routes", labels, nil)
} else {
m.importCountDesc = prometheus.NewDesc(prefix+"_prefix_count_import", "Number of imported routes", labels, nil)
m.exportCountDesc = prometheus.NewDesc(prefix+"_prefix_count_export", "Number of exported routes", labels, nil)
m.filterCountDesc = prometheus.NewDesc(prefix+"_prefix_count_filter", "Number of filtered routes", labels, nil)
m.preferredCountDesc = prometheus.NewDesc(prefix+"_prefix_count_preferred", "Number of preferred routes", labels, nil)
}
m.uptimeDesc = prometheus.NewDesc(prefix+"_uptime", "Uptime of the protocol in seconds", labels, nil)
m.updatesImportIgnoreCountDesc = prometheus.NewDesc(prefix+"_changes_update_import_ignore_count", "Number of incoming updates beeing ignored", labels, nil)
m.updatesImportAcceptCountDesc = prometheus.NewDesc(prefix+"_changes_update_import_accept_count", "Number of incoming updates beeing accepted", labels, nil)
@ -97,31 +110,32 @@ func (m *GenericProtocolMetricExporter) Describe(ch chan<- *prometheus.Desc) {
ch <- m.withdrawsExportReceiveCountDesc
}
func (m *GenericProtocolMetricExporter) Export(protocol *Protocol, ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(m.upDesc, prometheus.GaugeValue, float64(protocol.Up), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.importCountDesc, prometheus.GaugeValue, float64(protocol.Imported), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.exportCountDesc, prometheus.GaugeValue, float64(protocol.Exported), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.filterCountDesc, prometheus.GaugeValue, float64(protocol.Filtered), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.preferredCountDesc, prometheus.GaugeValue, float64(protocol.Preferred), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.uptimeDesc, prometheus.GaugeValue, float64(protocol.Uptime), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesImportReceiveCountDesc, prometheus.GaugeValue, float64(protocol.ImportUpdates.Received), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesImportRejectCountDesc, prometheus.GaugeValue, float64(protocol.ImportUpdates.Rejected), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesImportFilterCountDesc, prometheus.GaugeValue, float64(protocol.ImportUpdates.Filtered), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesImportAcceptCountDesc, prometheus.GaugeValue, float64(protocol.ImportUpdates.Accepted), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesImportIgnoreCountDesc, prometheus.GaugeValue, float64(protocol.ImportUpdates.Ignored), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesExportReceiveCountDesc, prometheus.GaugeValue, float64(protocol.ExportUpdates.Received), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesExportRejectCountDesc, prometheus.GaugeValue, float64(protocol.ExportUpdates.Rejected), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesExportFilterCountDesc, prometheus.GaugeValue, float64(protocol.ExportUpdates.Filtered), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesExportAcceptCountDesc, prometheus.GaugeValue, float64(protocol.ExportUpdates.Accepted), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.updatesExportIgnoreCountDesc, prometheus.GaugeValue, float64(protocol.ExportUpdates.Ignored), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportReceiveCountDesc, prometheus.GaugeValue, float64(protocol.ImportWithdraws.Received), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportRejectCountDesc, prometheus.GaugeValue, float64(protocol.ImportWithdraws.Rejected), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportFilterCountDesc, prometheus.GaugeValue, float64(protocol.ImportWithdraws.Filtered), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportAcceptCountDesc, prometheus.GaugeValue, float64(protocol.ImportWithdraws.Accepted), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportIgnoreCountDesc, prometheus.GaugeValue, float64(protocol.ImportWithdraws.Ignored), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportReceiveCountDesc, prometheus.GaugeValue, float64(protocol.ExportWithdraws.Received), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportRejectCountDesc, prometheus.GaugeValue, float64(protocol.ExportWithdraws.Rejected), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportFilterCountDesc, prometheus.GaugeValue, float64(protocol.ExportWithdraws.Filtered), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportAcceptCountDesc, prometheus.GaugeValue, float64(protocol.ExportWithdraws.Accepted), protocol.Name)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportIgnoreCountDesc, prometheus.GaugeValue, float64(protocol.ExportWithdraws.Ignored), protocol.Name)
func (m *GenericProtocolMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
l := m.labelStrategy.labelValues(p)
ch <- prometheus.MustNewConstMetric(m.upDesc, prometheus.GaugeValue, float64(p.Up), l...)
ch <- prometheus.MustNewConstMetric(m.importCountDesc, prometheus.GaugeValue, float64(p.Imported), l...)
ch <- prometheus.MustNewConstMetric(m.exportCountDesc, prometheus.GaugeValue, float64(p.Exported), l...)
ch <- prometheus.MustNewConstMetric(m.filterCountDesc, prometheus.GaugeValue, float64(p.Filtered), l...)
ch <- prometheus.MustNewConstMetric(m.preferredCountDesc, prometheus.GaugeValue, float64(p.Preferred), l...)
ch <- prometheus.MustNewConstMetric(m.uptimeDesc, prometheus.GaugeValue, float64(p.Uptime), l...)
ch <- prometheus.MustNewConstMetric(m.updatesImportReceiveCountDesc, prometheus.GaugeValue, float64(p.ImportUpdates.Received), l...)
ch <- prometheus.MustNewConstMetric(m.updatesImportRejectCountDesc, prometheus.GaugeValue, float64(p.ImportUpdates.Rejected), l...)
ch <- prometheus.MustNewConstMetric(m.updatesImportFilterCountDesc, prometheus.GaugeValue, float64(p.ImportUpdates.Filtered), l...)
ch <- prometheus.MustNewConstMetric(m.updatesImportAcceptCountDesc, prometheus.GaugeValue, float64(p.ImportUpdates.Accepted), l...)
ch <- prometheus.MustNewConstMetric(m.updatesImportIgnoreCountDesc, prometheus.GaugeValue, float64(p.ImportUpdates.Ignored), l...)
ch <- prometheus.MustNewConstMetric(m.updatesExportReceiveCountDesc, prometheus.GaugeValue, float64(p.ExportUpdates.Received), l...)
ch <- prometheus.MustNewConstMetric(m.updatesExportRejectCountDesc, prometheus.GaugeValue, float64(p.ExportUpdates.Rejected), l...)
ch <- prometheus.MustNewConstMetric(m.updatesExportFilterCountDesc, prometheus.GaugeValue, float64(p.ExportUpdates.Filtered), l...)
ch <- prometheus.MustNewConstMetric(m.updatesExportAcceptCountDesc, prometheus.GaugeValue, float64(p.ExportUpdates.Accepted), l...)
ch <- prometheus.MustNewConstMetric(m.updatesExportIgnoreCountDesc, prometheus.GaugeValue, float64(p.ExportUpdates.Ignored), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportReceiveCountDesc, prometheus.GaugeValue, float64(p.ImportWithdraws.Received), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportRejectCountDesc, prometheus.GaugeValue, float64(p.ImportWithdraws.Rejected), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportFilterCountDesc, prometheus.GaugeValue, float64(p.ImportWithdraws.Filtered), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportAcceptCountDesc, prometheus.GaugeValue, float64(p.ImportWithdraws.Accepted), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsImportIgnoreCountDesc, prometheus.GaugeValue, float64(p.ImportWithdraws.Ignored), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportReceiveCountDesc, prometheus.GaugeValue, float64(p.ExportWithdraws.Received), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportRejectCountDesc, prometheus.GaugeValue, float64(p.ExportWithdraws.Rejected), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportFilterCountDesc, prometheus.GaugeValue, float64(p.ExportWithdraws.Filtered), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportAcceptCountDesc, prometheus.GaugeValue, float64(p.ExportWithdraws.Accepted), l...)
ch <- prometheus.MustNewConstMetric(m.withdrawsExportIgnoreCountDesc, prometheus.GaugeValue, float64(p.ExportWithdraws.Ignored), l...)
}

View File

@ -0,0 +1,8 @@
package metrics
import "github.com/czerwonk/bird_exporter/protocol"
type LabelStrategy interface {
labelNames() []string
labelValues(p *protocol.Protocol) []string
}

View File

@ -0,0 +1,31 @@
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/czerwonk/bird_exporter/protocol"
)
type LegacyMetricExporter struct {
ipv4Exporter *GenericProtocolMetricExporter
ipv6Exporter *GenericProtocolMetricExporter
}
func NewLegacyMetricExporter(prefixIpv4, prefixIpv6 string, labelStrategy LabelStrategy) MetricExporter {
return &LegacyMetricExporter {
ipv4Exporter: NewGenericProtocolMetricExporter(prefixIpv4, false, labelStrategy),
ipv6Exporter: NewGenericProtocolMetricExporter(prefixIpv6, false, labelStrategy),
}
}
func (e *LegacyMetricExporter) Describe(ch chan<- *prometheus.Desc) {
e.ipv4Exporter.Describe(ch)
e.ipv6Exporter.Describe(ch)
}
func (e *LegacyMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
if p.IpVersion == 4 {
e.ipv4Exporter.Export(p, ch)
} else {
e.ipv6Exporter.Export(p, ch)
}
}

View File

@ -0,0 +1,14 @@
package metrics
import "github.com/czerwonk/bird_exporter/protocol"
type LegacyLabelStrategy struct {
}
func (*LegacyLabelStrategy) labelNames() []string {
return []string{"name"}
}
func (*LegacyLabelStrategy) labelValues(p *protocol.Protocol) []string {
return []string{p.Name}
}

View File

@ -0,0 +1,11 @@
package metrics
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
type MetricExporter interface {
Describe(ch chan<- *prometheus.Desc)
Export(p *protocol.Protocol, ch chan<- prometheus.Metric)
}

View File

@ -3,26 +3,23 @@ package ospf
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
"github.com/czerwonk/bird_exporter/metrics"
)
var descriptions map[int]*desc
var exporter map[int]*protocol.GenericProtocolMetricExporter
type desc struct {
runningDesc *prometheus.Desc
}
type OspfMetricExporter struct {
type ospfMetricExporter struct {
descriptions map[int]*desc
}
func init() {
exporter = make(map[int]*protocol.GenericProtocolMetricExporter)
exporter[4] = protocol.NewGenericProtocolMetricExporter("ospf")
exporter[6] = protocol.NewGenericProtocolMetricExporter("ospfv3")
func NewExporter(prefix string) metrics.MetricExporter {
d := make(map[int]*desc)
d[4] = getDesc(prefix+"ospf")
d[6] = getDesc(prefix+"ospfv3")
descriptions = make(map[int]*desc)
descriptions[4] = getDesc("ospf")
descriptions[6] = getDesc("ospfv3")
return &ospfMetricExporter{descriptions: d}
}
func getDesc(prefix string) *desc {
@ -34,14 +31,11 @@ func getDesc(prefix string) *desc {
return d
}
func (*OspfMetricExporter) Describe(ch chan<- *prometheus.Desc) {
exporter[4].Describe(ch)
exporter[6].Describe(ch)
ch <- descriptions[4].runningDesc
ch <- descriptions[6].runningDesc
func (m *ospfMetricExporter) Describe(ch chan<- *prometheus.Desc) {
ch <- m.descriptions[4].runningDesc
ch <- m.descriptions[6].runningDesc
}
func (*OspfMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
exporter[p.IpVersion].Export(p, ch)
ch <- prometheus.MustNewConstMetric(descriptions[p.IpVersion].runningDesc, prometheus.GaugeValue, p.Attributes["running"], p.Name)
func (m *ospfMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(m.descriptions[p.IpVersion].runningDesc, prometheus.GaugeValue, p.Attributes["running"], p.Name)
}

View File

@ -1,4 +1,4 @@
package main
package parser
import (
"bufio"
@ -27,7 +27,8 @@ func init() {
routeChangeRegex = regexp.MustCompile("(Import|Export) (updates|withdraws):\\s+(\\d+|---)\\s+(\\d+|---)\\s+(\\d+|---)\\s+(\\d+|---)\\s+(\\d+|---)\\s*")
}
func parseOutput(data []byte, ipVersion int) []*protocol.Protocol {
// Parser parses bird output and returns protocol.Protocol structs
func Parse(data []byte, ipVersion int) []*protocol.Protocol {
protocols := make([]*protocol.Protocol, 0)
reader := bytes.NewReader(data)

View File

@ -5,11 +5,12 @@ import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/czerwonk/testutils/assert"
"github.com/czerwonk/bird_exporter/parser"
)
func TestEstablishedBgpOldTimeFormat(t *testing.T) {
data := "foo BGP master up 1481973060 Established\ntest\nbar\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -25,7 +26,7 @@ func TestEstablishedBgpOldTimeFormat(t *testing.T) {
func TestEstablishedBgpCurrentTimeFormat(t *testing.T) {
data := "foo BGP master up 00:01:00 Established\ntest\nbar\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -42,7 +43,7 @@ func TestEstablishedBgpCurrentTimeFormat(t *testing.T) {
func TestIpv6Bgp(t *testing.T) {
data := "foo BGP master up 00:01:00 Established\ntest\nbar\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 6)
p := parser.Parse([]byte(data), 6)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -51,7 +52,7 @@ func TestIpv6Bgp(t *testing.T) {
func TestActiveBgp(t *testing.T) {
data := "bar BGP master start 2016-01-01 Active\ntest\nbar"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -66,7 +67,7 @@ func TestActiveBgp(t *testing.T) {
func Test2BgpSessions(t *testing.T) {
data := "foo BGP master up 00:01:00 Established\ntest\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nbar BGP master start 2016-01-01 Active\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 2, len(p), t)
}
@ -78,7 +79,7 @@ func TestUpdateAndWithdrawCounts(t *testing.T) {
" Import withdraws: 6 7 8 9 10\n" +
" Export updates: 11 12 13 14 15\n" +
" Export withdraws: 16 17 18 19 ---"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
x := p[0]
assert.Int64Equal("import updates received", 1, x.ImportUpdates.Received, t)
@ -105,7 +106,7 @@ func TestUpdateAndWithdrawCounts(t *testing.T) {
func TestOspfOldTimeFormat(t *testing.T) {
data := "ospf1 OSPF master up 1481973060 Running\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -120,7 +121,7 @@ func TestOspfOldTimeFormat(t *testing.T) {
func TestOspfCurrentTimeFormat(t *testing.T) {
data := "ospf1 OSPF master up 00:01:00 Running\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -136,7 +137,7 @@ func TestOspfCurrentTimeFormat(t *testing.T) {
func TestOspfProtocolDown(t *testing.T) {
data := "o_hrz OSPF t_hrz down 1494926415 \n Preference: 150\n Input filter: ACCEPT\n Output filter: REJECT\nxxx"
p := parseOutput([]byte(data), 6)
p := parser.Parse([]byte(data), 6)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -150,7 +151,7 @@ func TestOspfProtocolDown(t *testing.T) {
func TestOspfRunning(t *testing.T) {
data := "ospf1 OSPF master up 00:01:00 Running\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]
@ -159,7 +160,7 @@ func TestOspfRunning(t *testing.T) {
func TestOspfAlone(t *testing.T) {
data := "ospf1 OSPF master up 00:01:00 Alone\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
p := parseOutput([]byte(data), 4)
p := parser.Parse([]byte(data), 4)
assert.IntEqual("protocols", 1, len(p), t)
x := p[0]

View File

@ -4,10 +4,10 @@ const (
PROTO_UNKNOWN = 0
BGP = 1
OSPF = 2
Kernel = 3
Static = 4
Direct = 5
Device = 6
Kernel = 4
Static = 8
Direct = 16
Device = 32
)
type Protocol struct {

View File

@ -1,26 +0,0 @@
package static
import (
"github.com/czerwonk/bird_exporter/protocol"
"github.com/prometheus/client_golang/prometheus"
)
var exporter map[int]*protocol.GenericProtocolMetricExporter
type StaticMetricExporter struct {
}
func init() {
exporter = make(map[int]*protocol.GenericProtocolMetricExporter)
exporter[4] = protocol.NewGenericProtocolMetricExporter("static4")
exporter[6] = protocol.NewGenericProtocolMetricExporter("static6")
}
func (m *StaticMetricExporter) Describe(ch chan<- *prometheus.Desc) {
exporter[4].Describe(ch)
exporter[6].Describe(ch)
}
func (m *StaticMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
exporter[p.IpVersion].Export(p, ch)
}