aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/prometheus/procfs/mountstats.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/prometheus/procfs/mountstats.go')
-rw-r--r--vendor/github.com/prometheus/procfs/mountstats.go638
1 files changed, 0 insertions, 638 deletions
diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go
deleted file mode 100644
index f7a828bb1..000000000
--- a/vendor/github.com/prometheus/procfs/mountstats.go
+++ /dev/null
@@ -1,638 +0,0 @@
-// 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 procfs
-
-// While implementing parsing of /proc/[pid]/mountstats, this blog was used
-// heavily as a reference:
-// https://utcc.utoronto.ca/~cks/space/blog/linux/NFSMountstatsIndex
-//
-// Special thanks to Chris Siebenmann for all of his posts explaining the
-// various statistics available for NFS.
-
-import (
- "bufio"
- "fmt"
- "io"
- "strconv"
- "strings"
- "time"
-)
-
-// Constants shared between multiple functions.
-const (
- deviceEntryLen = 8
-
- fieldBytesLen = 8
- fieldEventsLen = 27
-
- statVersion10 = "1.0"
- statVersion11 = "1.1"
-
- fieldTransport10TCPLen = 10
- fieldTransport10UDPLen = 7
-
- fieldTransport11TCPLen = 13
- fieldTransport11UDPLen = 10
-)
-
-// A Mount is a device mount parsed from /proc/[pid]/mountstats.
-type Mount struct {
- // Name of the device.
- Device string
- // The mount point of the device.
- Mount string
- // The filesystem type used by the device.
- Type string
- // If available additional statistics related to this Mount.
- // Use a type assertion to determine if additional statistics are available.
- Stats MountStats
-}
-
-// A MountStats is a type which contains detailed statistics for a specific
-// type of Mount.
-type MountStats interface {
- mountStats()
-}
-
-// A MountStatsNFS is a MountStats implementation for NFSv3 and v4 mounts.
-type MountStatsNFS struct {
- // The version of statistics provided.
- StatVersion string
- // The mount options of the NFS mount.
- Opts map[string]string
- // The age of the NFS mount.
- Age time.Duration
- // Statistics related to byte counters for various operations.
- Bytes NFSBytesStats
- // Statistics related to various NFS event occurrences.
- Events NFSEventsStats
- // Statistics broken down by filesystem operation.
- Operations []NFSOperationStats
- // Statistics about the NFS RPC transport.
- Transport NFSTransportStats
-}
-
-// mountStats implements MountStats.
-func (m MountStatsNFS) mountStats() {}
-
-// A NFSBytesStats contains statistics about the number of bytes read and written
-// by an NFS client to and from an NFS server.
-type NFSBytesStats struct {
- // Number of bytes read using the read() syscall.
- Read uint64
- // Number of bytes written using the write() syscall.
- Write uint64
- // Number of bytes read using the read() syscall in O_DIRECT mode.
- DirectRead uint64
- // Number of bytes written using the write() syscall in O_DIRECT mode.
- DirectWrite uint64
- // Number of bytes read from the NFS server, in total.
- ReadTotal uint64
- // Number of bytes written to the NFS server, in total.
- WriteTotal uint64
- // Number of pages read directly via mmap()'d files.
- ReadPages uint64
- // Number of pages written directly via mmap()'d files.
- WritePages uint64
-}
-
-// A NFSEventsStats contains statistics about NFS event occurrences.
-type NFSEventsStats struct {
- // Number of times cached inode attributes are re-validated from the server.
- InodeRevalidate uint64
- // Number of times cached dentry nodes are re-validated from the server.
- DnodeRevalidate uint64
- // Number of times an inode cache is cleared.
- DataInvalidate uint64
- // Number of times cached inode attributes are invalidated.
- AttributeInvalidate uint64
- // Number of times files or directories have been open()'d.
- VFSOpen uint64
- // Number of times a directory lookup has occurred.
- VFSLookup uint64
- // Number of times permissions have been checked.
- VFSAccess uint64
- // Number of updates (and potential writes) to pages.
- VFSUpdatePage uint64
- // Number of pages read directly via mmap()'d files.
- VFSReadPage uint64
- // Number of times a group of pages have been read.
- VFSReadPages uint64
- // Number of pages written directly via mmap()'d files.
- VFSWritePage uint64
- // Number of times a group of pages have been written.
- VFSWritePages uint64
- // Number of times directory entries have been read with getdents().
- VFSGetdents uint64
- // Number of times attributes have been set on inodes.
- VFSSetattr uint64
- // Number of pending writes that have been forcefully flushed to the server.
- VFSFlush uint64
- // Number of times fsync() has been called on directories and files.
- VFSFsync uint64
- // Number of times locking has been attempted on a file.
- VFSLock uint64
- // Number of times files have been closed and released.
- VFSFileRelease uint64
- // Unknown. Possibly unused.
- CongestionWait uint64
- // Number of times files have been truncated.
- Truncation uint64
- // Number of times a file has been grown due to writes beyond its existing end.
- WriteExtension uint64
- // Number of times a file was removed while still open by another process.
- SillyRename uint64
- // Number of times the NFS server gave less data than expected while reading.
- ShortRead uint64
- // Number of times the NFS server wrote less data than expected while writing.
- ShortWrite uint64
- // Number of times the NFS server indicated EJUKEBOX; retrieving data from
- // offline storage.
- JukeboxDelay uint64
- // Number of NFS v4.1+ pNFS reads.
- PNFSRead uint64
- // Number of NFS v4.1+ pNFS writes.
- PNFSWrite uint64
-}
-
-// A NFSOperationStats contains statistics for a single operation.
-type NFSOperationStats struct {
- // The name of the operation.
- Operation string
- // Number of requests performed for this operation.
- Requests uint64
- // Number of times an actual RPC request has been transmitted for this operation.
- Transmissions uint64
- // Number of times a request has had a major timeout.
- MajorTimeouts uint64
- // Number of bytes sent for this operation, including RPC headers and payload.
- BytesSent uint64
- // Number of bytes received for this operation, including RPC headers and payload.
- BytesReceived uint64
- // Duration all requests spent queued for transmission before they were sent.
- CumulativeQueueMilliseconds uint64
- // Duration it took to get a reply back after the request was transmitted.
- CumulativeTotalResponseMilliseconds uint64
- // Duration from when a request was enqueued to when it was completely handled.
- CumulativeTotalRequestMilliseconds uint64
- // The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions.
- Errors uint64
-}
-
-// A NFSTransportStats contains statistics for the NFS mount RPC requests and
-// responses.
-type NFSTransportStats struct {
- // The transport protocol used for the NFS mount.
- Protocol string
- // The local port used for the NFS mount.
- Port uint64
- // Number of times the client has had to establish a connection from scratch
- // to the NFS server.
- Bind uint64
- // Number of times the client has made a TCP connection to the NFS server.
- Connect uint64
- // Duration (in jiffies, a kernel internal unit of time) the NFS mount has
- // spent waiting for connections to the server to be established.
- ConnectIdleTime uint64
- // Duration since the NFS mount last saw any RPC traffic.
- IdleTimeSeconds uint64
- // Number of RPC requests for this mount sent to the NFS server.
- Sends uint64
- // Number of RPC responses for this mount received from the NFS server.
- Receives uint64
- // Number of times the NFS server sent a response with a transaction ID
- // unknown to this client.
- BadTransactionIDs uint64
- // A running counter, incremented on each request as the current difference
- // ebetween sends and receives.
- CumulativeActiveRequests uint64
- // A running counter, incremented on each request by the current backlog
- // queue size.
- CumulativeBacklog uint64
-
- // Stats below only available with stat version 1.1.
-
- // Maximum number of simultaneously active RPC requests ever used.
- MaximumRPCSlotsUsed uint64
- // A running counter, incremented on each request as the current size of the
- // sending queue.
- CumulativeSendingQueue uint64
- // A running counter, incremented on each request as the current size of the
- // pending queue.
- CumulativePendingQueue uint64
-}
-
-// parseMountStats parses a /proc/[pid]/mountstats file and returns a slice
-// of Mount structures containing detailed information about each mount.
-// If available, statistics for each mount are parsed as well.
-func parseMountStats(r io.Reader) ([]*Mount, error) {
- const (
- device = "device"
- statVersionPrefix = "statvers="
-
- nfs3Type = "nfs"
- nfs4Type = "nfs4"
- )
-
- var mounts []*Mount
-
- s := bufio.NewScanner(r)
- for s.Scan() {
- // Only look for device entries in this function
- ss := strings.Fields(string(s.Bytes()))
- if len(ss) == 0 || ss[0] != device {
- continue
- }
-
- m, err := parseMount(ss)
- if err != nil {
- return nil, err
- }
-
- // Does this mount also possess statistics information?
- if len(ss) > deviceEntryLen {
- // Only NFSv3 and v4 are supported for parsing statistics
- if m.Type != nfs3Type && m.Type != nfs4Type {
- return nil, fmt.Errorf("cannot parse MountStats for fstype %q", m.Type)
- }
-
- statVersion := strings.TrimPrefix(ss[8], statVersionPrefix)
-
- stats, err := parseMountStatsNFS(s, statVersion)
- if err != nil {
- return nil, err
- }
-
- m.Stats = stats
- }
-
- mounts = append(mounts, m)
- }
-
- return mounts, s.Err()
-}
-
-// parseMount parses an entry in /proc/[pid]/mountstats in the format:
-// device [device] mounted on [mount] with fstype [type]
-func parseMount(ss []string) (*Mount, error) {
- if len(ss) < deviceEntryLen {
- return nil, fmt.Errorf("invalid device entry: %v", ss)
- }
-
- // Check for specific words appearing at specific indices to ensure
- // the format is consistent with what we expect
- format := []struct {
- i int
- s string
- }{
- {i: 0, s: "device"},
- {i: 2, s: "mounted"},
- {i: 3, s: "on"},
- {i: 5, s: "with"},
- {i: 6, s: "fstype"},
- }
-
- for _, f := range format {
- if ss[f.i] != f.s {
- return nil, fmt.Errorf("invalid device entry: %v", ss)
- }
- }
-
- return &Mount{
- Device: ss[1],
- Mount: ss[4],
- Type: ss[7],
- }, nil
-}
-
-// parseMountStatsNFS parses a MountStatsNFS by scanning additional information
-// related to NFS statistics.
-func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, error) {
- // Field indicators for parsing specific types of data
- const (
- fieldOpts = "opts:"
- fieldAge = "age:"
- fieldBytes = "bytes:"
- fieldEvents = "events:"
- fieldPerOpStats = "per-op"
- fieldTransport = "xprt:"
- )
-
- stats := &MountStatsNFS{
- StatVersion: statVersion,
- }
-
- for s.Scan() {
- ss := strings.Fields(string(s.Bytes()))
- if len(ss) == 0 {
- break
- }
-
- switch ss[0] {
- case fieldOpts:
- if len(ss) < 2 {
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
- }
- if stats.Opts == nil {
- stats.Opts = map[string]string{}
- }
- for _, opt := range strings.Split(ss[1], ",") {
- split := strings.Split(opt, "=")
- if len(split) == 2 {
- stats.Opts[split[0]] = split[1]
- } else {
- stats.Opts[opt] = ""
- }
- }
- case fieldAge:
- if len(ss) < 2 {
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
- }
- // Age integer is in seconds
- d, err := time.ParseDuration(ss[1] + "s")
- if err != nil {
- return nil, err
- }
-
- stats.Age = d
- case fieldBytes:
- if len(ss) < 2 {
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
- }
- bstats, err := parseNFSBytesStats(ss[1:])
- if err != nil {
- return nil, err
- }
-
- stats.Bytes = *bstats
- case fieldEvents:
- if len(ss) < 2 {
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
- }
- estats, err := parseNFSEventsStats(ss[1:])
- if err != nil {
- return nil, err
- }
-
- stats.Events = *estats
- case fieldTransport:
- if len(ss) < 3 {
- return nil, fmt.Errorf("not enough information for NFS transport stats: %v", ss)
- }
-
- tstats, err := parseNFSTransportStats(ss[1:], statVersion)
- if err != nil {
- return nil, err
- }
-
- stats.Transport = *tstats
- }
-
- // When encountering "per-operation statistics", we must break this
- // loop and parse them separately to ensure we can terminate parsing
- // before reaching another device entry; hence why this 'if' statement
- // is not just another switch case
- if ss[0] == fieldPerOpStats {
- break
- }
- }
-
- if err := s.Err(); err != nil {
- return nil, err
- }
-
- // NFS per-operation stats appear last before the next device entry
- perOpStats, err := parseNFSOperationStats(s)
- if err != nil {
- return nil, err
- }
-
- stats.Operations = perOpStats
-
- return stats, nil
-}
-
-// parseNFSBytesStats parses a NFSBytesStats line using an input set of
-// integer fields.
-func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) {
- if len(ss) != fieldBytesLen {
- return nil, fmt.Errorf("invalid NFS bytes stats: %v", ss)
- }
-
- ns := make([]uint64, 0, fieldBytesLen)
- for _, s := range ss {
- n, err := strconv.ParseUint(s, 10, 64)
- if err != nil {
- return nil, err
- }
-
- ns = append(ns, n)
- }
-
- return &NFSBytesStats{
- Read: ns[0],
- Write: ns[1],
- DirectRead: ns[2],
- DirectWrite: ns[3],
- ReadTotal: ns[4],
- WriteTotal: ns[5],
- ReadPages: ns[6],
- WritePages: ns[7],
- }, nil
-}
-
-// parseNFSEventsStats parses a NFSEventsStats line using an input set of
-// integer fields.
-func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) {
- if len(ss) != fieldEventsLen {
- return nil, fmt.Errorf("invalid NFS events stats: %v", ss)
- }
-
- ns := make([]uint64, 0, fieldEventsLen)
- for _, s := range ss {
- n, err := strconv.ParseUint(s, 10, 64)
- if err != nil {
- return nil, err
- }
-
- ns = append(ns, n)
- }
-
- return &NFSEventsStats{
- InodeRevalidate: ns[0],
- DnodeRevalidate: ns[1],
- DataInvalidate: ns[2],
- AttributeInvalidate: ns[3],
- VFSOpen: ns[4],
- VFSLookup: ns[5],
- VFSAccess: ns[6],
- VFSUpdatePage: ns[7],
- VFSReadPage: ns[8],
- VFSReadPages: ns[9],
- VFSWritePage: ns[10],
- VFSWritePages: ns[11],
- VFSGetdents: ns[12],
- VFSSetattr: ns[13],
- VFSFlush: ns[14],
- VFSFsync: ns[15],
- VFSLock: ns[16],
- VFSFileRelease: ns[17],
- CongestionWait: ns[18],
- Truncation: ns[19],
- WriteExtension: ns[20],
- SillyRename: ns[21],
- ShortRead: ns[22],
- ShortWrite: ns[23],
- JukeboxDelay: ns[24],
- PNFSRead: ns[25],
- PNFSWrite: ns[26],
- }, nil
-}
-
-// parseNFSOperationStats parses a slice of NFSOperationStats by scanning
-// additional information about per-operation statistics until an empty
-// line is reached.
-func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
- const (
- // Minimum number of expected fields in each per-operation statistics set
- minFields = 9
- )
-
- var ops []NFSOperationStats
-
- for s.Scan() {
- ss := strings.Fields(string(s.Bytes()))
- if len(ss) == 0 {
- // Must break when reading a blank line after per-operation stats to
- // enable top-level function to parse the next device entry
- break
- }
-
- if len(ss) < minFields {
- return nil, fmt.Errorf("invalid NFS per-operations stats: %v", ss)
- }
-
- // Skip string operation name for integers
- ns := make([]uint64, 0, minFields-1)
- for _, st := range ss[1:] {
- n, err := strconv.ParseUint(st, 10, 64)
- if err != nil {
- return nil, err
- }
-
- ns = append(ns, n)
- }
-
- opStats := NFSOperationStats{
- Operation: strings.TrimSuffix(ss[0], ":"),
- Requests: ns[0],
- Transmissions: ns[1],
- MajorTimeouts: ns[2],
- BytesSent: ns[3],
- BytesReceived: ns[4],
- CumulativeQueueMilliseconds: ns[5],
- CumulativeTotalResponseMilliseconds: ns[6],
- CumulativeTotalRequestMilliseconds: ns[7],
- }
-
- if len(ns) > 8 {
- opStats.Errors = ns[8]
- }
-
- ops = append(ops, opStats)
- }
-
- return ops, s.Err()
-}
-
-// parseNFSTransportStats parses a NFSTransportStats line using an input set of
-// integer fields matched to a specific stats version.
-func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats, error) {
- // Extract the protocol field. It is the only string value in the line
- protocol := ss[0]
- ss = ss[1:]
-
- switch statVersion {
- case statVersion10:
- var expectedLength int
- if protocol == "tcp" {
- expectedLength = fieldTransport10TCPLen
- } else if protocol == "udp" {
- expectedLength = fieldTransport10UDPLen
- } else {
- return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.0 statement: %v", protocol, ss)
- }
- if len(ss) != expectedLength {
- return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss)
- }
- case statVersion11:
- var expectedLength int
- if protocol == "tcp" {
- expectedLength = fieldTransport11TCPLen
- } else if protocol == "udp" {
- expectedLength = fieldTransport11UDPLen
- } else {
- return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.1 statement: %v", protocol, ss)
- }
- if len(ss) != expectedLength {
- return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss)
- }
- default:
- return nil, fmt.Errorf("unrecognized NFS transport stats version: %q", statVersion)
- }
-
- // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay
- // in a v1.0 response. Since the stat length is bigger for TCP stats, we use
- // the TCP length here.
- //
- // Note: slice length must be set to length of v1.1 stats to avoid a panic when
- // only v1.0 stats are present.
- // See: https://github.com/prometheus/node_exporter/issues/571.
- ns := make([]uint64, fieldTransport11TCPLen)
- for i, s := range ss {
- n, err := strconv.ParseUint(s, 10, 64)
- if err != nil {
- return nil, err
- }
-
- ns[i] = n
- }
-
- // The fields differ depending on the transport protocol (TCP or UDP)
- // From https://utcc.utoronto.ca/%7Ecks/space/blog/linux/NFSMountstatsXprt
- //
- // For the udp RPC transport there is no connection count, connect idle time,
- // or idle time (fields #3, #4, and #5); all other fields are the same. So
- // we set them to 0 here.
- if protocol == "udp" {
- ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
- }
-
- return &NFSTransportStats{
- Protocol: protocol,
- Port: ns[0],
- Bind: ns[1],
- Connect: ns[2],
- ConnectIdleTime: ns[3],
- IdleTimeSeconds: ns[4],
- Sends: ns[5],
- Receives: ns[6],
- BadTransactionIDs: ns[7],
- CumulativeActiveRequests: ns[8],
- CumulativeBacklog: ns[9],
- MaximumRPCSlotsUsed: ns[10],
- CumulativeSendingQueue: ns[11],
- CumulativePendingQueue: ns[12],
- }, nil
-}