Skip to content

Commit 4fd03c3

Browse files
authored
Merge pull request #323 from stuartnelson3/dfly-devstat
Dragonfly devstat
2 parents 7a9aad0 + e589a2b commit 4fd03c3

File tree

2 files changed

+147
-1
lines changed

2 files changed

+147
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ vmstat | Exposes statistics from `/proc/vmstat`. | Linux
4141
Name | Description | OS
4242
---------|-------------|----
4343
bonding | Exposes the number of configured and active slaves of Linux bonding interfaces. | Linux
44-
devstat | Exposes device statistics | FreeBSD
44+
devstat | Exposes device statistics | Dragonfly, FreeBSD
4545
gmond | Exposes statistics from Ganglia. | _any_
4646
interrupts | Exposes detailed interrupts statistics. | Linux, OpenBSD
4747
ipvs | Exposes IPVS status from `/proc/net/ip_vs` and stats from `/proc/net/ip_vs_stats`. | Linux

collector/devstat_dragonfly.go

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright 2016 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
// +build !nodevstat
15+
16+
package collector
17+
18+
import (
19+
"errors"
20+
"fmt"
21+
22+
"github.com/prometheus/client_golang/prometheus"
23+
)
24+
25+
/*
26+
#cgo LDFLAGS: -ldevstat
27+
#include <devstat.h>
28+
#include <stdlib.h>
29+
#include <string.h>
30+
31+
typedef struct {
32+
char device[DEVSTAT_NAME_LEN];
33+
int unit;
34+
uint64_t bytes;
35+
uint64_t transfers;
36+
uint64_t blocks;
37+
} Stats;
38+
39+
int _get_ndevs() {
40+
struct statinfo current;
41+
int num_devices;
42+
43+
current.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo));
44+
if (current.dinfo == NULL)
45+
return -2;
46+
47+
checkversion();
48+
49+
if (getdevs(&current) == -1)
50+
return -1;
51+
52+
return current.dinfo->numdevs;
53+
}
54+
55+
Stats _get_stats(int i) {
56+
struct statinfo current;
57+
int num_devices;
58+
59+
current.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo));
60+
getdevs(&current);
61+
62+
num_devices = current.dinfo->numdevs;
63+
Stats stats;
64+
65+
uint64_t total_bytes, total_transfers, total_blocks;
66+
long double kb_per_transfer, transfers_per_second, mb_per_second, blocks_per_second, ms_per_transaction;
67+
68+
strcpy(stats.device, current.dinfo->devices[i].device_name);
69+
stats.unit = current.dinfo->devices[i].unit_number;
70+
compute_stats(&current.dinfo->devices[i],
71+
NULL,
72+
1.0,
73+
&total_bytes,
74+
&total_transfers,
75+
&total_blocks,
76+
&kb_per_transfer,
77+
&transfers_per_second,
78+
&mb_per_second,
79+
&blocks_per_second,
80+
&ms_per_transaction);
81+
82+
stats.bytes = total_bytes;
83+
stats.transfers = total_transfers;
84+
stats.blocks = total_blocks;
85+
86+
return stats;
87+
}
88+
*/
89+
import "C"
90+
91+
const (
92+
devstatSubsystem = "devstat"
93+
)
94+
95+
type devstatCollector struct {
96+
bytesDesc *prometheus.Desc
97+
transfersDesc *prometheus.Desc
98+
blocksDesc *prometheus.Desc
99+
}
100+
101+
func init() {
102+
Factories["devstat"] = NewDevstatCollector
103+
}
104+
105+
// Takes a prometheus registry and returns a new Collector exposing
106+
// Device stats.
107+
func NewDevstatCollector() (Collector, error) {
108+
return &devstatCollector{
109+
bytesDesc: prometheus.NewDesc(
110+
prometheus.BuildFQName(Namespace, devstatSubsystem, "bytes_total"),
111+
"The total number of bytes transferred for reads and writes on the device.",
112+
[]string{"device"}, nil,
113+
),
114+
transfersDesc: prometheus.NewDesc(
115+
prometheus.BuildFQName(Namespace, devstatSubsystem, "transfers_total"),
116+
"The total number of transactions completed.",
117+
[]string{"device"}, nil,
118+
),
119+
blocksDesc: prometheus.NewDesc(
120+
prometheus.BuildFQName(Namespace, devstatSubsystem, "blocks_total"),
121+
"The total number of bytes given in terms of the devices blocksize.",
122+
[]string{"device"}, nil,
123+
),
124+
}, nil
125+
}
126+
127+
func (c *devstatCollector) Update(ch chan<- prometheus.Metric) (err error) {
128+
count := C._get_ndevs()
129+
if count == -1 {
130+
return errors.New("getdevs() failed")
131+
}
132+
if count == -2 {
133+
return errors.New("calloc() failed")
134+
}
135+
136+
for i := C.int(0); i < count; i++ {
137+
stats := C._get_stats(i)
138+
device := fmt.Sprintf("%s%d", C.GoString(&stats.device[0]), stats.unit)
139+
140+
ch <- prometheus.MustNewConstMetric(c.bytesDesc, prometheus.CounterValue, float64(stats.bytes), device)
141+
ch <- prometheus.MustNewConstMetric(c.transfersDesc, prometheus.CounterValue, float64(stats.transfers), device)
142+
ch <- prometheus.MustNewConstMetric(c.blocksDesc, prometheus.CounterValue, float64(stats.blocks), device)
143+
}
144+
145+
return err
146+
}

0 commit comments

Comments
 (0)