Fix rollover bug in mountstats collector (#1364)

* Update procfs vendor to pull in github.com/prometheus/procfs/pull/165
* Update mountstats collector to use new types.
* Rollover counter automatically to avoid float64 accuracy issues.
* Update e2e test.

Signed-off-by: Ben Kochie <superq@gmail.com>
This commit is contained in:
Ben Kochie 2019-05-31 18:30:37 +02:00 committed by GitHub
parent 501ccf9fb4
commit 8146998945
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 771 additions and 76 deletions

View file

@ -1577,6 +1577,7 @@ node_mountstats_nfs_event_write_extension_total{export="192.168.1.1:/srv/test",p
node_mountstats_nfs_event_write_extension_total{export="192.168.1.1:/srv/test",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_major_timeouts_total Number of times a request has had a major timeout for a given operation.
# TYPE node_mountstats_nfs_operations_major_timeouts_total counter
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 0
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 0
@ -1585,6 +1586,7 @@ node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/tes
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_queue_time_seconds_total Duration all requests spent queued for transmission for a given operation before they were sent, in seconds.
# TYPE node_mountstats_nfs_operations_queue_time_seconds_total counter
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 9.007044786793922e+12
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 0.006
@ -1593,6 +1595,7 @@ node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_received_bytes_total Number of bytes received for a given operation, including RPC headers and payload.
# TYPE node_mountstats_nfs_operations_received_bytes_total counter
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 3.62996810236e+11
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 1.210292152e+09
@ -1601,6 +1604,7 @@ node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/tes
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_request_time_seconds_total Duration all requests took from when a request was enqueued to when it was completely handled for a given operation, in seconds.
# TYPE node_mountstats_nfs_operations_request_time_seconds_total counter
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 1.953587717e+06
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 79.407
@ -1609,6 +1613,7 @@ node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/s
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_requests_total Number of requests performed for a given operation.
# TYPE node_mountstats_nfs_operations_requests_total counter
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 2.927395007e+09
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 1298
@ -1617,6 +1622,7 @@ node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",ope
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_response_time_seconds_total Duration all requests took to get a reply back after a request for a given operation was transmitted, in seconds.
# TYPE node_mountstats_nfs_operations_response_time_seconds_total counter
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 1.667369447e+06
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 79.386
@ -1625,6 +1631,7 @@ node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_sent_bytes_total Number of bytes sent for a given operation, including RPC headers and payload.
# TYPE node_mountstats_nfs_operations_sent_bytes_total counter
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 5.26931094212e+11
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 207680
@ -1633,6 +1640,7 @@ node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",o
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_transmissions_total Number of times an actual RPC request has been transmitted for a given operation.
# TYPE node_mountstats_nfs_operations_transmissions_total counter
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 2.927394995e+09
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 1298

View file

@ -1577,6 +1577,7 @@ node_mountstats_nfs_event_write_extension_total{export="192.168.1.1:/srv/test",p
node_mountstats_nfs_event_write_extension_total{export="192.168.1.1:/srv/test",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_major_timeouts_total Number of times a request has had a major timeout for a given operation.
# TYPE node_mountstats_nfs_operations_major_timeouts_total counter
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 0
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 0
@ -1585,6 +1586,7 @@ node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/tes
node_mountstats_nfs_operations_major_timeouts_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_queue_time_seconds_total Duration all requests spent queued for transmission for a given operation before they were sent, in seconds.
# TYPE node_mountstats_nfs_operations_queue_time_seconds_total counter
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 9.007044786793922e+12
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 0.006
@ -1593,6 +1595,7 @@ node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv
node_mountstats_nfs_operations_queue_time_seconds_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_received_bytes_total Number of bytes received for a given operation, including RPC headers and payload.
# TYPE node_mountstats_nfs_operations_received_bytes_total counter
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 3.62996810236e+11
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 1.210292152e+09
@ -1601,6 +1604,7 @@ node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/tes
node_mountstats_nfs_operations_received_bytes_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_request_time_seconds_total Duration all requests took from when a request was enqueued to when it was completely handled for a given operation, in seconds.
# TYPE node_mountstats_nfs_operations_request_time_seconds_total counter
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 1.953587717e+06
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 79.407
@ -1609,6 +1613,7 @@ node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/s
node_mountstats_nfs_operations_request_time_seconds_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_requests_total Number of requests performed for a given operation.
# TYPE node_mountstats_nfs_operations_requests_total counter
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 2.927395007e+09
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 1298
@ -1617,6 +1622,7 @@ node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",ope
node_mountstats_nfs_operations_requests_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_response_time_seconds_total Duration all requests took to get a reply back after a request for a given operation was transmitted, in seconds.
# TYPE node_mountstats_nfs_operations_response_time_seconds_total counter
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 1.667369447e+06
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 79.386
@ -1625,6 +1631,7 @@ node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/
node_mountstats_nfs_operations_response_time_seconds_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_sent_bytes_total Number of bytes sent for a given operation, including RPC headers and payload.
# TYPE node_mountstats_nfs_operations_sent_bytes_total counter
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 5.26931094212e+11
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 207680
@ -1633,6 +1640,7 @@ node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",o
node_mountstats_nfs_operations_sent_bytes_total{export="192.168.1.1:/srv/test",operation="WRITE",protocol="udp"} 0
# HELP node_mountstats_nfs_operations_transmissions_total Number of times an actual RPC request has been transmitted for a given operation.
# TYPE node_mountstats_nfs_operations_transmissions_total counter
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="ACCESS",protocol="udp"} 2.927394995e+09
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="tcp"} 0
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="NULL",protocol="udp"} 0
node_mountstats_nfs_operations_transmissions_total{export="192.168.1.1:/srv/test",operation="READ",protocol="tcp"} 1298

View file

@ -31,6 +31,7 @@ device 192.168.1.1:/srv/test mounted on /mnt/nfs/test-dupe with fstype nfs4 stat
NULL: 0 0 0 0 0 0 0 0
READ: 1298 1298 0 207680 1210292152 6 79386 79407
WRITE: 0 0 0 0 0 0 0 0
ACCESS: 2927395007 2927394995 0 526931094212 362996810236 18446743919241604546 1667369447 1953587717
device 192.168.1.1:/srv/test mounted on /mnt/nfs/test-dupe with fstype nfs4 statvers=1.1
opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=udp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.5,local_lock=none
@ -46,3 +47,4 @@ device 192.168.1.1:/srv/test mounted on /mnt/nfs/test-dupe with fstype nfs4 stat
NULL: 0 0 0 0 0 0 0 0
READ: 1298 1298 0 207680 1210292152 6 79386 79407
WRITE: 0 0 0 0 0 0 0 0
ACCESS: 2927395007 2927394995 0 526931094212 362996810236 18446743919241604546 1667369447 1953587717

View file

@ -21,6 +21,11 @@ import (
"github.com/prometheus/procfs"
)
var (
// 64-bit float mantissa: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
float64Mantissa uint64 = 9007199254740992
)
type mountStatsCollector struct {
// General statistics
NFSAgeSecondsTotal *prometheus.Desc
@ -618,7 +623,7 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, export
ch <- prometheus.MustNewConstMetric(
c.NFSTransportIdleTimeSeconds,
prometheus.GaugeValue,
s.Transport.IdleTime.Seconds(),
float64(s.Transport.IdleTimeSeconds%float64Mantissa),
export,
protocol,
)
@ -728,7 +733,7 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, export
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsQueueTimeSecondsTotal,
prometheus.CounterValue,
op.CumulativeQueueTime.Seconds(),
float64(op.CumulativeQueueMilliseconds%float64Mantissa)/1000.0,
export,
protocol,
op.Operation,
@ -737,7 +742,7 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, export
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsResponseTimeSecondsTotal,
prometheus.CounterValue,
op.CumulativeTotalResponseTime.Seconds(),
float64(op.CumulativeTotalResponseMilliseconds%float64Mantissa)/1000.0,
export,
protocol,
op.Operation,
@ -746,7 +751,7 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, export
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsRequestTimeSecondsTotal,
prometheus.CounterValue,
op.CumulativeTotalRequestTime.Seconds(),
float64(op.CumulativeTotalRequestMilliseconds%float64Mantissa)/1000.0,
export,
protocol,
op.Operation,

2
go.mod
View file

@ -18,7 +18,7 @@ require (
github.com/prometheus/client_golang v0.9.2
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90
github.com/prometheus/common v0.3.0
github.com/prometheus/procfs v0.0.0-20190507043628-bc6930f2d510
github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae
github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745
github.com/sirupsen/logrus v1.4.1 // indirect
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a

4
go.sum
View file

@ -65,8 +65,8 @@ github.com/prometheus/common v0.3.0 h1:taZ4h8Tkxv2kNyoSctBvfXEHmBmxrwmIidZTIaHon
github.com/prometheus/common v0.3.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507043628-bc6930f2d510 h1:xDFyJxLucSC7yg81N/VozfnSEEB2dRj1VgR/YEzl5dA=
github.com/prometheus/procfs v0.0.0-20190507043628-bc6930f2d510/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae h1:kF6Y/ES9NQmW3t400V0XH+lO1jqvCpXBC1XoLDkvuMM=
github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745 h1:IuH7WumZNax0D+rEqmy2TyhKCzrtMGqbZO0b8rO00JA=
github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=

View file

@ -1,2 +1,2 @@
* Tobias Schmidt <tobidt@gmail.com> @grobie
* Johannes 'fish' Ziemke <github@freigeist.org> @discordianfish
* Paul Gier <pgier@redhat.com> @pgier

View file

@ -14,6 +14,7 @@
include Makefile.common
%/.unpacked: %.ttar
@echo ">> extracting fixtures"
./ttar -C $(dir $*) -x -f $*.ttar
touch $@

View file

@ -69,7 +69,7 @@ else
GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)
endif
PROMU_VERSION ?= 0.3.0
PROMU_VERSION ?= 0.4.0
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
GOLANGCI_LINT :=

View file

@ -1,7 +1,7 @@
# procfs
This procfs package provides functions to retrieve system, kernel and process
metrics from the pseudo-filesystem proc.
metrics from the pseudo-filesystems /proc and /sys.
*WARNING*: This package is a work in progress. Its API may still break in
backwards-incompatible ways without warnings. Use it at your own risk.
@ -9,3 +9,38 @@ backwards-incompatible ways without warnings. Use it at your own risk.
[![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs)
[![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs)
[![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs)
## Usage
The procfs library is organized by packages based on whether the gathered data is coming from
/proc, /sys, or both. Each package contains an `FS` type which represents the path to either /proc, /sys, or both. For example, current cpu statistics are gathered from
`/proc/stat` and are available via the root procfs package. First, the proc filesystem mount
point is initialized, and then the stat information is read.
```go
fs, err := procfs.NewFS("/proc")
stats, err := fs.NewStat()
```
## Building and Testing
The procfs library is normally built as part of another application. However, when making
changes to the library, the `make test` command can be used to run the API test suite.
### Updating Test Fixtures
The procfs library includes a set of test fixtures which include many example files from
the `/proc` and `/sys` filesystems. These fixtures are included as a ttar (text tar) file
which is extracted automatically during testing. To add/update the test fixtures, first
ensure the `fixtures` directory is up to date by removing the existing directory and then
extracting the ttar file using `make fixtures/.unpacked` or just `make test`.
```bash
rm -rf fixtures
make test
```
Next, make the required changes to the extracted files in the `fixtures` directory. When
the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file
based on the updated `fixtures` directory. And finally, verify the changes using
`git diff fixtures.ttar`.

View file

@ -75,13 +75,13 @@ Max realtime timeout unlimited unlimited us
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/26231/mountstats
Lines: 19
Lines: 20
device rootfs mounted on / with fstype rootfs
device sysfs mounted on /sys with fstype sysfs
device proc mounted on /proc with fstype proc
device /dev/sda1 mounted on / with fstype ext4
device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=1.1
opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.5,local_lock=none
opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,mountaddr=192.168.1.1,clientaddr=192.168.1.5,local_lock=none
age: 13968
caps: caps=0xfff7,wtmult=512,dtsize=32768,bsize=0,namlen=255
nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x0,acl=0x0,pnfs=not configured
@ -94,6 +94,7 @@ device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=
NULL: 0 0 0 0 0 0 0 0
READ: 1298 1298 0 207680 1210292152 6 79386 79407
WRITE: 0 0 0 0 0 0 0 0
ACCESS: 2927395007 2927394995 0 526931094212 362996810236 18446743919241604546 1667369447 1953587717
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -125,6 +126,63 @@ Lines: 1
26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/26231/status
Lines: 53
Name: prometheus
Umask: 0022
State: S (sleeping)
Tgid: 1
Ngid: 0
Pid: 1
PPid: 0
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 128
Groups:
NStgid: 1
NSpid: 1
NSpgid: 1
NSsid: 1
VmPeak: 58472 kB
VmSize: 58440 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 8028 kB
VmRSS: 6716 kB
RssAnon: 2092 kB
RssFile: 4624 kB
RssShmem: 0 kB
VmData: 2580 kB
VmStk: 136 kB
VmExe: 948 kB
VmLib: 6816 kB
VmPTE: 128 kB
VmPMD: 12 kB
VmSwap: 660 kB
HugetlbPages: 0 kB
Threads: 1
SigQ: 8/63965
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 7be3c0fe28014a03
SigIgn: 0000000000001000
SigCgt: 00000001800004ec
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
Seccomp: 0
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 4742839
nonvoluntary_ctxt_switches: 1727500
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/proc/26232
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -160,23 +218,23 @@ SymlinkTo: ../../symlinktargets/xyz
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/26232/limits
Lines: 17
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 29436 29436 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 29436 29436 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 29436 29436 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 29436 29436 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/26232/root
@ -206,9 +264,9 @@ Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/buddyinfo
Lines: 3
Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3
Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0
Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0
Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3
Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0
Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/diskstats
@ -302,13 +360,13 @@ Lines: 26
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9]
5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU]
md127 : active raid1 sdi2[0] sdj2[1]
312319552 blocks [2/2] [UU]
md0 : active raid1 sdk[2](S) sdi1[0] sdj1[1]
248896 blocks [2/2] [UU]
md4 : inactive raid1 sda3[0] sdb3[1]
4883648 blocks [2/2] [UU]
@ -402,6 +460,26 @@ proc4 2 2 10853
proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/unix
Lines: 6
Num RefCount Protocol Flags Type St Inode Path
0000000000000000: 00000002 00000000 00010000 0001 01 3442596 /var/run/postgresql/.s.PGSQL.5432
0000000000000000: 0000000a 00000000 00010000 0005 01 10061 /run/udev/control
0000000000000000: 00000007 00000000 00000000 0002 01 12392 /dev/log
0000000000000000: 00000003 00000000 00000000 0001 03 4787297 /var/run/postgresql/.s.PGSQL.5432
0000000000000000: 00000003 00000000 00000000 0001 03 5091797
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/unix_without_inode
Lines: 6
Num RefCount Protocol Flags Type St Path
0000000000000000: 00000002 00000000 00010000 0001 01 /var/run/postgresql/.s.PGSQL.5432
0000000000000000: 0000000a 00000000 00010000 0005 01 /run/udev/control
0000000000000000: 00000007 00000000 00000000 0002 01 /dev/log
0000000000000000: 00000003 00000000 00000000 0001 03 /var/run/postgresql/.s.PGSQL.5432
0000000000000000: 00000003 00000000 00000000 0001 03
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/xfrm_stat
Lines: 28
XfrmInError 1
@ -1107,6 +1185,22 @@ Mode: 644
Directory: fixtures/sys/devices/system
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/clocksource
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/clocksource/clocksource0
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/clocksource/clocksource0/available_clocksource
Lines: 1
tsc hpet acpi_pm
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/clocksource/clocksource0/current_clocksource
Lines: 1
tsc
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/cpu
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View file

@ -27,7 +27,7 @@ type FS struct {
const DefaultMountPoint = fs.DefaultProcMountPoint
// NewFS returns a new proc FS mounted under the given proc mountPoint. It will error
// if the mount point dirctory can't be read or is a file.
// if the mount point directory can't be read or is a file.
func NewFS(mountPoint string) (FS, error) {
fs, err := fs.NewFS(mountPoint)
if err != nil {

View file

@ -69,8 +69,8 @@ type MountStats interface {
type MountStatsNFS struct {
// The version of statistics provided.
StatVersion string
// The optional mountaddr of the NFS mount.
MountAddress 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.
@ -181,11 +181,11 @@ type NFSOperationStats struct {
// 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.
CumulativeQueueTime time.Duration
CumulativeQueueMilliseconds uint64
// Duration it took to get a reply back after the request was transmitted.
CumulativeTotalResponseTime time.Duration
CumulativeTotalResponseMilliseconds uint64
// Duration from when a request was enqueued to when it was completely handled.
CumulativeTotalRequestTime time.Duration
CumulativeTotalRequestMilliseconds uint64
}
// A NFSTransportStats contains statistics for the NFS mount RPC requests and
@ -204,7 +204,7 @@ type NFSTransportStats struct {
// spent waiting for connections to the server to be established.
ConnectIdleTime uint64
// Duration since the NFS mount last saw any RPC traffic.
IdleTime time.Duration
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.
@ -342,10 +342,15 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
switch ss[0] {
case fieldOpts:
if stats.Opts == nil {
stats.Opts = map[string]string{}
}
for _, opt := range strings.Split(ss[1], ",") {
split := strings.Split(opt, "=")
if len(split) == 2 && split[0] == "mountaddr" {
stats.MountAddress = split[1]
if len(split) == 2 {
stats.Opts[split[0]] = split[1]
} else {
stats.Opts[opt] = ""
}
}
case fieldAge:
@ -519,15 +524,15 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
}
ops = append(ops, NFSOperationStats{
Operation: strings.TrimSuffix(ss[0], ":"),
Requests: ns[0],
Transmissions: ns[1],
MajorTimeouts: ns[2],
BytesSent: ns[3],
BytesReceived: ns[4],
CumulativeQueueTime: time.Duration(ns[5]) * time.Millisecond,
CumulativeTotalResponseTime: time.Duration(ns[6]) * time.Millisecond,
CumulativeTotalRequestTime: time.Duration(ns[7]) * time.Millisecond,
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],
})
}
@ -603,7 +608,7 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
Bind: ns[1],
Connect: ns[2],
ConnectIdleTime: ns[3],
IdleTime: time.Duration(ns[4]) * time.Second,
IdleTimeSeconds: ns[4],
Sends: ns[5],
Receives: ns[6],
BadTransactionIDs: ns[7],

View file

@ -75,7 +75,7 @@ func newNetDev(file string) (NetDev, error) {
}
defer f.Close()
nd := NetDev{}
netDev := NetDev{}
s := bufio.NewScanner(f)
for n := 0; s.Scan(); n++ {
// Skip the 2 header lines.
@ -83,20 +83,20 @@ func newNetDev(file string) (NetDev, error) {
continue
}
line, err := nd.parseLine(s.Text())
line, err := netDev.parseLine(s.Text())
if err != nil {
return nd, err
return netDev, err
}
nd[line.Name] = *line
netDev[line.Name] = *line
}
return nd, s.Err()
return netDev, s.Err()
}
// parseLine parses a single line from the /proc/net/dev file. Header lines
// must be filtered prior to calling this method.
func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) {
parts := strings.SplitN(rawLine, ":", 2)
if len(parts) != 2 {
return nil, errors.New("invalid net/dev line, missing colon")
@ -185,11 +185,11 @@ func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
// Total aggregates the values across interfaces and returns a new NetDevLine.
// The Name field will be a sorted comma separated list of interface names.
func (nd NetDev) Total() NetDevLine {
func (netDev NetDev) Total() NetDevLine {
total := NetDevLine{}
names := make([]string, 0, len(nd))
for _, ifc := range nd {
names := make([]string, 0, len(netDev))
for _, ifc := range netDev {
names = append(names, ifc.Name)
total.RxBytes += ifc.RxBytes
total.RxPackets += ifc.RxPackets

275
vendor/github.com/prometheus/procfs/net_unix.go generated vendored Normal file
View file

@ -0,0 +1,275 @@
// 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
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"
)
// For the proc file format details,
// see https://elixir.bootlin.com/linux/v4.17/source/net/unix/af_unix.c#L2815
// and https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/net.h#L48.
const (
netUnixKernelPtrIdx = iota
netUnixRefCountIdx
_
netUnixFlagsIdx
netUnixTypeIdx
netUnixStateIdx
netUnixInodeIdx
// Inode and Path are optional.
netUnixStaticFieldsCnt = 6
)
const (
netUnixTypeStream = 1
netUnixTypeDgram = 2
netUnixTypeSeqpacket = 5
netUnixFlagListen = 1 << 16
netUnixStateUnconnected = 1
netUnixStateConnecting = 2
netUnixStateConnected = 3
netUnixStateDisconnected = 4
)
var errInvalidKernelPtrFmt = errors.New("Invalid Num(the kernel table slot number) format")
// NetUnixType is the type of the type field.
type NetUnixType uint64
// NetUnixFlags is the type of the flags field.
type NetUnixFlags uint64
// NetUnixState is the type of the state field.
type NetUnixState uint64
// NetUnixLine represents a line of /proc/net/unix.
type NetUnixLine struct {
KernelPtr string
RefCount uint64
Protocol uint64
Flags NetUnixFlags
Type NetUnixType
State NetUnixState
Inode uint64
Path string
}
// NetUnix holds the data read from /proc/net/unix.
type NetUnix struct {
Rows []*NetUnixLine
}
// NewNetUnix returns data read from /proc/net/unix.
func NewNetUnix() (*NetUnix, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return nil, err
}
return fs.NewNetUnix()
}
// NewNetUnix returns data read from /proc/net/unix.
func (fs FS) NewNetUnix() (*NetUnix, error) {
return NewNetUnixByPath(fs.proc.Path("net/unix"))
}
// NewNetUnixByPath returns data read from /proc/net/unix by file path.
// It might returns an error with partial parsed data, if an error occur after some data parsed.
func NewNetUnixByPath(path string) (*NetUnix, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return NewNetUnixByReader(f)
}
// NewNetUnixByReader returns data read from /proc/net/unix by a reader.
// It might returns an error with partial parsed data, if an error occur after some data parsed.
func NewNetUnixByReader(reader io.Reader) (*NetUnix, error) {
nu := &NetUnix{
Rows: make([]*NetUnixLine, 0, 32),
}
scanner := bufio.NewScanner(reader)
// Omit the header line.
scanner.Scan()
header := scanner.Text()
// From the man page of proc(5), it does not contain an Inode field,
// but in actually it exists.
// This code works for both cases.
hasInode := strings.Contains(header, "Inode")
minFieldsCnt := netUnixStaticFieldsCnt
if hasInode {
minFieldsCnt++
}
for scanner.Scan() {
line := scanner.Text()
item, err := nu.parseLine(line, hasInode, minFieldsCnt)
if err != nil {
return nu, err
}
nu.Rows = append(nu.Rows, item)
}
return nu, scanner.Err()
}
func (u *NetUnix) parseLine(line string, hasInode bool, minFieldsCnt int) (*NetUnixLine, error) {
fields := strings.Fields(line)
fieldsLen := len(fields)
if fieldsLen < minFieldsCnt {
return nil, fmt.Errorf(
"Parse Unix domain failed: expect at least %d fields but got %d",
minFieldsCnt, fieldsLen)
}
kernelPtr, err := u.parseKernelPtr(fields[netUnixKernelPtrIdx])
if err != nil {
return nil, fmt.Errorf("Parse Unix domain num(%s) failed: %s", fields[netUnixKernelPtrIdx], err)
}
users, err := u.parseUsers(fields[netUnixRefCountIdx])
if err != nil {
return nil, fmt.Errorf("Parse Unix domain ref count(%s) failed: %s", fields[netUnixRefCountIdx], err)
}
flags, err := u.parseFlags(fields[netUnixFlagsIdx])
if err != nil {
return nil, fmt.Errorf("Parse Unix domain flags(%s) failed: %s", fields[netUnixFlagsIdx], err)
}
typ, err := u.parseType(fields[netUnixTypeIdx])
if err != nil {
return nil, fmt.Errorf("Parse Unix domain type(%s) failed: %s", fields[netUnixTypeIdx], err)
}
state, err := u.parseState(fields[netUnixStateIdx])
if err != nil {
return nil, fmt.Errorf("Parse Unix domain state(%s) failed: %s", fields[netUnixStateIdx], err)
}
var inode uint64
if hasInode {
inodeStr := fields[netUnixInodeIdx]
inode, err = u.parseInode(inodeStr)
if err != nil {
return nil, fmt.Errorf("Parse Unix domain inode(%s) failed: %s", inodeStr, err)
}
}
nuLine := &NetUnixLine{
KernelPtr: kernelPtr,
RefCount: users,
Type: typ,
Flags: flags,
State: state,
Inode: inode,
}
// Path field is optional.
if fieldsLen > minFieldsCnt {
pathIdx := netUnixInodeIdx + 1
if !hasInode {
pathIdx--
}
nuLine.Path = fields[pathIdx]
}
return nuLine, nil
}
func (u NetUnix) parseKernelPtr(str string) (string, error) {
if !strings.HasSuffix(str, ":") {
return "", errInvalidKernelPtrFmt
}
return str[:len(str)-1], nil
}
func (u NetUnix) parseUsers(hexStr string) (uint64, error) {
return strconv.ParseUint(hexStr, 16, 32)
}
func (u NetUnix) parseProtocol(hexStr string) (uint64, error) {
return strconv.ParseUint(hexStr, 16, 32)
}
func (u NetUnix) parseType(hexStr string) (NetUnixType, error) {
typ, err := strconv.ParseUint(hexStr, 16, 16)
if err != nil {
return 0, err
}
return NetUnixType(typ), nil
}
func (u NetUnix) parseFlags(hexStr string) (NetUnixFlags, error) {
flags, err := strconv.ParseUint(hexStr, 16, 32)
if err != nil {
return 0, err
}
return NetUnixFlags(flags), nil
}
func (u NetUnix) parseState(hexStr string) (NetUnixState, error) {
st, err := strconv.ParseInt(hexStr, 16, 8)
if err != nil {
return 0, err
}
return NetUnixState(st), nil
}
func (u NetUnix) parseInode(inodeStr string) (uint64, error) {
return strconv.ParseUint(inodeStr, 10, 64)
}
func (t NetUnixType) String() string {
switch t {
case netUnixTypeStream:
return "stream"
case netUnixTypeDgram:
return "dgram"
case netUnixTypeSeqpacket:
return "seqpacket"
}
return "unknown"
}
func (f NetUnixFlags) String() string {
switch f {
case netUnixFlagListen:
return "listen"
default:
return "default"
}
}
func (s NetUnixState) String() string {
switch s {
case netUnixStateUnconnected:
return "unconnected"
case netUnixStateConnecting:
return "connecting"
case netUnixStateConnected:
return "connected"
case netUnixStateDisconnected:
return "disconnected"
}
return "unknown"
}

View file

@ -118,7 +118,7 @@ func parseClientRPC(v []uint64) (ClientRPC, error) {
func parseV2Stats(v []uint64) (V2Stats, error) {
values := int(v[0])
if len(v[1:]) != values || values != 18 {
if len(v[1:]) != values || values < 18 {
return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v)
}
@ -146,7 +146,7 @@ func parseV2Stats(v []uint64) (V2Stats, error) {
func parseV3Stats(v []uint64) (V3Stats, error) {
values := int(v[0])
if len(v[1:]) != values || values != 22 {
if len(v[1:]) != values || values < 22 {
return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v)
}

View file

@ -29,7 +29,7 @@ type Namespace struct {
// Namespaces contains all of the namespaces that the process is contained in.
type Namespaces map[string]Namespace
// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the
// NewNamespaces reads from /proc/<pid>/ns/* to get the namespaces of which the
// process is a member.
func (p Proc) NewNamespaces() (Namespaces, error) {
d, err := os.Open(p.path("ns"))

162
vendor/github.com/prometheus/procfs/proc_status.go generated vendored Normal file
View file

@ -0,0 +1,162 @@
// 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
import (
"bytes"
"io/ioutil"
"os"
"strconv"
"strings"
)
// ProcStat provides status information about the process,
// read from /proc/[pid]/stat.
type ProcStatus struct {
// The process ID.
PID int
// The process name.
Name string
// Peak virtual memory size.
VmPeak uint64
// Virtual memory size.
VmSize uint64
// Locked memory size.
VmLck uint64
// Pinned memory size.
VmPin uint64
// Peak resident set size.
VmHWM uint64
// Resident set size (sum of RssAnnon RssFile and RssShmem).
VmRSS uint64
// Size of resident anonymous memory.
RssAnon uint64
// Size of resident file mappings.
RssFile uint64
// Size of resident shared memory.
RssShmem uint64
// Size of data segments.
VmData uint64
// Size of stack segments.
VmStk uint64
// Size of text segments.
VmExe uint64
// Shared library code size.
VmLib uint64
// Page table entries size.
VmPTE uint64
// Size of second-level page tables.
VmPMD uint64
// Swapped-out virtual memory size by anonymous private.
VmSwap uint64
// Size of hugetlb memory portions
HugetlbPages uint64
// Number of voluntary context switches.
VoluntaryCtxtSwitches uint64
// Number of involuntary context switches.
NonVoluntaryCtxtSwitches uint64
}
// NewStatus returns the current status information of the process.
func (p Proc) NewStatus() (ProcStatus, error) {
f, err := os.Open(p.path("status"))
if err != nil {
return ProcStatus{}, err
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
return ProcStatus{}, err
}
s := ProcStatus{PID: p.PID}
lines := strings.Split(string(data), "\n")
for _, line := range lines {
if !bytes.Contains([]byte(line), []byte(":")) {
continue
}
kv := strings.SplitN(line, ":", 2)
// removes spaces
k := string(strings.TrimSpace(kv[0]))
v := string(strings.TrimSpace(kv[1]))
// removes "kB"
v = string(bytes.Trim([]byte(v), " kB"))
// value to int when possible
// we can skip error check here, 'cause vKBytes is not used when value is a string
vKBytes, _ := strconv.ParseUint(v, 10, 64)
// convert kB to B
vBytes := vKBytes * 1024
s.fillStatus(k, v, vKBytes, vBytes)
}
return s, nil
}
func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) {
switch k {
case "Name":
s.Name = vString
case "VmPeak":
s.VmPeak = vUintBytes
case "VmSize":
s.VmSize = vUintBytes
case "VmLck":
s.VmLck = vUintBytes
case "VmPin":
s.VmPin = vUintBytes
case "VmHWM":
s.VmHWM = vUintBytes
case "VmRSS":
s.VmRSS = vUintBytes
case "RssAnon":
s.RssAnon = vUintBytes
case "RssFile":
s.RssFile = vUintBytes
case "RssShmem":
s.RssShmem = vUintBytes
case "VmData":
s.VmData = vUintBytes
case "VmStk":
s.VmStk = vUintBytes
case "VmExe":
s.VmExe = vUintBytes
case "VmLib":
s.VmLib = vUintBytes
case "VmPTE":
s.VmPTE = vUintBytes
case "VmPMD":
s.VmPMD = vUintBytes
case "VmSwap":
s.VmSwap = vUintBytes
case "HugetlbPages":
s.HugetlbPages = vUintBytes
case "voluntary_ctxt_switches":
s.VoluntaryCtxtSwitches = vUint
case "nonvoluntary_ctxt_switches":
s.NonVoluntaryCtxtSwitches = vUint
}
}
// TotalCtxtSwitches returns the total context switch.
func (s ProcStatus) TotalCtxtSwitches() uint64 {
return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches
}

View file

@ -0,0 +1,76 @@
// Copyright 2019 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.
// +build !windows
package sysfs
import (
"path/filepath"
"strings"
"github.com/prometheus/procfs/internal/util"
)
// ClockSource contains metrics related to the clock source
type ClockSource struct {
Name string
Available []string
Current string
}
// ClockSources returns clocksource information including current and available clocksources
// read from '/sys/devices/system/clocksource'
func (fs FS) ClockSources() ([]ClockSource, error) {
clocksourcePaths, err := filepath.Glob(fs.sys.Path("devices/system/clocksource/clocksource[0-9]*"))
if err != nil {
return nil, err
}
clocksources := make([]ClockSource, len(clocksourcePaths))
for i, clocksourcePath := range clocksourcePaths {
clocksourceName := strings.TrimPrefix(filepath.Base(clocksourcePath), "clocksource")
clocksource, err := parseClocksource(clocksourcePath)
if err != nil {
return nil, err
}
clocksource.Name = clocksourceName
clocksources[i] = *clocksource
}
return clocksources, nil
}
func parseClocksource(clocksourcePath string) (*ClockSource, error) {
stringFiles := []string{
"available_clocksource",
"current_clocksource",
}
stringOut := make([]string, len(stringFiles))
var err error
for i, f := range stringFiles {
stringOut[i], err = util.SysReadFile(filepath.Join(clocksourcePath, f))
if err != nil {
return &ClockSource{}, err
}
}
return &ClockSource{
Available: strings.Fields(stringOut[0]),
Current: stringOut[1],
}, nil
}

View file

@ -86,8 +86,10 @@ Usage: $bname [-C <DIR>] -c -f <ARCHIVE> <FILE...> (create archive)
$bname [-C <DIR>] -x -f <ARCHIVE> (extract archive)
Options:
-C <DIR> (change directory)
-v (verbose)
-C <DIR> (change directory)
-v (verbose)
--recursive-unlink (recursively delete existing directory if path
collides with file or directory to extract)
Example: Change to sysfs directory, create ttar file from fixtures directory
$bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/
@ -111,8 +113,9 @@ function set_cmd {
}
unset VERBOSE
unset RECURSIVE_UNLINK
while getopts :cf:htxvC: opt; do
while getopts :cf:-:htxvC: opt; do
case $opt in
c)
set_cmd "create"
@ -136,6 +139,18 @@ while getopts :cf:htxvC: opt; do
C)
CDIR=$OPTARG
;;
-)
case $OPTARG in
recursive-unlink)
RECURSIVE_UNLINK="yes"
;;
*)
echo -e "Error: invalid option -$OPTARG"
echo
usage 1
;;
esac
;;
*)
echo >&2 "ERROR: invalid option -$OPTARG"
echo
@ -212,16 +227,16 @@ function extract {
local eof_without_newline
if [ "$size" -gt 0 ]; then
if [[ "$line" =~ [^\\]EOF ]]; then
# An EOF not preceeded by a backslash indicates that the line
# An EOF not preceded by a backslash indicates that the line
# does not end with a newline
eof_without_newline=1
else
eof_without_newline=0
fi
# Replace NULLBYTE with null byte if at beginning of line
# Replace NULLBYTE with null byte unless preceeded by backslash
# Replace NULLBYTE with null byte unless preceded by backslash
# Remove one backslash in front of NULLBYTE (if any)
# Remove EOF unless preceeded by backslash
# Remove EOF unless preceded by backslash
# Remove one backslash in front of EOF
if [ $USE_PYTHON -eq 1 ]; then
echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path"
@ -245,7 +260,16 @@ function extract {
fi
if [[ $line =~ ^Path:\ (.*)$ ]]; then
path=${BASH_REMATCH[1]}
if [ -e "$path" ] || [ -L "$path" ]; then
if [ -L "$path" ]; then
rm "$path"
elif [ -d "$path" ]; then
if [ "${RECURSIVE_UNLINK:-}" == "yes" ]; then
rm -r "$path"
else
# Safe because symlinks to directories are dealt with above
rmdir "$path"
fi
elif [ -e "$path" ]; then
rm "$path"
fi
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
@ -338,8 +362,8 @@ function _create {
else
< "$file" \
sed 's/EOF/\\EOF/g;
s/NULLBYTE/\\NULLBYTE/g;
s/\x0/NULLBYTE/g;
s/NULLBYTE/\\NULLBYTE/g;
s/\x0/NULLBYTE/g;
'
fi
if [[ "$eof_without_newline" -eq 1 ]]; then

2
vendor/modules.txt vendored
View file

@ -45,7 +45,7 @@ github.com/prometheus/common/version
github.com/prometheus/common/expfmt
github.com/prometheus/common/model
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
# github.com/prometheus/procfs v0.0.0-20190507043628-bc6930f2d510
# github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae
github.com/prometheus/procfs
github.com/prometheus/procfs/bcache
github.com/prometheus/procfs/nfs