| 212 | } |
| 213 | |
| 214 | func (c *zfsCollector) parseProcfsFile(reader io.Reader, fmtExt string, handler func(zfsSysctl, any)) error { |
| 215 | scanner := bufio.NewScanner(reader) |
| 216 | |
| 217 | parseLine := false |
| 218 | for scanner.Scan() { |
| 219 | parts := strings.Fields(scanner.Text()) |
| 220 | |
| 221 | if !parseLine && len(parts) == 3 && parts[0] == "name" && parts[1] == "type" && parts[2] == "data" { |
| 222 | // Start parsing from here. |
| 223 | parseLine = true |
| 224 | continue |
| 225 | } |
| 226 | |
| 227 | if !parseLine || len(parts) < 3 { |
| 228 | continue |
| 229 | } |
| 230 | |
| 231 | // kstat data type (column 2) should be KSTAT_DATA_UINT64, otherwise ignore |
| 232 | // TODO: when other KSTAT_DATA_* types arrive, much of this will need to be restructured |
| 233 | key := fmt.Sprintf("kstat.zfs.misc.%s.%s", fmtExt, parts[0]) |
| 234 | switch parts[1] { |
| 235 | case kstatDataUint64: |
| 236 | value, err := strconv.ParseUint(parts[2], 10, 64) |
| 237 | if err != nil { |
| 238 | return fmt.Errorf("could not parse expected unsigned integer value for %q: %w", key, err) |
| 239 | } |
| 240 | handler(zfsSysctl(key), value) |
| 241 | case kstatDataInt64: |
| 242 | value, err := strconv.ParseInt(parts[2], 10, 64) |
| 243 | if err != nil { |
| 244 | return fmt.Errorf("could not parse expected signed integer value for %q: %w", key, err) |
| 245 | } |
| 246 | handler(zfsSysctl(key), value) |
| 247 | } |
| 248 | } |
| 249 | if !parseLine { |
| 250 | return fmt.Errorf("did not parse a single %q metric", fmtExt) |
| 251 | } |
| 252 | |
| 253 | return scanner.Err() |
| 254 | } |
| 255 | |
| 256 | func (c *zfsCollector) parsePoolProcfsFile(reader io.Reader, zpoolPath string, handler func(string, zfsSysctl, uint64)) error { |
| 257 | scanner := bufio.NewScanner(reader) |