Skip to content

Commit 6807e53

Browse files
authored
read contents of objset file (prometheus#1632)
* added objread functionality Signed-off-by: Sudharshann D <sudhar287@gmail.com>
1 parent f87e566 commit 6807e53

9 files changed

Lines changed: 238 additions & 6 deletions

File tree

collector/fixtures/e2e-64k-page-output.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3584,6 +3584,42 @@ node_zfs_zil_zil_itx_needcopy_bytes 1.8446744073709537e+19
35843584
# HELP node_zfs_zil_zil_itx_needcopy_count kstat.zfs.misc.zil.zil_itx_needcopy_count
35853585
# TYPE node_zfs_zil_zil_itx_needcopy_count untyped
35863586
node_zfs_zil_zil_itx_needcopy_count 0
3587+
# HELP node_zfs_zpool_dataset_nread kstat.zfs.misc.objset.nread
3588+
# TYPE node_zfs_zpool_dataset_nread untyped
3589+
node_zfs_zpool_dataset_nread{dataset="pool1",zpool="pool1"} 0
3590+
node_zfs_zpool_dataset_nread{dataset="pool1/dataset1",zpool="pool1"} 28
3591+
node_zfs_zpool_dataset_nread{dataset="poolz1",zpool="poolz1"} 0
3592+
node_zfs_zpool_dataset_nread{dataset="poolz1/dataset1",zpool="poolz1"} 28
3593+
# HELP node_zfs_zpool_dataset_nunlinked kstat.zfs.misc.objset.nunlinked
3594+
# TYPE node_zfs_zpool_dataset_nunlinked untyped
3595+
node_zfs_zpool_dataset_nunlinked{dataset="pool1",zpool="pool1"} 0
3596+
node_zfs_zpool_dataset_nunlinked{dataset="pool1/dataset1",zpool="pool1"} 3
3597+
node_zfs_zpool_dataset_nunlinked{dataset="poolz1",zpool="poolz1"} 0
3598+
node_zfs_zpool_dataset_nunlinked{dataset="poolz1/dataset1",zpool="poolz1"} 14
3599+
# HELP node_zfs_zpool_dataset_nunlinks kstat.zfs.misc.objset.nunlinks
3600+
# TYPE node_zfs_zpool_dataset_nunlinks untyped
3601+
node_zfs_zpool_dataset_nunlinks{dataset="pool1",zpool="pool1"} 0
3602+
node_zfs_zpool_dataset_nunlinks{dataset="pool1/dataset1",zpool="pool1"} 3
3603+
node_zfs_zpool_dataset_nunlinks{dataset="poolz1",zpool="poolz1"} 0
3604+
node_zfs_zpool_dataset_nunlinks{dataset="poolz1/dataset1",zpool="poolz1"} 14
3605+
# HELP node_zfs_zpool_dataset_nwritten kstat.zfs.misc.objset.nwritten
3606+
# TYPE node_zfs_zpool_dataset_nwritten untyped
3607+
node_zfs_zpool_dataset_nwritten{dataset="pool1",zpool="pool1"} 0
3608+
node_zfs_zpool_dataset_nwritten{dataset="pool1/dataset1",zpool="pool1"} 12302
3609+
node_zfs_zpool_dataset_nwritten{dataset="poolz1",zpool="poolz1"} 0
3610+
node_zfs_zpool_dataset_nwritten{dataset="poolz1/dataset1",zpool="poolz1"} 32806
3611+
# HELP node_zfs_zpool_dataset_reads kstat.zfs.misc.objset.reads
3612+
# TYPE node_zfs_zpool_dataset_reads untyped
3613+
node_zfs_zpool_dataset_reads{dataset="pool1",zpool="pool1"} 0
3614+
node_zfs_zpool_dataset_reads{dataset="pool1/dataset1",zpool="pool1"} 2
3615+
node_zfs_zpool_dataset_reads{dataset="poolz1",zpool="poolz1"} 0
3616+
node_zfs_zpool_dataset_reads{dataset="poolz1/dataset1",zpool="poolz1"} 2
3617+
# HELP node_zfs_zpool_dataset_writes kstat.zfs.misc.objset.writes
3618+
# TYPE node_zfs_zpool_dataset_writes untyped
3619+
node_zfs_zpool_dataset_writes{dataset="pool1",zpool="pool1"} 0
3620+
node_zfs_zpool_dataset_writes{dataset="pool1/dataset1",zpool="pool1"} 4
3621+
node_zfs_zpool_dataset_writes{dataset="poolz1",zpool="poolz1"} 0
3622+
node_zfs_zpool_dataset_writes{dataset="poolz1/dataset1",zpool="poolz1"} 10
35873623
# HELP node_zfs_zpool_nread kstat.zfs.misc.io.nread
35883624
# TYPE node_zfs_zpool_nread untyped
35893625
node_zfs_zpool_nread{zpool="pool1"} 1.88416e+06

collector/fixtures/e2e-output.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3677,6 +3677,42 @@ node_zfs_zil_zil_itx_needcopy_bytes 1.8446744073709537e+19
36773677
# HELP node_zfs_zil_zil_itx_needcopy_count kstat.zfs.misc.zil.zil_itx_needcopy_count
36783678
# TYPE node_zfs_zil_zil_itx_needcopy_count untyped
36793679
node_zfs_zil_zil_itx_needcopy_count 0
3680+
# HELP node_zfs_zpool_dataset_nread kstat.zfs.misc.objset.nread
3681+
# TYPE node_zfs_zpool_dataset_nread untyped
3682+
node_zfs_zpool_dataset_nread{dataset="pool1",zpool="pool1"} 0
3683+
node_zfs_zpool_dataset_nread{dataset="pool1/dataset1",zpool="pool1"} 28
3684+
node_zfs_zpool_dataset_nread{dataset="poolz1",zpool="poolz1"} 0
3685+
node_zfs_zpool_dataset_nread{dataset="poolz1/dataset1",zpool="poolz1"} 28
3686+
# HELP node_zfs_zpool_dataset_nunlinked kstat.zfs.misc.objset.nunlinked
3687+
# TYPE node_zfs_zpool_dataset_nunlinked untyped
3688+
node_zfs_zpool_dataset_nunlinked{dataset="pool1",zpool="pool1"} 0
3689+
node_zfs_zpool_dataset_nunlinked{dataset="pool1/dataset1",zpool="pool1"} 3
3690+
node_zfs_zpool_dataset_nunlinked{dataset="poolz1",zpool="poolz1"} 0
3691+
node_zfs_zpool_dataset_nunlinked{dataset="poolz1/dataset1",zpool="poolz1"} 14
3692+
# HELP node_zfs_zpool_dataset_nunlinks kstat.zfs.misc.objset.nunlinks
3693+
# TYPE node_zfs_zpool_dataset_nunlinks untyped
3694+
node_zfs_zpool_dataset_nunlinks{dataset="pool1",zpool="pool1"} 0
3695+
node_zfs_zpool_dataset_nunlinks{dataset="pool1/dataset1",zpool="pool1"} 3
3696+
node_zfs_zpool_dataset_nunlinks{dataset="poolz1",zpool="poolz1"} 0
3697+
node_zfs_zpool_dataset_nunlinks{dataset="poolz1/dataset1",zpool="poolz1"} 14
3698+
# HELP node_zfs_zpool_dataset_nwritten kstat.zfs.misc.objset.nwritten
3699+
# TYPE node_zfs_zpool_dataset_nwritten untyped
3700+
node_zfs_zpool_dataset_nwritten{dataset="pool1",zpool="pool1"} 0
3701+
node_zfs_zpool_dataset_nwritten{dataset="pool1/dataset1",zpool="pool1"} 12302
3702+
node_zfs_zpool_dataset_nwritten{dataset="poolz1",zpool="poolz1"} 0
3703+
node_zfs_zpool_dataset_nwritten{dataset="poolz1/dataset1",zpool="poolz1"} 32806
3704+
# HELP node_zfs_zpool_dataset_reads kstat.zfs.misc.objset.reads
3705+
# TYPE node_zfs_zpool_dataset_reads untyped
3706+
node_zfs_zpool_dataset_reads{dataset="pool1",zpool="pool1"} 0
3707+
node_zfs_zpool_dataset_reads{dataset="pool1/dataset1",zpool="pool1"} 2
3708+
node_zfs_zpool_dataset_reads{dataset="poolz1",zpool="poolz1"} 0
3709+
node_zfs_zpool_dataset_reads{dataset="poolz1/dataset1",zpool="poolz1"} 2
3710+
# HELP node_zfs_zpool_dataset_writes kstat.zfs.misc.objset.writes
3711+
# TYPE node_zfs_zpool_dataset_writes untyped
3712+
node_zfs_zpool_dataset_writes{dataset="pool1",zpool="pool1"} 0
3713+
node_zfs_zpool_dataset_writes{dataset="pool1/dataset1",zpool="pool1"} 4
3714+
node_zfs_zpool_dataset_writes{dataset="poolz1",zpool="poolz1"} 0
3715+
node_zfs_zpool_dataset_writes{dataset="poolz1/dataset1",zpool="poolz1"} 10
36803716
# HELP node_zfs_zpool_nread kstat.zfs.misc.io.nread
36813717
# TYPE node_zfs_zpool_nread untyped
36823718
node_zfs_zpool_nread{zpool="pool1"} 1.88416e+06
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
23 1 0x01 7 2160 221578688875 6665999035587
2+
name type data
3+
dataset_name 7 pool1
4+
writes 4 0
5+
nwritten 4 0
6+
reads 4 0
7+
nread 4 0
8+
nunlinks 4 0
9+
nunlinked 4 0
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
24 1 0x01 7 2160 221611904716 7145015038451
2+
name type data
3+
dataset_name 7 pool1/dataset1
4+
writes 4 4
5+
nwritten 4 12302
6+
reads 4 2
7+
nread 4 28
8+
nunlinks 4 3
9+
nunlinked 4 3
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
30 1 0x01 7 2160 217993779684 2621674546179
2+
name type data
3+
dataset_name 7 poolz1
4+
writes 4 0
5+
nwritten 4 0
6+
reads 4 0
7+
nread 4 0
8+
nunlinks 4 0
9+
nunlinked 4 0
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
31 1 0x01 7 2160 218133979890 3024169078920
2+
name type data
3+
dataset_name 7 poolz1/dataset1
4+
writes 4 10
5+
nwritten 4 32806
6+
reads 4 2
7+
nread 4 28
8+
nunlinks 4 14
9+
nunlinked 4 14

collector/zfs.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,19 @@ func init() {
3434
}
3535

3636
type zfsCollector struct {
37-
linuxProcpathBase string
38-
linuxZpoolIoPath string
39-
linuxPathMap map[string]string
40-
logger log.Logger
37+
linuxProcpathBase string
38+
linuxZpoolIoPath string
39+
linuxZpoolObjsetPath string
40+
linuxPathMap map[string]string
41+
logger log.Logger
4142
}
4243

4344
// NewZFSCollector returns a new Collector exposing ZFS statistics.
4445
func NewZFSCollector(logger log.Logger) (Collector, error) {
4546
return &zfsCollector{
46-
linuxProcpathBase: "spl/kstat/zfs",
47-
linuxZpoolIoPath: "/*/io",
47+
linuxProcpathBase: "spl/kstat/zfs",
48+
linuxZpoolIoPath: "/*/io",
49+
linuxZpoolObjsetPath: "/*/objset-*",
4850
linuxPathMap: map[string]string{
4951
"zfs_abd": "abdstats",
5052
"zfs_arc": "arcstats",
@@ -113,3 +115,20 @@ func (c *zfsCollector) constPoolMetric(poolName string, sysctl zfsSysctl, value
113115
poolName,
114116
)
115117
}
118+
119+
func (c *zfsCollector) constPoolObjsetMetric(poolName string, datasetName string, sysctl zfsSysctl, value uint64) prometheus.Metric {
120+
metricName := sysctl.metricName()
121+
122+
return prometheus.MustNewConstMetric(
123+
prometheus.NewDesc(
124+
prometheus.BuildFQName(namespace, "zfs_zpool_dataset", metricName),
125+
string(sysctl),
126+
[]string{"zpool", "dataset"},
127+
nil,
128+
),
129+
prometheus.UntypedValue,
130+
float64(value),
131+
poolName,
132+
datasetName,
133+
)
134+
}

collector/zfs_linux.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,31 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
9090
}
9191
}
9292

93+
zpoolObjsetPaths, err := filepath.Glob(procFilePath(filepath.Join(c.linuxProcpathBase, c.linuxZpoolObjsetPath)))
94+
if err != nil {
95+
return err
96+
}
97+
98+
if zpoolObjsetPaths == nil {
99+
return nil
100+
}
101+
102+
for _, zpoolPath := range zpoolObjsetPaths {
103+
file, err := os.Open(zpoolPath)
104+
if err != nil {
105+
// this file should exist, but there is a race where an exporting pool can remove the files -- ok to ignore
106+
level.Debug(c.logger).Log("msg", "Cannot open file for reading", "path", zpoolPath)
107+
return errZFSNotAvailable
108+
}
109+
110+
err = c.parsePoolObjsetFile(file, zpoolPath, func(poolName string, datasetName string, s zfsSysctl, v uint64) {
111+
ch <- c.constPoolObjsetMetric(poolName, datasetName, s, v)
112+
})
113+
file.Close()
114+
if err != nil {
115+
return err
116+
}
117+
}
93118
return nil
94119
}
95120

