Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add zone serial numbers as metrics #91

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const (
type Statistics struct {
Server Server
Views []View
ZoneViews []ZoneView
TaskManager TaskManager
}

Expand All @@ -114,6 +115,12 @@ type View struct {
ResolverQueries []Counter
}

// View represents statistics for a single BIND zone view.
type ZoneView struct {
Name string
ZoneData []ZoneCounter
}

// TaskManager contains information about all running tasks.
type TaskManager struct {
Tasks []Task `xml:"tasks>task"`
Expand All @@ -126,6 +133,12 @@ type Counter struct {
Counter uint64 `xml:",chardata"`
}

// Counter represents a single zone counter value.
type ZoneCounter struct {
Name string
Serial uint64
}

// Gauge represents a single gauge value.
type Gauge struct {
Name string `xml:"name"`
Expand Down
18 changes: 16 additions & 2 deletions bind/v2/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ type View struct {
Cache []bind.Gauge `xml:"cache>rrset"`
Rdtype []Counter `xml:"rdtype"`
Resstat []Counter `xml:"resstat"`
Zones []Counter `xml:"zones>zone"`
Zones []Zone `xml:"zones>zone"`
}

type Zone struct {
Name string `xml:"name"`
Rdataclass string `xml:"rdataclass"`
Serial string `xml:"serial"`
Serial uint64 `xml:"serial"`
}

type Counter struct {
Expand Down Expand Up @@ -107,12 +107,26 @@ func (c *Client) Stats(...bind.StatisticGroup) (bind.Statistics, error) {
Name: view.Name,
Cache: view.Cache,
}
zv := bind.ZoneView{
Name: view.Name,
}
for _, t := range view.Rdtype {
v.ResolverQueries = append(v.ResolverQueries, bind.Counter(t))
}
for _, t := range view.Resstat {
v.ResolverStats = append(v.ResolverStats, bind.Counter(t))
}
for _, zone := range view.Zones {
if zone.Rdataclass != "IN" {
continue
}
z := bind.ZoneCounter{
Name: zone.Name,
Serial: zone.Serial,
}
zv.ZoneData = append(zv.ZoneData, z)
}
s.ZoneViews = append(s.ZoneViews, zv)
s.Views = append(s.Views, v)
}
s.TaskManager = stats.Taskmgr
Expand Down
41 changes: 40 additions & 1 deletion bind/v3/v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const (
StatusPath = "/xml/v3/status"
// TasksPath is the HTTP path of the v3 tasks resource.
TasksPath = "/xml/v3/tasks"
// ZonesPath is the HTTP path of the v3 zones resource.
ZonesPath = "/xml/v3/zones"

nsstat = "nsstat"
opcode = "opcode"
Expand All @@ -44,6 +46,10 @@ type Statistics struct {
Views []View `xml:"views>view"`
}

type ZoneStatistics struct {
ZoneViews []ZoneView `xml:"views>view"`
}

type Server struct {
BootTime time.Time `xml:"boot-time"`
ConfigTime time.Time `xml:"config-time"`
Expand All @@ -54,7 +60,11 @@ type View struct {
Name string `xml:"name,attr"`
Cache []bind.Gauge `xml:"cache>rrset"`
Counters []Counters `xml:"counters"`
Zones struct{} `xml:"zones>zone"`
}

type ZoneView struct {
Name string `xml:"name,attr"`
Zones []ZoneCounter `xml:"zones>zone"`
}

type Counters struct {
Expand All @@ -67,6 +77,12 @@ type Counter struct {
Counter uint64 `xml:"counter"`
}

type ZoneCounter struct {
Name string `xml:"name,attr"`
Rdataclass string `xml:"rdataclass,attr"`
Serial uint64 `xml:"serial"`
}

// Client implements bind.Client and can be used to query a BIND v3 API.
type Client struct {
*bind.XMLClient
Expand All @@ -86,6 +102,7 @@ func (c *Client) Stats(groups ...bind.StatisticGroup) (bind.Statistics, error) {
}

var stats Statistics
var zonestats ZoneStatistics
if m[bind.ServerStats] || m[bind.ViewStats] {
if err := c.Get(ServerPath, &stats); err != nil {
return s, err
Expand Down Expand Up @@ -122,6 +139,28 @@ func (c *Client) Stats(groups ...bind.StatisticGroup) (bind.Statistics, error) {
s.Views = append(s.Views, v)
}
}

if err := c.Get(ZonesPath, &zonestats); err != nil {
return s, err
}

for _, view := range zonestats.ZoneViews {
v := bind.ZoneView{
Name: view.Name,
}
for _, zone := range view.Zones {
if zone.Rdataclass != "IN" {
continue
}
z := bind.ZoneCounter{
Name: zone.Name,
Serial: zone.Serial,
}
v.ZoneData = append(v.ZoneData, z)
}
s.ZoneViews = append(s.ZoneViews, v)
}

if m[bind.TaskStats] {
if err := c.Get(TasksPath, &stats); err != nil {
return s, err
Expand Down
13 changes: 13 additions & 0 deletions bind_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ var (
"Total number of available worker threads.",
nil, nil,
)
zoneSerial = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "", "zone_serial"),
"Zone serial number.",
[]string{"view", "zone_name"}, nil,
)
)

type collectorConstructor func(*bind.Statistics) prometheus.Collector
Expand Down Expand Up @@ -327,6 +332,14 @@ func (c *viewCollector) Collect(ch chan<- prometheus.Metric) {
level.Warn(logger).Log("msg", "Error parsing RTT", "err", err)
}
}

for _, v := range c.stats.ZoneViews {
for _, z := range v.ZoneData {
ch <- prometheus.MustNewConstMetric(
zoneSerial, prometheus.CounterValue, float64(z.Serial), v.Name, z.Name,
)
}
}
}

type taskCollector struct {
Expand Down
2 changes: 2 additions & 0 deletions bind_exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var (
`bind_resolver_query_duration_seconds_bucket{view="_default",le="0.8"} 187375`,
`bind_resolver_query_duration_seconds_bucket{view="_default",le="1.6"} 188409`,
`bind_resolver_query_duration_seconds_bucket{view="_default",le="+Inf"} 227755`,
`bind_zone_serial{view="_default",zone_name="TEST_ZONE"} 123`,
}
taskStats = []string{
`bind_tasks_running 8`,
Expand Down Expand Up @@ -195,6 +196,7 @@ func newV3Server() *httptest.Server {
"/xml/v3/server": "fixtures/v3/server",
"/xml/v3/status": "fixtures/v3/status",
"/xml/v3/tasks": "fixtures/v3/tasks",
"/xml/v3/zones": "fixtures/v3/zones",
}
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if f, ok := m[r.RequestURI]; ok {
Expand Down
5 changes: 5 additions & 0 deletions fixtures/v2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<view>
<name>_default</name>
<zones>
<zone>
<name>TEST_ZONE</name>
<rdataclass>IN</rdataclass>
<serial>123</serial>
</zone>
<zone>
<name>0.in-addr.arpa/IN</name>
<rdataclass>IN</rdataclass>
Expand Down
14 changes: 14 additions & 0 deletions fixtures/v3/zones
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/bind9.xsl"?>
<statistics version="3.6">
<views>
<view name="_default">
<zones>
<zone name="TEST_ZONE" rdataclass="IN">
<type>builtin</type>
<serial>123</serial>
</zone>
</zones>
</view>
</views>
</statistics>