318 lines
7.1 KiB
Go
318 lines
7.1 KiB
Go
|
// 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 nfs
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
)
|
||
|
|
||
|
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 parseServerRPC(v []uint64) (ServerRPC, error) {
|
||
|
if len(v) != 5 {
|
||
|
return ServerRPC{}, fmt.Errorf("invalid RPC line %q", v)
|
||
|
}
|
||
|
|
||
|
return ServerRPC{
|
||
|
RPCCount: v[0],
|
||
|
BadCnt: v[1],
|
||
|
BadFmt: v[2],
|
||
|
BadAuth: v[3],
|
||
|
BadcInt: v[4],
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func parseClientRPC(v []uint64) (ClientRPC, error) {
|
||
|
if len(v) != 3 {
|
||
|
return ClientRPC{}, fmt.Errorf("invalid RPC line %q", v)
|
||
|
}
|
||
|
|
||
|
return ClientRPC{
|
||
|
RPCCount: v[0],
|
||
|
Retransmissions: v[1],
|
||
|
AuthRefreshes: v[2],
|
||
|
}, 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 parseClientV4Stats(v []uint64) (ClientV4Stats, error) {
|
||
|
values := int(v[0])
|
||
|
if len(v[1:]) != values {
|
||
|
return ClientV4Stats{}, fmt.Errorf("invalid ClientV4Stats line %q", v)
|
||
|
}
|
||
|
|
||
|
// This function currently supports mapping 59 NFS v4 client stats. Older
|
||
|
// kernels may emit fewer stats, so we must detect this and pad out the
|
||
|
// values to match the expected slice size.
|
||
|
if values < 59 {
|
||
|
newValues := make([]uint64, 60)
|
||
|
copy(newValues, v)
|
||
|
v = newValues
|
||
|
}
|
||
|
|
||
|
return ClientV4Stats{
|
||
|
Null: v[1],
|
||
|
Read: v[2],
|
||
|
Write: v[3],
|
||
|
Commit: v[4],
|
||
|
Open: v[5],
|
||
|
OpenConfirm: v[6],
|
||
|
OpenNoattr: v[7],
|
||
|
OpenDowngrade: v[8],
|
||
|
Close: v[9],
|
||
|
Setattr: v[10],
|
||
|
FsInfo: v[11],
|
||
|
Renew: v[12],
|
||
|
SetClientID: v[13],
|
||
|
SetClientIDConfirm: v[14],
|
||
|
Lock: v[15],
|
||
|
Lockt: v[16],
|
||
|
Locku: v[17],
|
||
|
Access: v[18],
|
||
|
Getattr: v[19],
|
||
|
Lookup: v[20],
|
||
|
LookupRoot: v[21],
|
||
|
Remove: v[22],
|
||
|
Rename: v[23],
|
||
|
Link: v[24],
|
||
|
Symlink: v[25],
|
||
|
Create: v[26],
|
||
|
Pathconf: v[27],
|
||
|
StatFs: v[28],
|
||
|
ReadLink: v[29],
|
||
|
ReadDir: v[30],
|
||
|
ServerCaps: v[31],
|
||
|
DelegReturn: v[32],
|
||
|
GetACL: v[33],
|
||
|
SetACL: v[34],
|
||
|
FsLocations: v[35],
|
||
|
ReleaseLockowner: v[36],
|
||
|
Secinfo: v[37],
|
||
|
FsidPresent: v[38],
|
||
|
ExchangeID: v[39],
|
||
|
CreateSession: v[40],
|
||
|
DestroySession: v[41],
|
||
|
Sequence: v[42],
|
||
|
GetLeaseTime: v[43],
|
||
|
ReclaimComplete: v[44],
|
||
|
LayoutGet: v[45],
|
||
|
GetDeviceInfo: v[46],
|
||
|
LayoutCommit: v[47],
|
||
|
LayoutReturn: v[48],
|
||
|
SecinfoNoName: v[49],
|
||
|
TestStateID: v[50],
|
||
|
FreeStateID: v[51],
|
||
|
GetDeviceList: v[52],
|
||
|
BindConnToSession: v[53],
|
||
|
DestroyClientID: v[54],
|
||
|
Seek: v[55],
|
||
|
Allocate: v[56],
|
||
|
DeAllocate: v[57],
|
||
|
LayoutStats: v[58],
|
||
|
Clone: v[59],
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func parseServerV4Stats(v []uint64) (ServerV4Stats, error) {
|
||
|
values := int(v[0])
|
||
|
if len(v[1:]) != values || values != 2 {
|
||
|
return ServerV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v)
|
||
|
}
|
||
|
|
||
|
return ServerV4Stats{
|
||
|
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
|
||
|
}
|