@@ -168,3 +193,43 @@ func (c *zfsCollector) parsePoolProcfsFile(reader io.Reader, zpoolPath string, h
168193

169194
return scanner.Err()
170195
}
196+
197+
func (c *zfsCollector) parsePoolObjsetFile(reader io.Reader, zpoolPath string, handler func(string, string, zfsSysctl, uint64)) error {
198+
scanner := bufio.NewScanner(reader)
199+
200+
parseLine := false
201+
var zpoolName, datasetName string
202+
for scanner.Scan() {
203+
parts := strings.Fields(scanner.Text())
204+
205+
if !parseLine && len(parts) == 3 && parts[0] == "name" && parts[1] == "type" && parts[2] == "data" {
206+
parseLine = true
207+
continue
208+
}
209+
210+
if !parseLine || len(parts) < 3 {
211+
continue
212+
}
213+
if parts[0] == "dataset_name" {
214+
zpoolPathElements := strings.Split(zpoolPath, "/")
215+
pathLen := len(zpoolPathElements)
216+
zpoolName = zpoolPathElements[pathLen-2]
217+
datasetName = parts[2]
218+
continue
219+
}
220+
221+
if parts[1] == kstatDataUint64 {
222+
key := fmt.Sprintf("kstat.zfs.misc.objset.%s", parts[0])
223+
value, err := strconv.ParseUint(parts[2], 10, 64)
224+
if err != nil {
225+
return fmt.Errorf("could not parse expected integer value for %q", key)
226+
}
227+
handler(zpoolName, datasetName, zfsSysctl(key), value)
228+
}
229+
}
230+
if !parseLine {
231+
return fmt.Errorf("did not parse a single %s %s metric", zpoolName, datasetName)
232+
}
233+
234+
return scanner.Err()
235+
}

