| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- // Copyright 2018 The Prometheus Authors
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package nfsd
- import (
- "bufio"
- "fmt"
- "io"
- "strings"
- "github.com/prometheus/procfs/internal/util"
- )
- // ParseRPCStats returns stats read from /proc/net/rpc/nfsd
- func ParseRPCStats(r io.Reader) (*RPCStats, error) {
- stats := &RPCStats{}
- scanner := bufio.NewScanner(r)
- for scanner.Scan() {
- line := scanner.Text()
- parts := strings.Fields(scanner.Text())
- // require at least <key> <value>
- if len(parts) < 2 {
- return nil, fmt.Errorf("invalid NFSd metric line %q", line)
- }
- label := parts[0]
- var values []uint64
- var err error
- if label == "th" {
- if len(parts) < 3 {
- return nil, fmt.Errorf("invalid NFSd th metric line %q", line)
- }
- values, err = util.ParseUint64s(parts[1:3])
- } else {
- values, err = util.ParseUint64s(parts[1:])
- }
- if err != nil {
- return nil, fmt.Errorf("error parsing NFSd metric line: %s", err)
- }
- switch metricLine := parts[0]; metricLine {
- case "rc":
- stats.ReplyCache, err = parseReplyCache(values)
- case "fh":
- stats.FileHandles, err = parseFileHandles(values)
- case "io":
- stats.InputOutput, err = parseInputOutput(values)
- case "th":
- stats.Threads, err = parseThreads(values)
- case "ra":
- stats.ReadAheadCache, err = parseReadAheadCache(values)
- case "net":
- stats.Network, err = parseNetwork(values)
- case "rpc":
- stats.RPC, err = parseRPC(values)
- case "proc2":
- stats.V2Stats, err = parseV2Stats(values)
- case "proc3":
- stats.V3Stats, err = parseV3Stats(values)
- case "proc4":
- stats.V4Stats, err = parseV4Stats(values)
- case "proc4ops":
- stats.V4Ops, err = parseV4Ops(values)
- default:
- return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine)
- }
- if err != nil {
- return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err)
- }
- }
- if err := scanner.Err(); err != nil {
- return nil, fmt.Errorf("error scanning NFSd file: %s", err)
- }
- return stats, nil
- }
- func parseReplyCache(v []uint64) (ReplyCache, error) {
- if len(v) != 3 {
- return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v)
- }
- return ReplyCache{
- Hits: v[0],
- Misses: v[1],
- NoCache: v[2],
- }, nil
- }
- func parseFileHandles(v []uint64) (FileHandles, error) {
- if len(v) != 5 {
- return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v)
- }
- return FileHandles{
- Stale: v[0],
- TotalLookups: v[1],
- AnonLookups: v[2],
- DirNoCache: v[3],
- NoDirNoCache: v[4],
- }, nil
- }
- func parseInputOutput(v []uint64) (InputOutput, error) {
- if len(v) != 2 {
- return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v)
- }
- return InputOutput{
- Read: v[0],
- Write: v[1],
- }, nil
- }
- func parseThreads(v []uint64) (Threads, error) {
- if len(v) != 2 {
- return Threads{}, fmt.Errorf("invalid Threads line %q", v)
- }
- return Threads{
- Threads: v[0],
- FullCnt: v[1],
- }, nil
- }
- func parseReadAheadCache(v []uint64) (ReadAheadCache, error) {
- if len(v) != 12 {
- return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v)
- }
- return ReadAheadCache{
- CacheSize: v[0],
- CacheHistogram: v[1:11],
- NotFound: v[11],
- }, nil
- }
- func parseNetwork(v []uint64) (Network, error) {
- if len(v) != 4 {
- return Network{}, fmt.Errorf("invalid Network line %q", v)
- }
- return Network{
- NetCount: v[0],
- UDPCount: v[1],
- TCPCount: v[2],
- TCPConnect: v[3],
- }, nil
- }
- func parseRPC(v []uint64) (RPC, error) {
- if len(v) != 5 {
- return RPC{}, fmt.Errorf("invalid RPC line %q", v)
- }
- return RPC{
- RPCCount: v[0],
- BadCnt: v[1],
- BadFmt: v[2],
- BadAuth: v[3],
- BadcInt: v[4],
- }, nil
- }
- func parseV2Stats(v []uint64) (V2Stats, error) {
- values := int(v[0])
- if len(v[1:]) != values || values != 18 {
- return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v)
- }
- return V2Stats{
- Null: v[1],
- GetAttr: v[2],
- SetAttr: v[3],
- Root: v[4],
- Lookup: v[5],
- ReadLink: v[6],
- Read: v[7],
- WrCache: v[8],
- Write: v[9],
- Create: v[10],
- Remove: v[11],
- Rename: v[12],
- Link: v[13],
- SymLink: v[14],
- MkDir: v[15],
- RmDir: v[16],
- ReadDir: v[17],
- FsStat: v[18],
- }, nil
- }
- func parseV3Stats(v []uint64) (V3Stats, error) {
- values := int(v[0])
- if len(v[1:]) != values || values != 22 {
- return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v)
- }
- return V3Stats{
- Null: v[1],
- GetAttr: v[2],
- SetAttr: v[3],
- Lookup: v[4],
- Access: v[5],
- ReadLink: v[6],
- Read: v[7],
- Write: v[8],
- Create: v[9],
- MkDir: v[10],
- SymLink: v[11],
- MkNod: v[12],
- Remove: v[13],
- RmDir: v[14],
- Rename: v[15],
- Link: v[16],
- ReadDir: v[17],
- ReadDirPlus: v[18],
- FsStat: v[19],
- FsInfo: v[20],
- PathConf: v[21],
- Commit: v[22],
- }, nil
- }
- func parseV4Stats(v []uint64) (V4Stats, error) {
- values := int(v[0])
- if len(v[1:]) != values || values != 2 {
- return V4Stats{}, fmt.Errorf("invalid V4Stats line %q", v)
- }
- return V4Stats{
- Null: v[1],
- Compound: v[2],
- }, nil
- }
- func parseV4Ops(v []uint64) (V4Ops, error) {
- values := int(v[0])
- if len(v[1:]) != values || values < 39 {
- return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v)
- }
- stats := V4Ops{
- Op0Unused: v[1],
- Op1Unused: v[2],
- Op2Future: v[3],
- Access: v[4],
- Close: v[5],
- Commit: v[6],
- Create: v[7],
- DelegPurge: v[8],
- DelegReturn: v[9],
- GetAttr: v[10],
- GetFH: v[11],
- Link: v[12],
- Lock: v[13],
- Lockt: v[14],
- Locku: v[15],
- Lookup: v[16],
- LookupRoot: v[17],
- Nverify: v[18],
- Open: v[19],
- OpenAttr: v[20],
- OpenConfirm: v[21],
- OpenDgrd: v[22],
- PutFH: v[23],
- PutPubFH: v[24],
- PutRootFH: v[25],
- Read: v[26],
- ReadDir: v[27],
- ReadLink: v[28],
- Remove: v[29],
- Rename: v[30],
- Renew: v[31],
- RestoreFH: v[32],
- SaveFH: v[33],
- SecInfo: v[34],
- SetAttr: v[35],
- Verify: v[36],
- Write: v[37],
- RelLockOwner: v[38],
- }
- return stats, nil
- }
|