diff options
author | Sudhar287 <sudhar287@gmail.com> | 2020-05-13 15:06:00 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-13 21:06:00 +0200 |
commit | 6807e5319bcc8698e0acbe0a04b7f139e5bac8ee (patch) | |
tree | 7066b93fb31bc181cc3a7254ad73113c8a48bdb7 | |
parent | f87e566df9c790938be2c6e5a64f7b58ea0cefb9 (diff) | |
download | prometheus_node_collector-6807e5319bcc8698e0acbe0a04b7f139e5bac8ee.tar.bz2 prometheus_node_collector-6807e5319bcc8698e0acbe0a04b7f139e5bac8ee.tar.xz prometheus_node_collector-6807e5319bcc8698e0acbe0a04b7f139e5bac8ee.zip |
read contents of objset file (#1632)
* added objread functionality
Signed-off-by: Sudharshann D <sudhar287@gmail.com>
-rw-r--r-- | collector/fixtures/e2e-64k-page-output.txt | 36 | ||||
-rw-r--r-- | collector/fixtures/e2e-output.txt | 36 | ||||
-rw-r--r-- | collector/fixtures/proc/spl/kstat/zfs/pool1/objset-1 | 9 | ||||
-rw-r--r-- | collector/fixtures/proc/spl/kstat/zfs/pool1/objset-2 | 9 | ||||
-rw-r--r-- | collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-1 | 9 | ||||
-rw-r--r-- | collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-2 | 9 | ||||
-rw-r--r-- | collector/zfs.go | 31 | ||||
-rw-r--r-- | collector/zfs_linux.go | 65 | ||||
-rw-r--r-- | collector/zfs_linux_test.go | 40 |
9 files changed, 238 insertions, 6 deletions
diff --git a/collector/fixtures/e2e-64k-page-output.txt b/collector/fixtures/e2e-64k-page-output.txt index 0ea506b..3e9f6cb 100644 --- a/collector/fixtures/e2e-64k-page-output.txt +++ b/collector/fixtures/e2e-64k-page-output.txt | |||
@@ -3584,6 +3584,42 @@ node_zfs_zil_zil_itx_needcopy_bytes 1.8446744073709537e+19 | |||
3584 | # HELP node_zfs_zil_zil_itx_needcopy_count kstat.zfs.misc.zil.zil_itx_needcopy_count | 3584 | # HELP node_zfs_zil_zil_itx_needcopy_count kstat.zfs.misc.zil.zil_itx_needcopy_count |
3585 | # TYPE node_zfs_zil_zil_itx_needcopy_count untyped | 3585 | # TYPE node_zfs_zil_zil_itx_needcopy_count untyped |
3586 | node_zfs_zil_zil_itx_needcopy_count 0 | 3586 | 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 | ||
3587 | # HELP node_zfs_zpool_nread kstat.zfs.misc.io.nread | 3623 | # HELP node_zfs_zpool_nread kstat.zfs.misc.io.nread |
3588 | # TYPE node_zfs_zpool_nread untyped | 3624 | # TYPE node_zfs_zpool_nread untyped |
3589 | node_zfs_zpool_nread{zpool="pool1"} 1.88416e+06 | 3625 | node_zfs_zpool_nread{zpool="pool1"} 1.88416e+06 |
diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index 5a2ba25..df04679 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt | |||
@@ -3677,6 +3677,42 @@ node_zfs_zil_zil_itx_needcopy_bytes 1.8446744073709537e+19 | |||
3677 | # HELP node_zfs_zil_zil_itx_needcopy_count kstat.zfs.misc.zil.zil_itx_needcopy_count | 3677 | # HELP node_zfs_zil_zil_itx_needcopy_count kstat.zfs.misc.zil.zil_itx_needcopy_count |
3678 | # TYPE node_zfs_zil_zil_itx_needcopy_count untyped | 3678 | # TYPE node_zfs_zil_zil_itx_needcopy_count untyped |
3679 | node_zfs_zil_zil_itx_needcopy_count 0 | 3679 | 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 | ||
3680 | # HELP node_zfs_zpool_nread kstat.zfs.misc.io.nread | 3716 | # HELP node_zfs_zpool_nread kstat.zfs.misc.io.nread |
3681 | # TYPE node_zfs_zpool_nread untyped | 3717 | # TYPE node_zfs_zpool_nread untyped |
3682 | node_zfs_zpool_nread{zpool="pool1"} 1.88416e+06 | 3718 | node_zfs_zpool_nread{zpool="pool1"} 1.88416e+06 |
diff --git a/collector/fixtures/proc/spl/kstat/zfs/pool1/objset-1 b/collector/fixtures/proc/spl/kstat/zfs/pool1/objset-1 new file mode 100644 index 0000000..28a9d2e --- /dev/null +++ b/collector/fixtures/proc/spl/kstat/zfs/pool1/objset-1 | |||
@@ -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 | ||
diff --git a/collector/fixtures/proc/spl/kstat/zfs/pool1/objset-2 b/collector/fixtures/proc/spl/kstat/zfs/pool1/objset-2 new file mode 100644 index 0000000..79ee31d --- /dev/null +++ b/collector/fixtures/proc/spl/kstat/zfs/pool1/objset-2 | |||
@@ -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 | ||
diff --git a/collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-1 b/collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-1 new file mode 100644 index 0000000..189b655 --- /dev/null +++ b/collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-1 | |||
@@ -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 \ No newline at end of file | ||
diff --git a/collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-2 b/collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-2 new file mode 100644 index 0000000..3d44623 --- /dev/null +++ b/collector/fixtures/proc/spl/kstat/zfs/poolz1/objset-2 | |||
@@ -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 \ No newline at end of file | ||
diff --git a/collector/zfs.go b/collector/zfs.go index 093ded5..b530e35 100644 --- a/collector/zfs.go +++ b/collector/zfs.go | |||
@@ -34,17 +34,19 @@ func init() { | |||
34 | } | 34 | } |
35 | 35 | ||
36 | type zfsCollector struct { | 36 | type zfsCollector struct { |
37 | linuxProcpathBase string | 37 | linuxProcpathBase string |
38 | linuxZpoolIoPath string | 38 | linuxZpoolIoPath string |
39 | linuxPathMap map[string]string | 39 | linuxZpoolObjsetPath string |
40 | logger log.Logger | 40 | linuxPathMap map[string]string |
41 | logger log.Logger | ||
41 | } | 42 | } |
42 | 43 | ||
43 | // NewZFSCollector returns a new Collector exposing ZFS statistics. | 44 | // NewZFSCollector returns a new Collector exposing ZFS statistics. |
44 | func NewZFSCollector(logger log.Logger) (Collector, error) { | 45 | func NewZFSCollector(logger log.Logger) (Collector, error) { |
45 | return &zfsCollector{ | 46 | return &zfsCollector{ |
46 | linuxProcpathBase: "spl/kstat/zfs", | 47 | linuxProcpathBase: "spl/kstat/zfs", |
47 | linuxZpoolIoPath: "/*/io", | 48 | linuxZpoolIoPath: "/*/io", |
49 | linuxZpoolObjsetPath: "/*/objset-*", | ||
48 | linuxPathMap: map[string]string{ | 50 | linuxPathMap: map[string]string{ |
49 | "zfs_abd": "abdstats", | 51 | "zfs_abd": "abdstats", |
50 | "zfs_arc": "arcstats", | 52 | "zfs_arc": "arcstats", |
@@ -113,3 +115,20 @@ func (c *zfsCollector) constPoolMetric(poolName string, sysctl zfsSysctl, value | |||
113 | poolName, | 115 | poolName, |
114 | ) | 116 | ) |
115 | } | 117 | } |
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 | } | ||
diff --git a/collector/zfs_linux.go b/collector/zfs_linux.go index aa27db8..e2c9749 100644 --- a/collector/zfs_linux.go +++ b/collector/zfs_linux.go | |||
@@ -90,6 +90,31 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error { | |||
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
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 | } | ||
93 | return nil | 118 | return nil |
94 | } | 119 | } |
95 | 120 | ||
@@ -168,3 +193,43 @@ func (c *zfsCollector) parsePoolProcfsFile(reader io.Reader, zpoolPath string, h | |||
168 | 193 | ||
169 | return scanner.Err() | 194 | return scanner.Err() |
170 | } | 195 | } |
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 | } | ||
diff --git a/collector/zfs_linux_test.go b/collector/zfs_linux_test.go index 3574858..29d28e8 100644 --- a/collector/zfs_linux_test.go +++ b/collector/zfs_linux_test.go | |||
@@ -311,6 +311,46 @@ func TestZpoolParsing(t *testing.T) { | |||
311 | } | 311 | } |
312 | } | 312 | } |
313 | 313 | ||
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 | |||
314 | func TestAbdstatsParsing(t *testing.T) { | 354 | func TestAbdstatsParsing(t *testing.T) { |
315 | abdstatsFile, err := os.Open("fixtures/proc/spl/kstat/zfs/abdstats") | 355 | abdstatsFile, err := os.Open("fixtures/proc/spl/kstat/zfs/abdstats") |
316 | if err != nil { | 356 | if err != nil { |