parse_nfsd.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // Copyright 2018 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package nfsd
  14. import (
  15. "bufio"
  16. "fmt"
  17. "io"
  18. "strings"
  19. "github.com/prometheus/procfs/internal/util"
  20. )
  21. // ParseRPCStats returns stats read from /proc/net/rpc/nfsd
  22. func ParseRPCStats(r io.Reader) (*RPCStats, error) {
  23. stats := &RPCStats{}
  24. scanner := bufio.NewScanner(r)
  25. for scanner.Scan() {
  26. line := scanner.Text()
  27. parts := strings.Fields(scanner.Text())
  28. // require at least <key> <value>
  29. if len(parts) < 2 {
  30. return nil, fmt.Errorf("invalid NFSd metric line %q", line)
  31. }
  32. label := parts[0]
  33. var values []uint64
  34. var err error
  35. if label == "th" {
  36. if len(parts) < 3 {
  37. return nil, fmt.Errorf("invalid NFSd th metric line %q", line)
  38. }
  39. values, err = util.ParseUint64s(parts[1:3])
  40. } else {
  41. values, err = util.ParseUint64s(parts[1:])
  42. }
  43. if err != nil {
  44. return nil, fmt.Errorf("error parsing NFSd metric line: %s", err)
  45. }
  46. switch metricLine := parts[0]; metricLine {
  47. case "rc":
  48. stats.ReplyCache, err = parseReplyCache(values)
  49. case "fh":
  50. stats.FileHandles, err = parseFileHandles(values)
  51. case "io":
  52. stats.InputOutput, err = parseInputOutput(values)
  53. case "th":
  54. stats.Threads, err = parseThreads(values)
  55. case "ra":
  56. stats.ReadAheadCache, err = parseReadAheadCache(values)
  57. case "net":
  58. stats.Network, err = parseNetwork(values)
  59. case "rpc":
  60. stats.RPC, err = parseRPC(values)
  61. case "proc2":
  62. stats.V2Stats, err = parseV2Stats(values)
  63. case "proc3":
  64. stats.V3Stats, err = parseV3Stats(values)
  65. case "proc4":
  66. stats.V4Stats, err = parseV4Stats(values)
  67. case "proc4ops":
  68. stats.V4Ops, err = parseV4Ops(values)
  69. default:
  70. return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine)
  71. }
  72. if err != nil {
  73. return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err)
  74. }
  75. }
  76. if err := scanner.Err(); err != nil {
  77. return nil, fmt.Errorf("error scanning NFSd file: %s", err)
  78. }
  79. return stats, nil
  80. }
  81. func parseReplyCache(v []uint64) (ReplyCache, error) {
  82. if len(v) != 3 {
  83. return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v)
  84. }
  85. return ReplyCache{
  86. Hits: v[0],
  87. Misses: v[1],
  88. NoCache: v[2],
  89. }, nil
  90. }
  91. func parseFileHandles(v []uint64) (FileHandles, error) {
  92. if len(v) != 5 {
  93. return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v)
  94. }
  95. return FileHandles{
  96. Stale: v[0],
  97. TotalLookups: v[1],
  98. AnonLookups: v[2],
  99. DirNoCache: v[3],
  100. NoDirNoCache: v[4],
  101. }, nil
  102. }
  103. func parseInputOutput(v []uint64) (InputOutput, error) {
  104. if len(v) != 2 {
  105. return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v)
  106. }
  107. return InputOutput{
  108. Read: v[0],
  109. Write: v[1],
  110. }, nil
  111. }
  112. func parseThreads(v []uint64) (Threads, error) {
  113. if len(v) != 2 {
  114. return Threads{}, fmt.Errorf("invalid Threads line %q", v)
  115. }
  116. return Threads{
  117. Threads: v[0],
  118. FullCnt: v[1],
  119. }, nil
  120. }
  121. func parseReadAheadCache(v []uint64) (ReadAheadCache, error) {
  122. if len(v) != 12 {
  123. return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v)
  124. }
  125. return ReadAheadCache{
  126. CacheSize: v[0],
  127. CacheHistogram: v[1:11],
  128. NotFound: v[11],
  129. }, nil
  130. }
  131. func parseNetwork(v []uint64) (Network, error) {
  132. if len(v) != 4 {
  133. return Network{}, fmt.Errorf("invalid Network line %q", v)
  134. }
  135. return Network{
  136. NetCount: v[0],
  137. UDPCount: v[1],
  138. TCPCount: v[2],
  139. TCPConnect: v[3],
  140. }, nil
  141. }
  142. func parseRPC(v []uint64) (RPC, error) {
  143. if len(v) != 5 {
  144. return RPC{}, fmt.Errorf("invalid RPC line %q", v)
  145. }
  146. return RPC{
  147. RPCCount: v[0],
  148. BadCnt: v[1],
  149. BadFmt: v[2],
  150. BadAuth: v[3],
  151. BadcInt: v[4],
  152. }, nil
  153. }
  154. func parseV2Stats(v []uint64) (V2Stats, error) {
  155. values := int(v[0])
  156. if len(v[1:]) != values || values != 18 {
  157. return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v)
  158. }
  159. return V2Stats{
  160. Null: v[1],
  161. GetAttr: v[2],
  162. SetAttr: v[3],
  163. Root: v[4],
  164. Lookup: v[5],
  165. ReadLink: v[6],
  166. Read: v[7],
  167. WrCache: v[8],
  168. Write: v[9],
  169. Create: v[10],
  170. Remove: v[11],
  171. Rename: v[12],
  172. Link: v[13],
  173. SymLink: v[14],
  174. MkDir: v[15],
  175. RmDir: v[16],
  176. ReadDir: v[17],
  177. FsStat: v[18],
  178. }, nil
  179. }
  180. func parseV3Stats(v []uint64) (V3Stats, error) {
  181. values := int(v[0])
  182. if len(v[1:]) != values || values != 22 {
  183. return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v)
  184. }
  185. return V3Stats{
  186. Null: v[1],
  187. GetAttr: v[2],
  188. SetAttr: v[3],
  189. Lookup: v[4],
  190. Access: v[5],
  191. ReadLink: v[6],
  192. Read: v[7],
  193. Write: v[8],
  194. Create: v[9],
  195. MkDir: v[10],
  196. SymLink: v[11],
  197. MkNod: v[12],
  198. Remove: v[13],
  199. RmDir: v[14],
  200. Rename: v[15],
  201. Link: v[16],
  202. ReadDir: v[17],
  203. ReadDirPlus: v[18],
  204. FsStat: v[19],
  205. FsInfo: v[20],
  206. PathConf: v[21],
  207. Commit: v[22],
  208. }, nil
  209. }
  210. func parseV4Stats(v []uint64) (V4Stats, error) {
  211. values := int(v[0])
  212. if len(v[1:]) != values || values != 2 {
  213. return V4Stats{}, fmt.Errorf("invalid V4Stats line %q", v)
  214. }
  215. return V4Stats{
  216. Null: v[1],
  217. Compound: v[2],
  218. }, nil
  219. }
  220. func parseV4Ops(v []uint64) (V4Ops, error) {
  221. values := int(v[0])
  222. if len(v[1:]) != values || values < 39 {
  223. return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v)
  224. }
  225. stats := V4Ops{
  226. Op0Unused: v[1],
  227. Op1Unused: v[2],
  228. Op2Future: v[3],
  229. Access: v[4],
  230. Close: v[5],
  231. Commit: v[6],
  232. Create: v[7],
  233. DelegPurge: v[8],
  234. DelegReturn: v[9],
  235. GetAttr: v[10],
  236. GetFH: v[11],
  237. Link: v[12],
  238. Lock: v[13],
  239. Lockt: v[14],
  240. Locku: v[15],
  241. Lookup: v[16],
  242. LookupRoot: v[17],
  243. Nverify: v[18],
  244. Open: v[19],
  245. OpenAttr: v[20],
  246. OpenConfirm: v[21],
  247. OpenDgrd: v[22],
  248. PutFH: v[23],
  249. PutPubFH: v[24],
  250. PutRootFH: v[25],
  251. Read: v[26],
  252. ReadDir: v[27],
  253. ReadLink: v[28],
  254. Remove: v[29],
  255. Rename: v[30],
  256. Renew: v[31],
  257. RestoreFH: v[32],
  258. SaveFH: v[33],
  259. SecInfo: v[34],
  260. SetAttr: v[35],
  261. Verify: v[36],
  262. Write: v[37],
  263. RelLockOwner: v[38],
  264. }
  265. return stats, nil
  266. }