collector/zfs_linux_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,46 @@ func TestZpoolParsing(t *testing.T) {
311311
}
312312
}
313313

314+
func TestZpoolObjsetParsing(t *testing.T) {
315+
zpoolPaths, err := filepath.Glob("fixtures/proc/spl/kstat/zfs/*/objset-*")
316+
if err != nil {
317+
t.Fatal(err)
318+
}
319+
320+
c := zfsCollector{}
321+
if err != nil {
322+
t.Fatal(err)
323+
}
324+
325+
handlerCalled := false
326+
for _, zpoolPath := range zpoolPaths {
327+
file, err := os.Open(zpoolPath)
328+
if err != nil {
329+
t.Fatal(err)
330+
}
331+
332+
err = c.parsePoolObjsetFile(file, zpoolPath, func(poolName string, datasetName string, s zfsSysctl, v uint64) {
333+
if s != zfsSysctl("kstat.zfs.misc.objset.writes") {
334+
return
335+
}
336+
337+
handlerCalled = true
338+
339+
if v != uint64(0) && v != uint64(4) && v != uint64(10) {
340+
t.Fatalf("Incorrect value parsed from procfs data %v", v)
341+
}
342+
343+
})
344+
file.Close()
345+
if err != nil {
346+
t.Fatal(err)
347+
}
348+
}
349+
if !handlerCalled {
350+
t.Fatal("Zpool parsing handler was not called for some expected sysctls")
351+
}
352+
}
353+
314354
func TestAbdstatsParsing(t *testing.T) {
315355
abdstatsFile, err := os.Open("fixtures/proc/spl/kstat/zfs/abdstats")
316356
if err != nil {

0 commit comments

Comments
 (0)