cmd/kg/main.go: replace deprecated prom collectors (#255)

Signed-off-by: leonnicolas <leonloechner@gmx.de>
This commit is contained in:
leonnicolas 2021-11-15 23:08:06 +01:00 committed by GitHub
parent 05e8ded744
commit ee480dece4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
105 changed files with 2597 additions and 1374 deletions

View File

@ -29,6 +29,7 @@ import (
"github.com/go-kit/kit/log/level"
"github.com/oklog/run"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/cobra"
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
@ -171,8 +172,8 @@ func preRun(_ *cobra.Command, _ []string) error {
registry = prometheus.NewRegistry()
registry.MustRegister(
prometheus.NewGoCollector(),
prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}),
collectors.NewGoCollector(),
collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
)
return nil

13
go.mod
View File

@ -12,12 +12,12 @@ require (
github.com/imdario/mergo v0.3.6 // indirect
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
github.com/oklog/run v1.1.0
github.com/prometheus/client_golang v1.7.1
github.com/prometheus/client_golang v1.11.0
github.com/spf13/cobra v1.1.3
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
golang.org/x/sys v0.0.0-20210510120138-977fb7262007
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40
k8s.io/api v0.21.1
k8s.io/apiextensions-apiserver v0.21.1
k8s.io/apimachinery v0.21.1
@ -32,7 +32,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/evanphx/json-patch v4.9.0+incompatible // indirect
github.com/fatih/color v1.12.0 // indirect
github.com/go-logfmt/logfmt v0.4.0 // indirect
github.com/go-logfmt/logfmt v0.5.0 // indirect
github.com/go-logr/logr v0.4.0 // indirect
github.com/gobuffalo/flect v0.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
@ -42,8 +42,7 @@ require (
github.com/googleapis/gnostic v0.4.1 // indirect
github.com/hashicorp/golang-lru v0.5.1 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
@ -52,8 +51,8 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.10.0 // indirect
github.com/prometheus/procfs v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect

31
go.sum
View File

@ -41,6 +41,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
@ -114,9 +115,11 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
@ -174,6 +177,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -233,19 +237,22 @@ github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@ -291,6 +298,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@ -328,8 +336,9 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -338,14 +347,16 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -355,6 +366,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@ -478,6 +490,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
@ -496,6 +509,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -532,16 +546,19 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=

View File

@ -1,4 +1 @@
_testdata/
_testdata2/
logfmt-fuzz.zip
logfmt.test.exe
.vscode/

View File

@ -6,6 +6,8 @@ go:
- "1.9.x"
- "1.10.x"
- "1.11.x"
- "1.12.x"
- "1.13.x"
- "tip"
before_install:

View File

@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.5.0] - 2020-01-03
### Changed
- Remove the dependency on github.com/kr/logfmt by [@ChrisHines]
- Move fuzz code to github.com/go-logfmt/fuzzlogfmt by [@ChrisHines]
## [0.4.0] - 2018-11-21
### Added
@ -30,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Decoder by [@ChrisHines]
- MarshalKeyvals by [@ChrisHines]
[0.5.0]: https://github.com/go-logfmt/logfmt/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/go-logfmt/logfmt/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/go-logfmt/logfmt/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/go-logfmt/logfmt/compare/v0.1.0...v0.2.0

View File

@ -79,7 +79,7 @@ key:
dec.pos += p
if dec.pos > start {
dec.key = line[start:dec.pos]
if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) {
dec.syntaxError(invalidKeyError)
return false
}
@ -97,7 +97,7 @@ key:
dec.pos += p
if dec.pos > start {
dec.key = line[start:dec.pos]
if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) {
dec.syntaxError(invalidKeyError)
return false
}
@ -110,7 +110,7 @@ key:
dec.pos = len(line)
if dec.pos > start {
dec.key = line[start:dec.pos]
if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) {
dec.syntaxError(invalidKeyError)
return false
}

View File

@ -1,126 +0,0 @@
// +build gofuzz
package logfmt
import (
"bufio"
"bytes"
"fmt"
"io"
"reflect"
kr "github.com/kr/logfmt"
)
// Fuzz checks reserialized data matches
func Fuzz(data []byte) int {
parsed, err := parse(data)
if err != nil {
return 0
}
var w1 bytes.Buffer
if err = write(parsed, &w1); err != nil {
panic(err)
}
parsed, err = parse(w1.Bytes())
if err != nil {
panic(err)
}
var w2 bytes.Buffer
if err = write(parsed, &w2); err != nil {
panic(err)
}
if !bytes.Equal(w1.Bytes(), w2.Bytes()) {
panic(fmt.Sprintf("reserialized data does not match:\n%q\n%q\n", w1.Bytes(), w2.Bytes()))
}
return 1
}
// FuzzVsKR checks go-logfmt/logfmt against kr/logfmt
func FuzzVsKR(data []byte) int {
parsed, err := parse(data)
parsedKR, errKR := parseKR(data)
// github.com/go-logfmt/logfmt is a stricter parser. It returns errors for
// more inputs than github.com/kr/logfmt. Ignore any inputs that have a
// stict error.
if err != nil {
return 0
}
// Fail if the more forgiving parser finds an error not found by the
// stricter parser.
if errKR != nil {
panic(fmt.Sprintf("unmatched error: %v", errKR))
}
if !reflect.DeepEqual(parsed, parsedKR) {
panic(fmt.Sprintf("parsers disagree:\n%+v\n%+v\n", parsed, parsedKR))
}
return 1
}
type kv struct {
k, v []byte
}
func parse(data []byte) ([][]kv, error) {
var got [][]kv
dec := NewDecoder(bytes.NewReader(data))
for dec.ScanRecord() {
var kvs []kv
for dec.ScanKeyval() {
kvs = append(kvs, kv{dec.Key(), dec.Value()})
}
got = append(got, kvs)
}
return got, dec.Err()
}
func parseKR(data []byte) ([][]kv, error) {
var (
s = bufio.NewScanner(bytes.NewReader(data))
err error
h saveHandler
got [][]kv
)
for err == nil && s.Scan() {
h.kvs = nil
err = kr.Unmarshal(s.Bytes(), &h)
got = append(got, h.kvs)
}
if err == nil {
err = s.Err()
}
return got, err
}
type saveHandler struct {
kvs []kv
}
func (h *saveHandler) HandleLogfmt(key, val []byte) error {
if len(key) == 0 {
key = nil
}
if len(val) == 0 {
val = nil
}
h.kvs = append(h.kvs, kv{key, val})
return nil
}
func write(recs [][]kv, w io.Writer) error {
enc := NewEncoder(w)
for _, rec := range recs {
for _, f := range rec {
if err := enc.EncodeKeyval(f.k, f.v); err != nil {
return err
}
}
if err := enc.EndRecord(); err != nil {
return err
}
}
return nil
}

View File

@ -288,6 +288,9 @@ non_decimal_loop:
return iter.readFloat64SlowPath()
}
value = (value << 3) + (value << 1) + uint64(ind)
if value > maxFloat64 {
return iter.readFloat64SlowPath()
}
}
}
return iter.readFloat64SlowPath()

View File

@ -9,6 +9,7 @@ var intDigits []int8
const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1
const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1
const maxFloat64 = 1<<53 - 1
func init() {
intDigits = make([]int8, 256)
@ -339,7 +340,7 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
}
func (iter *Iterator) assertInteger() {
if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' {
if iter.head < iter.tail && iter.buf[iter.head] == '.' {
iter.ReportError("assertInteger", "can not decode float as int")
}
}

View File

@ -65,7 +65,7 @@ func (iter *Iterator) ReadVal(obj interface{}) {
decoder := iter.cfg.getDecoderFromCache(cacheKey)
if decoder == nil {
typ := reflect2.TypeOf(obj)
if typ.Kind() != reflect.Ptr {
if typ == nil || typ.Kind() != reflect.Ptr {
iter.ReportError("ReadVal", "can only unmarshal into pointer")
return
}

View File

@ -33,11 +33,19 @@ type jsonRawMessageCodec struct {
}
func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
if iter.ReadNil() {
*((*json.RawMessage)(ptr)) = nil
} else {
*((*json.RawMessage)(ptr)) = iter.SkipAndReturnBytes()
}
}
func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
if *((*json.RawMessage)(ptr)) == nil {
stream.WriteNil()
} else {
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
}
}
func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
@ -48,11 +56,19 @@ type jsoniterRawMessageCodec struct {
}
func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes())
if iter.ReadNil() {
*((*RawMessage)(ptr)) = nil
} else {
*((*RawMessage)(ptr)) = iter.SkipAndReturnBytes()
}
}
func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*RawMessage)(ptr))))
if *((*RawMessage)(ptr)) == nil {
stream.WriteNil()
} else {
stream.WriteRaw(string(*((*RawMessage)(ptr))))
}
}
func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {

View File

@ -1075,6 +1075,11 @@ type stringModeNumberDecoder struct {
}
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() == NilValue {
decoder.elemDecoder.Decode(ptr, iter)
return
}
c := iter.nextToken()
if c != '"' {
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))

View File

@ -1,3 +0,0 @@
*.test
*.swp
*.prof

12
vendor/github.com/kr/logfmt/Readme generated vendored
View File

@ -1,12 +0,0 @@
Go package for parsing (and, eventually, generating)
log lines in the logfmt style.
See http://godoc.org/github.com/kr/logfmt for format, and other documentation and examples.
Copyright (C) 2013 Keith Rarick, Blake Mizerany
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

184
vendor/github.com/kr/logfmt/decode.go generated vendored
View File

@ -1,184 +0,0 @@
// Package implements the decoding of logfmt key-value pairs.
//
// Example logfmt message:
//
// foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf
//
// Example result in JSON:
//
// { "foo": "bar", "a": 14, "baz": "hello kitty", "cool%story": "bro", "f": true, "%^asdf": true }
//
// EBNFish:
//
// ident_byte = any byte greater than ' ', excluding '=' and '"'
// string_byte = any byte excluding '"' and '\'
// garbage = !ident_byte
// ident = ident_byte, { ident byte }
// key = ident
// value = ident | '"', { string_byte | '\', '"' }, '"'
// pair = key, '=', value | key, '=' | key
// message = { garbage, pair }, garbage
package logfmt
import (
"reflect"
"strconv"
"strings"
"time"
)
// Handler is the interface implemented by objects that accept logfmt
// key-value pairs. HandleLogfmt must copy the logfmt data if it
// wishes to retain the data after returning.
type Handler interface {
HandleLogfmt(key, val []byte) error
}
// The HandlerFunc type is an adapter to allow the use of ordinary functions as
// logfmt handlers. If f is a function with the appropriate signature,
// HandlerFunc(f) is a Handler object that calls f.
type HandlerFunc func(key, val []byte) error
func (f HandlerFunc) HandleLogfmt(key, val []byte) error {
return f(key, val)
}
// Unmarshal parses the logfmt encoding data and stores the result in the value
// pointed to by v. If v is an Handler, HandleLogfmt will be called for each
// key-value pair.
//
// If v is not a Handler, it will pass v to NewStructHandler and use the
// returned StructHandler for decoding.
func Unmarshal(data []byte, v interface{}) (err error) {
h, ok := v.(Handler)
if !ok {
h, err = NewStructHandler(v)
if err != nil {
return err
}
}
return gotoScanner(data, h)
}
// StructHandler unmarshals logfmt into a struct. It matches incoming keys to
// the the struct's fields (either the struct field name or its tag, preferring
// an exact match but also accepting a case-insensitive match.
//
// Field types supported by StructHandler are:
//
// all numeric types (e.g. float32, int, etc.)
// []byte
// string
// bool - true if key is present, false otherwise (the value is ignored).
// time.Duration - uses time.ParseDuration
//
// If a field is a pointer to an above type, and a matching key is not present
// in the logfmt data, the pointer will be untouched.
//
// If v is not a pointer to an Handler or struct, Unmarshal will return an
// error.
type StructHandler struct {
rv reflect.Value
}
func NewStructHandler(v interface{}) (Handler, error) {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return nil, &InvalidUnmarshalError{reflect.TypeOf(v)}
}
return &StructHandler{rv: rv}, nil
}
func (h *StructHandler) HandleLogfmt(key, val []byte) error {
el := h.rv.Elem()
skey := string(key)
for i := 0; i < el.NumField(); i++ {
fv := el.Field(i)
ft := el.Type().Field(i)
switch {
case ft.Name == skey:
case ft.Tag.Get("logfmt") == skey:
case strings.EqualFold(ft.Name, skey):
default:
continue
}
if fv.Kind() == reflect.Ptr {
if fv.IsNil() {
t := fv.Type().Elem()
v := reflect.New(t)
fv.Set(v)
fv = v
}
fv = fv.Elem()
}
switch fv.Interface().(type) {
case time.Duration:
d, err := time.ParseDuration(string(val))
if err != nil {
return &UnmarshalTypeError{string(val), fv.Type()}
}
fv.Set(reflect.ValueOf(d))
case string:
fv.SetString(string(val))
case []byte:
b := make([]byte, len(val))
copy(b, val)
fv.SetBytes(b)
case bool:
fv.SetBool(true)
default:
switch {
case reflect.Int <= fv.Kind() && fv.Kind() <= reflect.Int64:
v, err := strconv.ParseInt(string(val), 10, 64)
if err != nil {
return err
}
fv.SetInt(v)
case reflect.Uint32 <= fv.Kind() && fv.Kind() <= reflect.Uint64:
v, err := strconv.ParseUint(string(val), 10, 64)
if err != nil {
return err
}
fv.SetUint(v)
case reflect.Float32 <= fv.Kind() && fv.Kind() <= reflect.Float64:
v, err := strconv.ParseFloat(string(val), 10)
if err != nil {
return err
}
fv.SetFloat(v)
default:
return &UnmarshalTypeError{string(val), fv.Type()}
}
}
}
return nil
}
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
// (The argument to Unmarshal must be a non-nil pointer.)
type InvalidUnmarshalError struct {
Type reflect.Type
}
func (e *InvalidUnmarshalError) Error() string {
if e.Type == nil {
return "logfmt: Unmarshal(nil)"
}
if e.Type.Kind() != reflect.Ptr {
return "logfmt: Unmarshal(non-pointer " + e.Type.String() + ")"
}
return "logfmt: Unmarshal(nil " + e.Type.String() + ")"
}
// An UnmarshalTypeError describes a logfmt value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
Value string // the logfmt value
Type reflect.Type // type of Go value it could not be assigned to
}
func (e *UnmarshalTypeError) Error() string {
return "logfmt: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
}

View File

@ -1,149 +0,0 @@
package logfmt
import (
"errors"
"fmt"
)
var ErrUnterminatedString = errors.New("logfmt: unterminated string")
func gotoScanner(data []byte, h Handler) (err error) {
saveError := func(e error) {
if err == nil {
err = e
}
}
var c byte
var i int
var m int
var key []byte
var val []byte
var ok bool
var esc bool
garbage:
if i == len(data) {
return
}
c = data[i]
switch {
case c > ' ' && c != '"' && c != '=':
key, val = nil, nil
m = i
i++
goto key
default:
i++
goto garbage
}
key:
if i >= len(data) {
if m >= 0 {
key = data[m:i]
saveError(h.HandleLogfmt(key, nil))
}
return
}
c = data[i]
switch {
case c > ' ' && c != '"' && c != '=':
i++
goto key
case c == '=':
key = data[m:i]
i++
goto equal
default:
key = data[m:i]
i++
saveError(h.HandleLogfmt(key, nil))
goto garbage
}
equal:
if i >= len(data) {
if m >= 0 {
i--
key = data[m:i]
saveError(h.HandleLogfmt(key, nil))
}
return
}
c = data[i]
switch {
case c > ' ' && c != '"' && c != '=':
m = i
i++
goto ivalue
case c == '"':
m = i
i++
esc = false
goto qvalue
default:
if key != nil {
saveError(h.HandleLogfmt(key, val))
}
i++
goto garbage
}
ivalue:
if i >= len(data) {
if m >= 0 {
val = data[m:i]
saveError(h.HandleLogfmt(key, val))
}
return
}
c = data[i]
switch {
case c > ' ' && c != '"' && c != '=':
i++
goto ivalue
default:
val = data[m:i]
saveError(h.HandleLogfmt(key, val))
i++
goto garbage
}
qvalue:
if i >= len(data) {
if m >= 0 {
saveError(ErrUnterminatedString)
}
return
}
c = data[i]
switch c {
case '\\':
i += 2
esc = true
goto qvalue
case '"':
i++
val = data[m:i]
if esc {
val, ok = unquoteBytes(val)
if !ok {
saveError(fmt.Errorf("logfmt: error unquoting bytes %q", string(val)))
goto garbage
}
} else {
val = val[1 : len(val)-1]
}
saveError(h.HandleLogfmt(key, val))
goto garbage
default:
i++
goto qvalue
}
}

View File

@ -1,149 +0,0 @@
package logfmt
import (
"strconv"
"unicode"
"unicode/utf16"
"unicode/utf8"
)
// Taken from Go's encoding/json
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
// or it returns -1.
func getu4(s []byte) rune {
if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
return -1
}
r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
if err != nil {
return -1
}
return rune(r)
}
// unquote converts a quoted JSON string literal s into an actual string t.
// The rules are different than for Go, so cannot use strconv.Unquote.
func unquote(s []byte) (t string, ok bool) {
s, ok = unquoteBytes(s)
t = string(s)
return
}
func unquoteBytes(s []byte) (t []byte, ok bool) {
if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
return
}
s = s[1 : len(s)-1]
// Check for unusual characters. If there are none,
// then no unquoting is needed, so return a slice of the
// original bytes.
r := 0
for r < len(s) {
c := s[r]
if c == '\\' || c == '"' || c < ' ' {
break
}
if c < utf8.RuneSelf {
r++
continue
}
rr, size := utf8.DecodeRune(s[r:])
if rr == utf8.RuneError && size == 1 {
break
}
r += size
}
if r == len(s) {
return s, true
}
b := make([]byte, len(s)+2*utf8.UTFMax)
w := copy(b, s[0:r])
for r < len(s) {
// Out of room? Can only happen if s is full of
// malformed UTF-8 and we're replacing each
// byte with RuneError.
if w >= len(b)-2*utf8.UTFMax {
nb := make([]byte, (len(b)+utf8.UTFMax)*2)
copy(nb, b[0:w])
b = nb
}
switch c := s[r]; {
case c == '\\':
r++
if r >= len(s) {
return
}
switch s[r] {
default:
return
case '"', '\\', '/', '\'':
b[w] = s[r]
r++
w++
case 'b':
b[w] = '\b'
r++
w++
case 'f':
b[w] = '\f'
r++
w++
case 'n':
b[w] = '\n'
r++
w++
case 'r':
b[w] = '\r'
r++
w++
case 't':
b[w] = '\t'
r++
w++
case 'u':
r--
rr := getu4(s[r:])
if rr < 0 {
return
}
r += 6
if utf16.IsSurrogate(rr) {
rr1 := getu4(s[r:])
if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
// A valid pair; consume.
r += 6
w += utf8.EncodeRune(b[w:], dec)
break
}
// Invalid surrogate; fall back to replacement rune.
rr = unicode.ReplacementChar
}
w += utf8.EncodeRune(b[w:], rr)
}
// Quote, control characters are invalid.
case c == '"', c < ' ':
return
// ASCII
case c < utf8.RuneSelf:
b[w] = c
r++
w++
// Coerce to well-formed UTF-8.
default:
rr, size := utf8.DecodeRune(s[r:])
r += size
w += utf8.EncodeRune(b[w:], rr)
}
}
return b[0:w], true
}

View File

@ -0,0 +1,16 @@
// Copyright 2021 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 collectors provides implementations of prometheus.Collector to
// conveniently collect process and Go-related metrics.
package collectors

View File

@ -0,0 +1,119 @@
// Copyright 2021 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 collectors
import (
"database/sql"
"github.com/prometheus/client_golang/prometheus"
)
type dbStatsCollector struct {
db *sql.DB
maxOpenConnections *prometheus.Desc
openConnections *prometheus.Desc
inUseConnections *prometheus.Desc
idleConnections *prometheus.Desc
waitCount *prometheus.Desc
waitDuration *prometheus.Desc
maxIdleClosed *prometheus.Desc
maxIdleTimeClosed *prometheus.Desc
maxLifetimeClosed *prometheus.Desc
}
// NewDBStatsCollector returns a collector that exports metrics about the given *sql.DB.
// See https://golang.org/pkg/database/sql/#DBStats for more information on stats.
func NewDBStatsCollector(db *sql.DB, dbName string) prometheus.Collector {
fqName := func(name string) string {
return "go_sql_" + name
}
return &dbStatsCollector{
db: db,
maxOpenConnections: prometheus.NewDesc(
fqName("max_open_connections"),
"Maximum number of open connections to the database.",
nil, prometheus.Labels{"db_name": dbName},
),
openConnections: prometheus.NewDesc(
fqName("open_connections"),
"The number of established connections both in use and idle.",
nil, prometheus.Labels{"db_name": dbName},
),
inUseConnections: prometheus.NewDesc(
fqName("in_use_connections"),
"The number of connections currently in use.",
nil, prometheus.Labels{"db_name": dbName},
),
idleConnections: prometheus.NewDesc(
fqName("idle_connections"),
"The number of idle connections.",
nil, prometheus.Labels{"db_name": dbName},
),
waitCount: prometheus.NewDesc(
fqName("wait_count_total"),
"The total number of connections waited for.",
nil, prometheus.Labels{"db_name": dbName},
),
waitDuration: prometheus.NewDesc(
fqName("wait_duration_seconds_total"),
"The total time blocked waiting for a new connection.",
nil, prometheus.Labels{"db_name": dbName},
),
maxIdleClosed: prometheus.NewDesc(
fqName("max_idle_closed_total"),
"The total number of connections closed due to SetMaxIdleConns.",
nil, prometheus.Labels{"db_name": dbName},
),
maxIdleTimeClosed: prometheus.NewDesc(
fqName("max_idle_time_closed_total"),
"The total number of connections closed due to SetConnMaxIdleTime.",
nil, prometheus.Labels{"db_name": dbName},
),
maxLifetimeClosed: prometheus.NewDesc(
fqName("max_lifetime_closed_total"),
"The total number of connections closed due to SetConnMaxLifetime.",
nil, prometheus.Labels{"db_name": dbName},
),
}
}
// Describe implements Collector.
func (c *dbStatsCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.maxOpenConnections
ch <- c.openConnections
ch <- c.inUseConnections
ch <- c.idleConnections
ch <- c.waitCount
ch <- c.waitDuration
ch <- c.maxIdleClosed
ch <- c.maxLifetimeClosed
c.describeNewInGo115(ch)
}
// Collect implements Collector.
func (c *dbStatsCollector) Collect(ch chan<- prometheus.Metric) {
stats := c.db.Stats()
ch <- prometheus.MustNewConstMetric(c.maxOpenConnections, prometheus.GaugeValue, float64(stats.MaxOpenConnections))
ch <- prometheus.MustNewConstMetric(c.openConnections, prometheus.GaugeValue, float64(stats.OpenConnections))
ch <- prometheus.MustNewConstMetric(c.inUseConnections, prometheus.GaugeValue, float64(stats.InUse))
ch <- prometheus.MustNewConstMetric(c.idleConnections, prometheus.GaugeValue, float64(stats.Idle))
ch <- prometheus.MustNewConstMetric(c.waitCount, prometheus.CounterValue, float64(stats.WaitCount))
ch <- prometheus.MustNewConstMetric(c.waitDuration, prometheus.CounterValue, stats.WaitDuration.Seconds())
ch <- prometheus.MustNewConstMetric(c.maxIdleClosed, prometheus.CounterValue, float64(stats.MaxIdleClosed))
ch <- prometheus.MustNewConstMetric(c.maxLifetimeClosed, prometheus.CounterValue, float64(stats.MaxLifetimeClosed))
c.collectNewInGo115(ch, stats)
}

View File

@ -0,0 +1,30 @@
// Copyright 2021 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 go1.15
package collectors
import (
"database/sql"
"github.com/prometheus/client_golang/prometheus"
)
func (c *dbStatsCollector) describeNewInGo115(ch chan<- *prometheus.Desc) {
ch <- c.maxIdleTimeClosed
}
func (c *dbStatsCollector) collectNewInGo115(ch chan<- prometheus.Metric, stats sql.DBStats) {
ch <- prometheus.MustNewConstMetric(c.maxIdleTimeClosed, prometheus.CounterValue, float64(stats.MaxIdleTimeClosed))
}

View File

@ -1,4 +1,4 @@
// Copyright 2019 The Prometheus Authors
// Copyright 2021 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
@ -11,19 +11,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// +build go1.12
// +build !go1.15
package prometheus
package collectors
import "runtime/debug"
import (
"database/sql"
// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go 1.12+.
func readBuildInfo() (path, version, sum string) {
path, version, sum = "unknown", "unknown", "unknown"
if bi, ok := debug.ReadBuildInfo(); ok {
path = bi.Main.Path
version = bi.Main.Version
sum = bi.Main.Sum
}
return
}
"github.com/prometheus/client_golang/prometheus"
)
func (c *dbStatsCollector) describeNewInGo115(ch chan<- *prometheus.Desc) {}
func (c *dbStatsCollector) collectNewInGo115(ch chan<- prometheus.Metric, stats sql.DBStats) {}

View File

@ -0,0 +1,57 @@
// Copyright 2021 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 collectors
import "github.com/prometheus/client_golang/prometheus"
// NewExpvarCollector returns a newly allocated expvar Collector.
//
// An expvar Collector collects metrics from the expvar interface. It provides a
// quick way to expose numeric values that are already exported via expvar as
// Prometheus metrics. Note that the data models of expvar and Prometheus are
// fundamentally different, and that the expvar Collector is inherently slower
// than native Prometheus metrics. Thus, the expvar Collector is probably great
// for experiments and prototying, but you should seriously consider a more
// direct implementation of Prometheus metrics for monitoring production
// systems.
//
// The exports map has the following meaning:
//
// The keys in the map correspond to expvar keys, i.e. for every expvar key you
// want to export as Prometheus metric, you need an entry in the exports
// map. The descriptor mapped to each key describes how to export the expvar
// value. It defines the name and the help string of the Prometheus metric
// proxying the expvar value. The type will always be Untyped.
//
// For descriptors without variable labels, the expvar value must be a number or
// a bool. The number is then directly exported as the Prometheus sample
// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
// that are not numbers or bools are silently ignored.
//
// If the descriptor has one variable label, the expvar value must be an expvar
// map. The keys in the expvar map become the various values of the one
// Prometheus label. The values in the expvar map must be numbers or bools again
// as above.
//
// For descriptors with more than one variable label, the expvar must be a
// nested expvar map, i.e. where the values of the topmost map are maps again
// etc. until a depth is reached that corresponds to the number of labels. The
// leaves of that structure must be numbers or bools as above to serve as the
// sample values.
//
// Anything that does not fit into the scheme above is silently ignored.
func NewExpvarCollector(exports map[string]*prometheus.Desc) prometheus.Collector {
//nolint:staticcheck // Ignore SA1019 until v2.
return prometheus.NewExpvarCollector(exports)
}

View File

@ -0,0 +1,69 @@
// Copyright 2021 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 collectors
import "github.com/prometheus/client_golang/prometheus"
// NewGoCollector returns a collector that exports metrics about the current Go
// process. This includes memory stats. To collect those, runtime.ReadMemStats
// is called. This requires to “stop the world”, which usually only happens for
// garbage collection (GC). Take the following implications into account when
// deciding whether to use the Go collector:
//
// 1. The performance impact of stopping the world is the more relevant the more
// frequently metrics are collected. However, with Go1.9 or later the
// stop-the-world time per metrics collection is very short (~25µs) so that the
// performance impact will only matter in rare cases. However, with older Go
// versions, the stop-the-world duration depends on the heap size and can be
// quite significant (~1.7 ms/GiB as per
// https://go-review.googlesource.com/c/go/+/34937).
//
// 2. During an ongoing GC, nothing else can stop the world. Therefore, if the
// metrics collection happens to coincide with GC, it will only complete after
// GC has finished. Usually, GC is fast enough to not cause problems. However,
// with a very large heap, GC might take multiple seconds, which is enough to
// cause scrape timeouts in common setups. To avoid this problem, the Go
// collector will use the memstats from a previous collection if
// runtime.ReadMemStats takes more than 1s. However, if there are no previously
// collected memstats, or their collection is more than 5m ago, the collection
// will block until runtime.ReadMemStats succeeds.
//
// NOTE: The problem is solved in Go 1.15, see
// https://github.com/golang/go/issues/19812 for the related Go issue.
func NewGoCollector() prometheus.Collector {
//nolint:staticcheck // Ignore SA1019 until v2.
return prometheus.NewGoCollector()
}
// NewBuildInfoCollector returns a collector collecting a single metric
// "go_build_info" with the constant value 1 and three labels "path", "version",
// and "checksum". Their label values contain the main module path, version, and
// checksum, respectively. The labels will only have meaningful values if the
// binary is built with Go module support and from source code retrieved from
// the source repository (rather than the local file system). This is usually
// accomplished by building from outside of GOPATH, specifying the full address
// of the main package, e.g. "GO111MODULE=on go run
// github.com/prometheus/client_golang/examples/random". If built without Go
// module support, all label values will be "unknown". If built with Go module
// support but using the source code from the local file system, the "path" will
// be set appropriately, but "checksum" will be empty and "version" will be
// "(devel)".
//
// This collector uses only the build information for the main module. See
// https://github.com/povilasv/prommod for an example of a collector for the
// module dependencies.
func NewBuildInfoCollector() prometheus.Collector {
//nolint:staticcheck // Ignore SA1019 until v2.
return prometheus.NewBuildInfoCollector()
}

View File

@ -0,0 +1,56 @@
// Copyright 2021 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 collectors
import "github.com/prometheus/client_golang/prometheus"
// ProcessCollectorOpts defines the behavior of a process metrics collector
// created with NewProcessCollector.
type ProcessCollectorOpts struct {
// PidFn returns the PID of the process the collector collects metrics
// for. It is called upon each collection. By default, the PID of the
// current process is used, as determined on construction time by
// calling os.Getpid().
PidFn func() (int, error)
// If non-empty, each of the collected metrics is prefixed by the
// provided string and an underscore ("_").
Namespace string
// If true, any error encountered during collection is reported as an
// invalid metric (see NewInvalidMetric). Otherwise, errors are ignored
// and the collected metrics will be incomplete. (Possibly, no metrics
// will be collected at all.) While that's usually not desired, it is
// appropriate for the common "mix-in" of process metrics, where process
// metrics are nice to have, but failing to collect them should not
// disrupt the collection of the remaining metrics.
ReportErrors bool
}
// NewProcessCollector returns a collector which exports the current state of
// process metrics including CPU, memory and file descriptor usage as well as
// the process start time. The detailed behavior is defined by the provided
// ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a
// collector for the current process with an empty namespace string and no error
// reporting.
//
// The collector only works on operating systems with a Linux-style proc
// filesystem and on Microsoft Windows. On other operating systems, it will not
// collect any metrics.
func NewProcessCollector(opts ProcessCollectorOpts) prometheus.Collector {
//nolint:staticcheck // Ignore SA1019 until v2.
return prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{
PidFn: opts.PidFn,
Namespace: opts.Namespace,
ReportErrors: opts.ReportErrors,
})
}

View File

@ -163,7 +163,7 @@ func (c *counter) updateExemplar(v float64, l Labels) {
// (e.g. number of HTTP requests, partitioned by response code and
// method). Create instances with NewCounterVec.
type CounterVec struct {
*metricVec
*MetricVec
}
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
@ -176,11 +176,11 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
opts.ConstLabels,
)
return &CounterVec{
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
}
result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs), now: time.Now}
result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now}
result.init(result) // Init self-collection.
return result
}),
@ -188,7 +188,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
}
// GetMetricWithLabelValues returns the Counter for the given slice of label
// values (same order as the VariableLabels in Desc). If that combination of
// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Counter is created.
//
// It is possible to call this method without using the returned Counter to only
@ -202,7 +202,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
// Counter with the same label values is created later.
//
// An error is returned if the number of label values is not the same as the
// number of VariableLabels in Desc (minus any curried labels).
// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -211,7 +211,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Counter), err
}
@ -219,19 +219,19 @@ func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
}
// GetMetricWith returns the Counter for the given Labels map (the label names
// must match those of the VariableLabels in Desc). If that label map is
// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Counter is created. Implications of
// creating a Counter without using it and keeping the Counter for later use are
// the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
// with those of the VariableLabels in Desc (minus any curried labels).
// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
metric, err := v.metricVec.getMetricWith(labels)
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Counter), err
}
@ -275,7 +275,7 @@ func (v *CounterVec) With(labels Labels) Counter {
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
vec, err := v.curryWith(labels)
vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &CounterVec{vec}, err
}

View File

@ -20,7 +20,7 @@ import (
"strings"
"github.com/cespare/xxhash/v2"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/model"
@ -51,7 +51,7 @@ type Desc struct {
// constLabelPairs contains precalculated DTO label pairs based on
// the constant labels.
constLabelPairs []*dto.LabelPair
// VariableLabels contains names of labels for which the metric
// variableLabels contains names of labels for which the metric
// maintains variable values.
variableLabels []string
// id is a hash of the values of the ConstLabels and fqName. This

View File

@ -22,43 +22,10 @@ type expvarCollector struct {
exports map[string]*Desc
}
// NewExpvarCollector returns a newly allocated expvar Collector that still has
// to be registered with a Prometheus registry.
// NewExpvarCollector is the obsolete version of collectors.NewExpvarCollector.
// See there for documentation.
//
// An expvar Collector collects metrics from the expvar interface. It provides a
// quick way to expose numeric values that are already exported via expvar as
// Prometheus metrics. Note that the data models of expvar and Prometheus are
// fundamentally different, and that the expvar Collector is inherently slower
// than native Prometheus metrics. Thus, the expvar Collector is probably great
// for experiments and prototying, but you should seriously consider a more
// direct implementation of Prometheus metrics for monitoring production
// systems.
//
// The exports map has the following meaning:
//
// The keys in the map correspond to expvar keys, i.e. for every expvar key you
// want to export as Prometheus metric, you need an entry in the exports
// map. The descriptor mapped to each key describes how to export the expvar
// value. It defines the name and the help string of the Prometheus metric
// proxying the expvar value. The type will always be Untyped.
//
// For descriptors without variable labels, the expvar value must be a number or
// a bool. The number is then directly exported as the Prometheus sample
// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
// that are not numbers or bools are silently ignored.
//
// If the descriptor has one variable label, the expvar value must be an expvar
// map. The keys in the expvar map become the various values of the one
// Prometheus label. The values in the expvar map must be numbers or bools again
// as above.
//
// For descriptors with more than one variable label, the expvar must be a
// nested expvar map, i.e. where the values of the topmost map are maps again
// etc. until a depth is reached that corresponds to the number of labels. The
// leaves of that structure must be numbers or bools as above to serve as the
// sample values.
//
// Anything that does not fit into the scheme above is silently ignored.
// Deprecated: Use collectors.NewExpvarCollector instead.
func NewExpvarCollector(exports map[string]*Desc) Collector {
return &expvarCollector{
exports: exports,

View File

@ -132,7 +132,7 @@ func (g *gauge) Write(out *dto.Metric) error {
// (e.g. number of operations queued, partitioned by user and operation
// type). Create instances with NewGaugeVec.
type GaugeVec struct {
*metricVec
*MetricVec
}
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
@ -145,11 +145,11 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
opts.ConstLabels,
)
return &GaugeVec{
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
}
result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
result.init(result) // Init self-collection.
return result
}),
@ -157,7 +157,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
}
// GetMetricWithLabelValues returns the Gauge for the given slice of label
// values (same order as the VariableLabels in Desc). If that combination of
// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Gauge is created.
//
// It is possible to call this method without using the returned Gauge to only
@ -172,7 +172,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
// example.
//
// An error is returned if the number of label values is not the same as the
// number of VariableLabels in Desc (minus any curried labels).
// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -180,7 +180,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Gauge), err
}
@ -188,19 +188,19 @@ func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
}
// GetMetricWith returns the Gauge for the given Labels map (the label names
// must match those of the VariableLabels in Desc). If that label map is
// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Gauge is created. Implications of
// creating a Gauge without using it and keeping the Gauge for later use are
// the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
// with those of the VariableLabels in Desc (minus any curried labels).
// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
metric, err := v.metricVec.getMetricWith(labels)
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Gauge), err
}
@ -244,7 +244,7 @@ func (v *GaugeVec) With(labels Labels) Gauge {
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
vec, err := v.curryWith(labels)
vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &GaugeVec{vec}, err
}

View File

@ -36,31 +36,10 @@ type goCollector struct {
msMaxAge time.Duration // Maximum allowed age of old memstats.
}
// NewGoCollector returns a collector that exports metrics about the current Go
// process. This includes memory stats. To collect those, runtime.ReadMemStats
// is called. This requires to “stop the world”, which usually only happens for
// garbage collection (GC). Take the following implications into account when
// deciding whether to use the Go collector:
// NewGoCollector is the obsolete version of collectors.NewGoCollector.
// See there for documentation.
//
// 1. The performance impact of stopping the world is the more relevant the more
// frequently metrics are collected. However, with Go1.9 or later the
// stop-the-world time per metrics collection is very short (~25µs) so that the
// performance impact will only matter in rare cases. However, with older Go
// versions, the stop-the-world duration depends on the heap size and can be
// quite significant (~1.7 ms/GiB as per
// https://go-review.googlesource.com/c/go/+/34937).
//
// 2. During an ongoing GC, nothing else can stop the world. Therefore, if the
// metrics collection happens to coincide with GC, it will only complete after
// GC has finished. Usually, GC is fast enough to not cause problems. However,
// with a very large heap, GC might take multiple seconds, which is enough to
// cause scrape timeouts in common setups. To avoid this problem, the Go
// collector will use the memstats from a previous collection if
// runtime.ReadMemStats takes more than 1s. However, if there are no previously
// collected memstats, or their collection is more than 5m ago, the collection
// will block until runtime.ReadMemStats succeeds. (The problem might be solved
// in Go1.13, see https://github.com/golang/go/issues/19812 for the related Go
// issue.)
// Deprecated: Use collectors.NewGoCollector instead.
func NewGoCollector() Collector {
return &goCollector{
goroutinesDesc: NewDesc(
@ -365,25 +344,17 @@ type memStatsMetrics []struct {
valType ValueType
}
// NewBuildInfoCollector returns a collector collecting a single metric
// "go_build_info" with the constant value 1 and three labels "path", "version",
// and "checksum". Their label values contain the main module path, version, and
// checksum, respectively. The labels will only have meaningful values if the
// binary is built with Go module support and from source code retrieved from
// the source repository (rather than the local file system). This is usually
// accomplished by building from outside of GOPATH, specifying the full address
// of the main package, e.g. "GO111MODULE=on go run
// github.com/prometheus/client_golang/examples/random". If built without Go
// module support, all label values will be "unknown". If built with Go module
// support but using the source code from the local file system, the "path" will
// be set appropriately, but "checksum" will be empty and "version" will be
// "(devel)".
// NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector.
// See there for documentation.
//
// This collector uses only the build information for the main module. See
// https://github.com/povilasv/prommod for an example of a collector for the
// module dependencies.
// Deprecated: Use collectors.NewBuildInfoCollector instead.
func NewBuildInfoCollector() Collector {
path, version, sum := readBuildInfo()
path, version, sum := "unknown", "unknown", "unknown"
if bi, ok := debug.ReadBuildInfo(); ok {
path = bi.Main.Path
version = bi.Main.Version
sum = bi.Main.Sum
}
c := &selfCollector{MustNewConstMetric(
NewDesc(
"go_build_info",

View File

@ -22,7 +22,7 @@ import (
"sync/atomic"
"time"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
@ -47,7 +47,12 @@ type Histogram interface {
Metric
Collector
// Observe adds a single observation to the histogram.
// Observe adds a single observation to the histogram. Observations are
// usually positive or zero. Negative observations are accepted but
// prevent current versions of Prometheus from properly detecting
// counter resets in the sum of observations. See
// https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
// for details.
Observe(float64)
}
@ -192,7 +197,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
h := &histogram{
desc: desc,
upperBounds: opts.Buckets,
labelPairs: makeLabelPairs(desc, labelValues),
labelPairs: MakeLabelPairs(desc, labelValues),
counts: [2]*histogramCounts{{}, {}},
now: time.Now,
}
@ -409,7 +414,7 @@ func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
// (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewHistogramVec.
type HistogramVec struct {
*metricVec
*MetricVec
}
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
@ -422,14 +427,14 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
opts.ConstLabels,
)
return &HistogramVec{
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
return newHistogram(desc, opts, lvs...)
}),
}
}
// GetMetricWithLabelValues returns the Histogram for the given slice of label
// values (same order as the VariableLabels in Desc). If that combination of
// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Histogram is created.
//
// It is possible to call this method without using the returned Histogram to only
@ -444,7 +449,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
// example.
//
// An error is returned if the number of label values is not the same as the
// number of VariableLabels in Desc (minus any curried labels).
// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -453,7 +458,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Observer), err
}
@ -461,19 +466,19 @@ func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error)
}
// GetMetricWith returns the Histogram for the given Labels map (the label names
// must match those of the VariableLabels in Desc). If that label map is
// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Histogram is created. Implications of
// creating a Histogram without using it and keeping the Histogram for later use
// are the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
// with those of the VariableLabels in Desc (minus any curried labels).
// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
metric, err := v.metricVec.getMetricWith(labels)
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Observer), err
}
@ -517,7 +522,7 @@ func (v *HistogramVec) With(labels Labels) Observer {
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) {
vec, err := v.curryWith(labels)
vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &HistogramVec{vec}, err
}
@ -602,7 +607,7 @@ func NewConstHistogram(
count: count,
sum: sum,
buckets: buckets,
labelPairs: makeLabelPairs(desc, labelValues),
labelPairs: MakeLabelPairs(desc, labelValues),
}, nil
}

View File

@ -17,7 +17,7 @@ import (
"strings"
"time"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/model"
@ -58,7 +58,7 @@ type Metric interface {
}
// Opts bundles the options for creating most Metric types. Each metric
// implementation XXX has its own XXXOpts type, but in most cases, it is just be
// implementation XXX has its own XXXOpts type, but in most cases, it is just
// an alias of this type (which might change when the requirement arises.)
//
// It is mandatory to set Name to a non-empty string. All other fields are
@ -89,7 +89,7 @@ type Opts struct {
// better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
ConstLabels Labels
}

View File

@ -15,7 +15,11 @@ package prometheus
import (
"errors"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
)
type processCollector struct {
@ -50,16 +54,10 @@ type ProcessCollectorOpts struct {
ReportErrors bool
}
// NewProcessCollector returns a collector which exports the current state of
// process metrics including CPU, memory and file descriptor usage as well as
// the process start time. The detailed behavior is defined by the provided
// ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a
// collector for the current process with an empty namespace string and no error
// reporting.
// NewProcessCollector is the obsolete version of collectors.NewProcessCollector.
// See there for documentation.
//
// The collector only works on operating systems with a Linux-style proc
// filesystem and on Microsoft Windows. On other operating systems, it will not
// collect any metrics.
// Deprecated: Use collectors.NewProcessCollector instead.
func NewProcessCollector(opts ProcessCollectorOpts) Collector {
ns := ""
if len(opts.Namespace) > 0 {
@ -149,3 +147,20 @@ func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error)
}
ch <- NewInvalidMetric(desc, err)
}
// NewPidFileFn returns a function that retrieves a pid from the specified file.
// It is meant to be used for the PidFn field in ProcessCollectorOpts.
func NewPidFileFn(pidFilePath string) func() (int, error) {
return func() (int, error) {
content, err := ioutil.ReadFile(pidFilePath)
if err != nil {
return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err)
}
pid, err := strconv.Atoi(strings.TrimSpace(string(content)))
if err != nil {
return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err)
}
return pid, nil
}
}

View File

@ -83,8 +83,7 @@ type readerFromDelegator struct{ *responseWriterDelegator }
type pusherDelegator struct{ *responseWriterDelegator }
func (d closeNotifierDelegator) CloseNotify() <-chan bool {
//lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to
//remove support from client_golang yet.
//nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
func (d flusherDelegator) Flush() {
@ -348,8 +347,7 @@ func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) deleg
}
id := 0
//lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to
//remove support from client_golang yet.
//nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
if _, ok := w.(http.CloseNotifier); ok {
id += closeNotifier
}

View File

@ -99,7 +99,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
}
if opts.Registry != nil {
// Initialize all possibilites that can occur below.
// Initialize all possibilities that can occur below.
errCnt.WithLabelValues("gathering")
errCnt.WithLabelValues("encoding")
if err := opts.Registry.Register(errCnt); err != nil {
@ -303,8 +303,12 @@ type Logger interface {
// HandlerOpts specifies options how to serve metrics via an http.Handler. The
// zero value of HandlerOpts is a reasonable default.
type HandlerOpts struct {
// ErrorLog specifies an optional logger for errors collecting and
// serving metrics. If nil, errors are not logged at all.
// ErrorLog specifies an optional Logger for errors collecting and
// serving metrics. If nil, errors are not logged at all. Note that the
// type of a reported error is often prometheus.MultiError, which
// formats into a multi-line error string. If you want to avoid the
// latter, create a Logger implementation that detects a
// prometheus.MultiError and formats the contained errors into one line.
ErrorLog Logger
// ErrorHandling defines how errors are handled. Note that errors are
// logged regardless of the configured ErrorHandling provided ErrorLog

View File

@ -43,14 +43,14 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
// InstrumentHandlerDuration is a middleware that wraps the provided
// http.Handler to observe the request duration with the provided ObserverVec.
// The ObserverVec must have zero, one, or two non-const non-curried labels. For
// those, the only allowed label names are "code" and "method". The function
// panics otherwise. The Observe method of the Observer in the ObserverVec is
// called with the request duration in seconds. Partitioning happens by HTTP
// status code and/or HTTP method if the respective instance label names are
// present in the ObserverVec. For unpartitioned observations, use an
// ObserverVec with zero labels. Note that partitioning of Histograms is
// expensive and should be used judiciously.
// The ObserverVec must have valid metric and label names and must have zero,
// one, or two non-const non-curried labels. For those, the only allowed label
// names are "code" and "method". The function panics otherwise. The Observe
// method of the Observer in the ObserverVec is called with the request duration
// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
// the respective instance label names are present in the ObserverVec. For
// unpartitioned observations, use an ObserverVec with zero labels. Note that
// partitioning of Histograms is expensive and should be used judiciously.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@ -79,12 +79,13 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht
}
// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler
// to observe the request result with the provided CounterVec. The CounterVec
// must have zero, one, or two non-const non-curried labels. For those, the only
// allowed label names are "code" and "method". The function panics
// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or
// HTTP method if the respective instance label names are present in the
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
// to observe the request result with the provided CounterVec. The CounterVec
// must have valid metric and label names and must have zero, one, or two
// non-const non-curried labels. For those, the only allowed label names are
// "code" and "method". The function panics otherwise. Partitioning of the
// CounterVec happens by HTTP status code and/or HTTP method if the respective
// instance label names are present in the CounterVec. For unpartitioned
// counting, use a CounterVec with zero labels.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@ -110,14 +111,15 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler)
// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
// http.Handler to observe with the provided ObserverVec the request duration
// until the response headers are written. The ObserverVec must have zero, one,
// or two non-const non-curried labels. For those, the only allowed label names
// are "code" and "method". The function panics otherwise. The Observe method of
// the Observer in the ObserverVec is called with the request duration in
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
// respective instance label names are present in the ObserverVec. For
// unpartitioned observations, use an ObserverVec with zero labels. Note that
// partitioning of Histograms is expensive and should be used judiciously.
// until the response headers are written. The ObserverVec must have valid
// metric and label names and must have zero, one, or two non-const non-curried
// labels. For those, the only allowed label names are "code" and "method". The
// function panics otherwise. The Observe method of the Observer in the
// ObserverVec is called with the request duration in seconds. Partitioning
// happens by HTTP status code and/or HTTP method if the respective instance
// label names are present in the ObserverVec. For unpartitioned observations,
// use an ObserverVec with zero labels. Note that partitioning of Histograms is
// expensive and should be used judiciously.
//
// If the wrapped Handler panics before calling WriteHeader, no value is
// reported.
@ -139,15 +141,15 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
}
// InstrumentHandlerRequestSize is a middleware that wraps the provided
// http.Handler to observe the request size with the provided ObserverVec. The
// ObserverVec must have zero, one, or two non-const non-curried labels. For
// those, the only allowed label names are "code" and "method". The function
// panics otherwise. The Observe method of the Observer in the ObserverVec is
// called with the request size in bytes. Partitioning happens by HTTP status
// code and/or HTTP method if the respective instance label names are present in
// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
// labels. Note that partitioning of Histograms is expensive and should be used
// judiciously.
// http.Handler to observe the request size with the provided ObserverVec. The
// ObserverVec must have valid metric and label names and must have zero, one,
// or two non-const non-curried labels. For those, the only allowed label names
// are "code" and "method". The function panics otherwise. The Observe method of
// the Observer in the ObserverVec is called with the request size in
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
// respective instance label names are present in the ObserverVec. For
// unpartitioned observations, use an ObserverVec with zero labels. Note that
// partitioning of Histograms is expensive and should be used judiciously.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@ -174,15 +176,15 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler)
}
// InstrumentHandlerResponseSize is a middleware that wraps the provided
// http.Handler to observe the response size with the provided ObserverVec. The
// ObserverVec must have zero, one, or two non-const non-curried labels. For
// those, the only allowed label names are "code" and "method". The function
// panics otherwise. The Observe method of the Observer in the ObserverVec is
// called with the response size in bytes. Partitioning happens by HTTP status
// code and/or HTTP method if the respective instance label names are present in
// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
// labels. Note that partitioning of Histograms is expensive and should be used
// judiciously.
// http.Handler to observe the response size with the provided ObserverVec. The
// ObserverVec must have valid metric and label names and must have zero, one,
// or two non-const non-curried labels. For those, the only allowed label names
// are "code" and "method". The function panics otherwise. The Observe method of
// the Observer in the ObserverVec is called with the response size in
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
// respective instance label names are present in the ObserverVec. For
// unpartitioned observations, use an ObserverVec with zero labels. Note that
// partitioning of Histograms is expensive and should be used judiciously.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@ -198,6 +200,11 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler
})
}
// checkLabels returns whether the provided Collector has a non-const,
// non-curried label named "code" and/or "method". It panics if the provided
// Collector does not have a Desc or has more than one Desc or its Desc is
// invalid. It also panics if the Collector has any non-const, non-curried
// labels that are not named "code" or "method".
func checkLabels(c prometheus.Collector) (code bool, method bool) {
// TODO(beorn7): Remove this hacky way to check for instance labels
// once Descriptors can have their dimensionality queried.
@ -225,6 +232,10 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) {
close(descc)
// Make sure the Collector has a valid Desc by registering it with a
// temporary registry.
prometheus.NewRegistry().MustRegister(c)
// Create a ConstMetric with the Desc. Since we don't know how many
// variable labels there are, try for as long as it needs.
for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) {

View File

@ -26,7 +26,7 @@ import (
"unicode/utf8"
"github.com/cespare/xxhash/v2"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/expfmt"
@ -215,6 +215,8 @@ func (err AlreadyRegisteredError) Error() string {
// by a Gatherer to report multiple errors during MetricFamily gathering.
type MultiError []error
// Error formats the contained errors as a bullet point list, preceded by the
// total number of errors. Note that this results in a multi-line string.
func (errs MultiError) Error() string {
if len(errs) == 0 {
return ""

View File

@ -23,7 +23,7 @@ import (
"time"
"github.com/beorn7/perks/quantile"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
@ -55,7 +55,12 @@ type Summary interface {
Metric
Collector
// Observe adds a single observation to the summary.
// Observe adds a single observation to the summary. Observations are
// usually positive or zero. Negative observations are accepted but
// prevent current versions of Prometheus from properly detecting
// counter resets in the sum of observations. See
// https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
// for details.
Observe(float64)
}
@ -110,7 +115,7 @@ type SummaryOpts struct {
// better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
ConstLabels Labels
// Objectives defines the quantile rank estimates with their respective
@ -121,7 +126,9 @@ type SummaryOpts struct {
Objectives map[float64]float64
// MaxAge defines the duration for which an observation stays relevant
// for the summary. Must be positive. The default value is DefMaxAge.
// for the summary. Only applies to pre-calculated quantiles, does not
// apply to _sum and _count. Must be positive. The default value is
// DefMaxAge.
MaxAge time.Duration
// AgeBuckets is the number of buckets used to exclude observations that
@ -208,7 +215,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
// Use the lock-free implementation of a Summary without objectives.
s := &noObjectivesSummary{
desc: desc,
labelPairs: makeLabelPairs(desc, labelValues),
labelPairs: MakeLabelPairs(desc, labelValues),
counts: [2]*summaryCounts{{}, {}},
}
s.init(s) // Init self-collection.
@ -221,7 +228,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
objectives: opts.Objectives,
sortedObjectives: make([]float64, 0, len(opts.Objectives)),
labelPairs: makeLabelPairs(desc, labelValues),
labelPairs: MakeLabelPairs(desc, labelValues),
hotBuf: make([]float64, 0, opts.BufCap),
coldBuf: make([]float64, 0, opts.BufCap),
@ -513,7 +520,7 @@ func (s quantSort) Less(i, j int) bool {
// (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewSummaryVec.
type SummaryVec struct {
*metricVec
*MetricVec
}
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
@ -535,14 +542,14 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
opts.ConstLabels,
)
return &SummaryVec{
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
return newSummary(desc, opts, lvs...)
}),
}
}
// GetMetricWithLabelValues returns the Summary for the given slice of label
// values (same order as the VariableLabels in Desc). If that combination of
// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Summary is created.
//
// It is possible to call this method without using the returned Summary to only
@ -557,7 +564,7 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
// example.
//
// An error is returned if the number of label values is not the same as the
// number of VariableLabels in Desc (minus any curried labels).
// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -566,7 +573,7 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Observer), err
}
@ -574,19 +581,19 @@ func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
}
// GetMetricWith returns the Summary for the given Labels map (the label names
// must match those of the VariableLabels in Desc). If that label map is
// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Summary is created. Implications of
// creating a Summary without using it and keeping the Summary for later use are
// the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
// with those of the VariableLabels in Desc (minus any curried labels).
// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
metric, err := v.metricVec.getMetricWith(labels)
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Observer), err
}
@ -630,7 +637,7 @@ func (v *SummaryVec) With(labels Labels) Observer {
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) {
vec, err := v.curryWith(labels)
vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &SummaryVec{vec}, err
}
@ -716,7 +723,7 @@ func NewConstSummary(
count: count,
sum: sum,
quantiles: quantiles,
labelPairs: makeLabelPairs(desc, labelValues),
labelPairs: MakeLabelPairs(desc, labelValues),
}, nil
}

View File

@ -19,7 +19,7 @@ import (
"time"
"unicode/utf8"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
@ -63,7 +63,7 @@ func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *val
desc: desc,
valType: valueType,
function: function,
labelPairs: makeLabelPairs(desc, nil),
labelPairs: MakeLabelPairs(desc, nil),
}
result.init(result)
return result
@ -95,7 +95,7 @@ func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues
desc: desc,
valType: valueType,
val: value,
labelPairs: makeLabelPairs(desc, labelValues),
labelPairs: MakeLabelPairs(desc, labelValues),
}, nil
}
@ -145,7 +145,14 @@ func populateMetric(
return nil
}
func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
// MakeLabelPairs is a helper function to create protobuf LabelPairs from the
// variable and constant labels in the provided Desc. The values for the
// variable labels are defined by the labelValues slice, which must be in the
// same order as the corresponding variable labels in the Desc.
//
// This function is only needed for custom Metric implementations. See MetricVec
// example.
func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
if totalLen == 0 {
// Super fast path.

View File

@ -20,12 +20,20 @@ import (
"github.com/prometheus/common/model"
)
// metricVec is a Collector to bundle metrics of the same name that differ in
// their label values. metricVec is not used directly (and therefore
// unexported). It is used as a building block for implementations of vectors of
// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec.
// It also handles label currying.
type metricVec struct {
// MetricVec is a Collector to bundle metrics of the same name that differ in
// their label values. MetricVec is not used directly but as a building block
// for implementations of vectors of a given metric type, like GaugeVec,
// CounterVec, SummaryVec, and HistogramVec. It is exported so that it can be
// used for custom Metric implementations.
//
// To create a FooVec for custom Metric Foo, embed a pointer to MetricVec in
// FooVec and initialize it with NewMetricVec. Implement wrappers for
// GetMetricWithLabelValues and GetMetricWith that return (Foo, error) rather
// than (Metric, error). Similarly, create a wrapper for CurryWith that returns
// (*FooVec, error) rather than (*MetricVec, error). It is recommended to also
// add the convenience methods WithLabelValues, With, and MustCurryWith, which
// panic instead of returning errors. See also the MetricVec example.
type MetricVec struct {
*metricMap
curry []curriedLabelValue
@ -35,9 +43,9 @@ type metricVec struct {
hashAddByte func(h uint64, b byte) uint64
}
// newMetricVec returns an initialized metricVec.
func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
return &metricVec{
// NewMetricVec returns an initialized metricVec.
func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
return &MetricVec{
metricMap: &metricMap{
metrics: map[uint64][]metricWithLabelValues{},
desc: desc,
@ -63,7 +71,7 @@ func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
// See also the CounterVec example.
func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
h, err := m.hashLabelValues(lvs)
if err != nil {
return false
@ -82,7 +90,7 @@ func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
//
// This method is used for the same purpose as DeleteLabelValues(...string). See
// there for pros and cons of the two methods.
func (m *metricVec) Delete(labels Labels) bool {
func (m *MetricVec) Delete(labels Labels) bool {
h, err := m.hashLabels(labels)
if err != nil {
return false
@ -95,15 +103,32 @@ func (m *metricVec) Delete(labels Labels) bool {
// show up in GoDoc.
// Describe implements Collector.
func (m *metricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) }
func (m *MetricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) }
// Collect implements Collector.
func (m *metricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) }
func (m *MetricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) }
// Reset deletes all metrics in this vector.
func (m *metricVec) Reset() { m.metricMap.Reset() }
func (m *MetricVec) Reset() { m.metricMap.Reset() }
func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
// CurryWith returns a vector curried with the provided labels, i.e. the
// returned vector has those labels pre-set for all labeled operations performed
// on it. The cardinality of the curried vector is reduced accordingly. The
// order of the remaining labels stays the same (just with the curried labels
// taken out of the sequence which is relevant for the
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
// vector, but only with labels not yet used for currying before.
//
// The metrics contained in the MetricVec are shared between the curried and
// uncurried vectors. They are just accessed differently. Curried and uncurried
// vectors behave identically in terms of collection. Only one must be
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
//
// Note that CurryWith is usually not called directly but through a wrapper
// around MetricVec, implementing a vector for a specific Metric
// implementation, for example GaugeVec.
func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
var (
newCurry []curriedLabelValue
oldCurry = m.curry
@ -128,7 +153,7 @@ func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
return nil, fmt.Errorf("%d unknown label(s) found during currying", l)
}
return &metricVec{
return &MetricVec{
metricMap: m.metricMap,
curry: newCurry,
hashAdd: m.hashAdd,
@ -136,7 +161,34 @@ func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
}, nil
}
func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
// GetMetricWithLabelValues returns the Metric for the given slice of label
// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Metric is created (by
// calling the newMetric function provided during construction of the
// MetricVec).
//
// It is possible to call this method without using the returned Metric to only
// create the new Metric but leave it in its initial state.
//
// Keeping the Metric for later use is possible (and should be considered if
// performance is critical), but keep in mind that Reset, DeleteLabelValues and
// Delete can be used to delete the Metric from the MetricVec. In that case, the
// Metric will still exist, but it will not be exported anymore, even if a
// Metric with the same label values is created later.
//
// An error is returned if the number of label values is not the same as the
// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
// an alternative to avoid that type of mistake. For higher label numbers, the
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
//
// Note that GetMetricWithLabelValues is usually not called directly but through
// a wrapper around MetricVec, implementing a vector for a specific Metric
// implementation, for example GaugeVec.
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
h, err := m.hashLabelValues(lvs)
if err != nil {
return nil, err
@ -145,7 +197,23 @@ func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil
}
func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
// GetMetricWith returns the Metric for the given Labels map (the label names
// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Metric is created. Implications of
// creating a Metric without using it and keeping the Metric for later use
// are the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
//
// Note that GetMetricWith is usually not called directly but through a wrapper
// around MetricVec, implementing a vector for a specific Metric implementation,
// for example GaugeVec.
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
h, err := m.hashLabels(labels)
if err != nil {
return nil, err
@ -154,7 +222,7 @@ func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil
}
func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
return 0, err
}
@ -177,7 +245,7 @@ func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
return h, nil
}
func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
return 0, err
}
@ -276,7 +344,9 @@ func (m *metricMap) deleteByHashWithLabelValues(
}
if len(metrics) > 1 {
old := metrics
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
old[len(old)-1] = metricWithLabelValues{}
} else {
delete(m.metrics, h)
}
@ -302,7 +372,9 @@ func (m *metricMap) deleteByHashWithLabels(
}
if len(metrics) > 1 {
old := metrics
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
old[len(old)-1] = metricWithLabelValues{}
} else {
delete(m.metrics, h)
}

View File

@ -17,7 +17,7 @@ import (
"fmt"
"sort"
//lint:ignore SA1019 Need to keep deprecated package for compatibility.
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
@ -32,7 +32,9 @@ import (
// in a no-op Registerer.
//
// WrapRegistererWith provides a way to add fixed labels to a subset of
// Collectors. It should not be used to add fixed labels to all metrics exposed.
// Collectors. It should not be used to add fixed labels to all metrics
// exposed. See also
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
//
// Conflicts between Collectors registered through the original Registerer with
// Collectors registered through the wrapping Registerer will still be

View File

@ -164,7 +164,7 @@ func (sd *SampleDecoder) Decode(s *model.Vector) error {
}
// ExtractSamples builds a slice of samples from the provided metric
// families. If an error occurrs during sample extraction, it continues to
// families. If an error occurs during sample extraction, it continues to
// extract from the remaining metric families. The returned error is the last
// error that has occurred.
func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) {

View File

@ -299,6 +299,17 @@ func (p *TextParser) startLabelName() stateFn {
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
return nil
}
// Check for duplicate label names.
labels := make(map[string]struct{})
for _, l := range p.currentMetric.Label {
lName := l.GetName()
if _, exists := labels[lName]; !exists {
labels[lName] = struct{}{}
} else {
p.parseError(fmt.Sprintf("duplicate label names for metric %q", p.currentMF.GetName()))
return nil
}
}
return p.startLabelValue
}

View File

@ -20,7 +20,7 @@ const (
prime64 = 1099511628211
)
// hashNew initializies a new fnv64a hash value.
// hashNew initializes a new fnv64a hash value.
func hashNew() uint64 {
return offset64
}

View File

@ -45,6 +45,14 @@ const (
// scrape a target.
MetricsPathLabel = "__metrics_path__"
// ScrapeIntervalLabel is the name of the label that holds the scrape interval
// used to scrape a target.
ScrapeIntervalLabel = "__scrape_interval__"
// ScrapeTimeoutLabel is the name of the label that holds the scrape
// timeout used to scrape a target.
ScrapeTimeoutLabel = "__scrape_timeout__"
// ReservedLabelPrefix is a prefix which is not legal in user-supplied
// label names.
ReservedLabelPrefix = "__"

View File

@ -14,6 +14,8 @@
package model
import (
"encoding/json"
"errors"
"fmt"
"math"
"regexp"
@ -181,77 +183,118 @@ func (d *Duration) Type() string {
return "duration"
}
var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$")
var durationRE = regexp.MustCompile("^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$")
// ParseDuration parses a string into a time.Duration, assuming that a year
// always has 365d, a week always has 7d, and a day always has 24h.
func ParseDuration(durationStr string) (Duration, error) {
// Allow 0 without a unit.
if durationStr == "0" {
switch durationStr {
case "0":
// Allow 0 without a unit.
return 0, nil
case "":
return 0, fmt.Errorf("empty duration string")
}
matches := durationRE.FindStringSubmatch(durationStr)
if len(matches) != 3 {
if matches == nil {
return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
}
var (
n, _ = strconv.Atoi(matches[1])
dur = time.Duration(n) * time.Millisecond
)
switch unit := matches[2]; unit {
case "y":
dur *= 1000 * 60 * 60 * 24 * 365
case "w":
dur *= 1000 * 60 * 60 * 24 * 7
case "d":
dur *= 1000 * 60 * 60 * 24
case "h":
dur *= 1000 * 60 * 60
case "m":
dur *= 1000 * 60
case "s":
dur *= 1000
case "ms":
// Value already correct
default:
return 0, fmt.Errorf("invalid time unit in duration string: %q", unit)
var dur time.Duration
// Parse the match at pos `pos` in the regex and use `mult` to turn that
// into ms, then add that value to the total parsed duration.
var overflowErr error
m := func(pos int, mult time.Duration) {
if matches[pos] == "" {
return
}
n, _ := strconv.Atoi(matches[pos])
// Check if the provided duration overflows time.Duration (> ~ 290years).
if n > int((1<<63-1)/mult/time.Millisecond) {
overflowErr = errors.New("duration out of range")
}
d := time.Duration(n) * time.Millisecond
dur += d * mult
if dur < 0 {
overflowErr = errors.New("duration out of range")
}
}
return Duration(dur), nil
m(2, 1000*60*60*24*365) // y
m(4, 1000*60*60*24*7) // w
m(6, 1000*60*60*24) // d
m(8, 1000*60*60) // h
m(10, 1000*60) // m
m(12, 1000) // s
m(14, 1) // ms
return Duration(dur), overflowErr
}
func (d Duration) String() string {
var (
ms = int64(time.Duration(d) / time.Millisecond)
unit = "ms"
ms = int64(time.Duration(d) / time.Millisecond)
r = ""
)
if ms == 0 {
return "0s"
}
factors := map[string]int64{
"y": 1000 * 60 * 60 * 24 * 365,
"w": 1000 * 60 * 60 * 24 * 7,
"d": 1000 * 60 * 60 * 24,
"h": 1000 * 60 * 60,
"m": 1000 * 60,
"s": 1000,
"ms": 1,
f := func(unit string, mult int64, exact bool) {
if exact && ms%mult != 0 {
return
}
if v := ms / mult; v > 0 {
r += fmt.Sprintf("%d%s", v, unit)
ms -= v * mult
}
}
switch int64(0) {
case ms % factors["y"]:
unit = "y"
case ms % factors["w"]:
unit = "w"
case ms % factors["d"]:
unit = "d"
case ms % factors["h"]:
unit = "h"
case ms % factors["m"]:
unit = "m"
case ms % factors["s"]:
unit = "s"
// Only format years and weeks if the remainder is zero, as it is often
// easier to read 90d than 12w6d.
f("y", 1000*60*60*24*365, true)
f("w", 1000*60*60*24*7, true)
f("d", 1000*60*60*24, false)
f("h", 1000*60*60, false)
f("m", 1000*60, false)
f("s", 1000, false)
f("ms", 1, false)
return r
}
// MarshalJSON implements the json.Marshaler interface.
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *Duration) UnmarshalJSON(bytes []byte) error {
var s string
if err := json.Unmarshal(bytes, &s); err != nil {
return err
}
return fmt.Sprintf("%v%v", ms/factors[unit], unit)
dur, err := ParseDuration(s)
if err != nil {
return err
}
*d = dur
return nil
}
// MarshalText implements the encoding.TextMarshaler interface.
func (d *Duration) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (d *Duration) UnmarshalText(text []byte) error {
var err error
*d, err = ParseDuration(string(text))
return err
}
// MarshalYAML implements the yaml.Marshaler interface.

View File

@ -78,7 +78,7 @@ ifneq ($(shell which gotestsum),)
endif
endif
PROMU_VERSION ?= 0.5.0
PROMU_VERSION ?= 0.7.0
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
GOLANGCI_LINT :=
@ -245,10 +245,12 @@ common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)"
DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION)))
.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS)
common-docker-tag-latest: $(TAG_DOCKER_ARCHS)
$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"
.PHONY: common-docker-manifest
common-docker-manifest:

6
vendor/github.com/prometheus/procfs/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,6 @@
# Reporting a security issue
The Prometheus security policy, including how to report vulnerabilities, can be
found here:
https://prometheus.io/docs/operating/security/

View File

@ -36,7 +36,7 @@ type ARPEntry struct {
func (fs FS) GatherARPEntries() ([]ARPEntry, error) {
data, err := ioutil.ReadFile(fs.proc.Path("net/arp"))
if err != nil {
return nil, fmt.Errorf("error reading arp %s: %s", fs.proc.Path("net/arp"), err)
return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err)
}
return parseARPEntries(data)
@ -59,7 +59,7 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) {
} else if width == expectedDataWidth {
entry, err := parseARPEntry(columns)
if err != nil {
return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %s", err)
return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %w", err)
}
entries = append(entries, entry)
} else {

View File

@ -74,7 +74,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
for i := 0; i < arraySize; i++ {
sizes[i], err = strconv.ParseFloat(parts[i+4], 64)
if err != nil {
return nil, fmt.Errorf("invalid value in buddyinfo: %s", err)
return nil, fmt.Errorf("invalid value in buddyinfo: %w", err)
}
}

View File

@ -19,6 +19,7 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
@ -77,7 +78,7 @@ func parseCPUInfoX86(info []byte) ([]CPUInfo, error) {
// find the first "processor" line
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
v, err := strconv.ParseUint(field[1], 0, 32)
@ -192,7 +193,7 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
firstLine := firstNonEmptyLine(scanner)
match, _ := regexp.MatchString("^[Pp]rocessor", firstLine)
if !match || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
cpuinfo := []CPUInfo{}
@ -256,7 +257,7 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) {
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "vendor_id") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
cpuinfo := []CPUInfo{}
@ -281,7 +282,7 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) {
if strings.HasPrefix(line, "processor") {
match := cpuinfoS390XProcessorRegexp.FindStringSubmatch(line)
if len(match) < 2 {
return nil, errors.New("Invalid line found in cpuinfo: " + line)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
cpu := commonCPUInfo
v, err := strconv.ParseUint(match[1], 0, 32)
@ -313,6 +314,22 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) {
return nil, err
}
cpuinfo[i].CPUMHz = v
case "physical id":
cpuinfo[i].PhysicalID = field[1]
case "core id":
cpuinfo[i].CoreID = field[1]
case "cpu cores":
v, err := strconv.ParseUint(field[1], 0, 32)
if err != nil {
return nil, err
}
cpuinfo[i].CPUCores = uint(v)
case "siblings":
v, err := strconv.ParseUint(field[1], 0, 32)
if err != nil {
return nil, err
}
cpuinfo[i].Siblings = uint(v)
}
}
@ -325,7 +342,7 @@ func parseCPUInfoMips(info []byte) ([]CPUInfo, error) {
// find the first "processor" line
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
cpuinfo := []CPUInfo{}
@ -367,7 +384,7 @@ func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) {
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
v, err := strconv.ParseUint(field[1], 0, 32)
@ -412,7 +429,7 @@ func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) {
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
v, err := strconv.ParseUint(field[1], 0, 32)

View File

@ -1,4 +1,4 @@
// Copyright 2019 The Prometheus Authors
// Copyright 2020 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
@ -11,12 +11,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !go1.12
// +build linux
// +build riscv riscv64
package prometheus
package procfs
// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go versions before
// 1.12. Remove this whole file once the minimum supported Go version is 1.12.
func readBuildInfo() (path, version, sum string) {
return "unknown", "unknown", "unknown"
}
var parseCPUInfo = parseCPUInfoRISCV

View File

@ -55,12 +55,12 @@ func (fs FS) Crypto() ([]Crypto, error) {
path := fs.proc.Path("crypto")
b, err := util.ReadFileNoStat(path)
if err != nil {
return nil, fmt.Errorf("error reading crypto %s: %s", path, err)
return nil, fmt.Errorf("error reading crypto %q: %w", path, err)
}
crypto, err := parseCrypto(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("error parsing crypto %s: %s", path, err)
return nil, fmt.Errorf("error parsing crypto %q: %w", path, err)
}
return crypto, nil

View File

@ -111,7 +111,7 @@ Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 62898 62898 processes
Max open files 2048 4096 files
Max locked memory 65536 65536 bytes
Max locked memory 18446744073708503040 18446744073708503040 bytes
Max address space 8589934592 unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 62898 62898 signals
@ -1080,7 +1080,6 @@ internal : yes
type : skcipher
async : yes
blocksize : 1
min keysize : 16
max keysize : 32
ivsize : 16
chunksize : 16
@ -1839,6 +1838,7 @@ min keysize : 16
max keysize : 32
Mode: 444
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/diskstats
Lines: 52
@ -2129,6 +2129,24 @@ Lines: 6
4 1FB3C 0 1282A8F 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/protocols
Lines: 14
protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em
PACKET 1344 2 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n
PINGv6 1112 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n
RAWv6 1112 1 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n
UDPLITEv6 1216 0 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n
UDPv6 1216 10 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n
TCPv6 2144 1937 1225378 no 320 yes kernel y y y y y y y y y y y y y n y y y y y
UNIX 1024 120 -1 NI 0 yes kernel n n n n n n n n n n n n n n n n n n n
UDP-Lite 1024 0 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n
PING 904 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n
RAW 912 0 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n
UDP 1024 73 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n
TCP 1984 93064 1225378 yes 320 yes kernel y y y y y y y y y y y y y n y y y y y
NETLINK 1040 16 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/proc/net/rpc
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -2186,10 +2204,25 @@ Lines: 1
00015c73 00020e76 F0000769 00000000
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/tcp
Lines: 4
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/tcp6
Lines: 3
sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0
6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/udp
Lines: 4
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 0A000005:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0
Mode: 644
@ -2292,6 +2325,312 @@ Mode: 644
Path: fixtures/proc/self
SymlinkTo: 26231
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/slabinfo
Lines: 302
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
pid_3 375 532 576 28 4 : tunables 0 0 0 : slabdata 19 19 0
pid_2 3 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0
nvidia_p2p_page_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
nvidia_pte_cache 9022 9152 368 22 2 : tunables 0 0 0 : slabdata 416 416 0
nvidia_stack_cache 321 326 12624 2 8 : tunables 0 0 0 : slabdata 163 163 0
kvm_async_pf 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0
kvm_vcpu 0 0 15552 2 8 : tunables 0 0 0 : slabdata 0 0 0
kvm_mmu_page_header 0 0 504 32 4 : tunables 0 0 0 : slabdata 0 0 0
pte_list_desc 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
x86_emulator 0 0 3024 10 8 : tunables 0 0 0 : slabdata 0 0 0
x86_fpu 0 0 4608 7 8 : tunables 0 0 0 : slabdata 0 0 0
iwl_cmd_pool:0000:04:00.0 0 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0
ext4_groupinfo_4k 3719 3740 480 34 4 : tunables 0 0 0 : slabdata 110 110 0
bio-6 32 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0
bio-5 16 48 1344 24 8 : tunables 0 0 0 : slabdata 2 2 0
bio-4 17 92 1408 23 8 : tunables 0 0 0 : slabdata 4 4 0
fat_inode_cache 0 0 1056 31 8 : tunables 0 0 0 : slabdata 0 0 0
fat_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
ovl_aio_req 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
ovl_inode 0 0 1000 32 8 : tunables 0 0 0 : slabdata 0 0 0
squashfs_inode_cache 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0
fuse_request 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0
fuse_inode 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0
xfs_dqtrx 0 0 864 37 8 : tunables 0 0 0 : slabdata 0 0 0
xfs_dquot 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0
xfs_buf 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_bui_item 0 0 544 30 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_bud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_cui_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_cud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_rui_item 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0
xfs_rud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_icr 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_ili 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_inode 0 0 1344 24 8 : tunables 0 0 0 : slabdata 0 0 0
xfs_efi_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_efd_item 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_buf_item 0 0 608 26 4 : tunables 0 0 0 : slabdata 0 0 0
xf_trans 0 0 568 28 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_ifork 0 0 376 21 2 : tunables 0 0 0 : slabdata 0 0 0
xfs_da_state 0 0 816 20 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_btree_cur 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0
xfs_bmap_free_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0
xfs_log_ticket 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0
nfs_direct_cache 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0
nfs_commit_data 4 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0
nfs_write_data 32 50 1280 25 8 : tunables 0 0 0 : slabdata 2 2 0
nfs_read_data 0 0 1280 25 8 : tunables 0 0 0 : slabdata 0 0 0
nfs_inode_cache 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0
nfs_page 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
rpc_inode_cache 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0
rpc_buffers 8 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0
rpc_tasks 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0
fscache_cookie_jar 1 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0
jfs_mp 32 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0
jfs_ip 0 0 1592 20 8 : tunables 0 0 0 : slabdata 0 0 0
reiser_inode_cache 0 0 1096 29 8 : tunables 0 0 0 : slabdata 0 0 0
btrfs_end_io_wq 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_prelim_ref 0 0 424 38 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_delayed_extent_op 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
btrfs_delayed_data_ref 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_delayed_tree_ref 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_delayed_ref_head 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_inode_defrag 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0
btrfs_delayed_node 0 0 648 25 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_ordered_extent 0 0 752 21 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_extent_map 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_extent_state 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0
bio-3 35 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0
btrfs_extent_buffer 0 0 600 27 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_free_space_bitmap 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0
btrfs_free_space 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_path 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_trans_handle 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0
btrfs_inode 0 0 1496 21 8 : tunables 0 0 0 : slabdata 0 0 0
ext4_inode_cache 84136 84755 1400 23 8 : tunables 0 0 0 : slabdata 3685 3685 0
ext4_free_data 22 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0
ext4_allocation_context 0 70 464 35 4 : tunables 0 0 0 : slabdata 2 2 0
ext4_prealloc_space 24 74 440 37 4 : tunables 0 0 0 : slabdata 2 2 0
ext4_system_zone 267 273 376 21 2 : tunables 0 0 0 : slabdata 13 13 0
ext4_io_end_vec 0 88 368 22 2 : tunables 0 0 0 : slabdata 4 4 0
ext4_io_end 0 80 400 20 2 : tunables 0 0 0 : slabdata 4 4 0
ext4_bio_post_read_ctx 128 147 384 21 2 : tunables 0 0 0 : slabdata 7 7 0
ext4_pending_reservation 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
ext4_extent_status 79351 79422 376 21 2 : tunables 0 0 0 : slabdata 3782 3782 0
jbd2_transaction_s 44 100 640 25 4 : tunables 0 0 0 : slabdata 4 4 0
jbd2_inode 6785 6840 400 20 2 : tunables 0 0 0 : slabdata 342 342 0
jbd2_journal_handle 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0
jbd2_journal_head 824 1944 448 36 4 : tunables 0 0 0 : slabdata 54 54 0
jbd2_revoke_table_s 4 23 352 23 2 : tunables 0 0 0 : slabdata 1 1 0
jbd2_revoke_record_s 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0
ext2_inode_cache 0 0 1144 28 8 : tunables 0 0 0 : slabdata 0 0 0
mbcache 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0
dm_thin_new_mapping 0 152 424 38 4 : tunables 0 0 0 : slabdata 4 4 0
dm_snap_pending_exception 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0
dm_exception 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
dm_dirty_log_flush_entry 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
dm_bio_prison_cell_v2 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0
dm_bio_prison_cell 0 148 432 37 4 : tunables 0 0 0 : slabdata 4 4 0
kcopyd_job 0 8 3648 8 8 : tunables 0 0 0 : slabdata 1 1 0
io 0 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0
dm_uevent 0 0 3224 10 8 : tunables 0 0 0 : slabdata 0 0 0
dax_cache 1 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0
aic94xx_ascb 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
aic94xx_dma_token 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0
asd_sas_event 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
sas_task 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0
qla2xxx_srbs 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0
sd_ext_cdb 2 22 368 22 2 : tunables 0 0 0 : slabdata 1 1 0
scsi_sense_cache 258 288 512 32 4 : tunables 0 0 0 : slabdata 9 9 0
virtio_scsi_cmd 64 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0
L2TP/IPv6 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0
L2TP/IP 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0
ip6-frags 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0
fib6_nodes 5 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0
ip6_dst_cache 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0
ip6_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
PINGv6 0 0 1600 20 8 : tunables 0 0 0 : slabdata 0 0 0
RAWv6 25 40 1600 20 8 : tunables 0 0 0 : slabdata 2 2 0
UDPLITEv6 0 0 1728 18 8 : tunables 0 0 0 : slabdata 0 0 0
UDPv6 3 54 1728 18 8 : tunables 0 0 0 : slabdata 3 3 0
tw_sock_TCPv6 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
request_sock_TCPv6 0 0 632 25 4 : tunables 0 0 0 : slabdata 0 0 0
TCPv6 0 33 2752 11 8 : tunables 0 0 0 : slabdata 3 3 0
uhci_urb_priv 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0
sgpool-128 2 14 4544 7 8 : tunables 0 0 0 : slabdata 2 2 0
sgpool-64 2 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0
sgpool-32 2 44 1472 22 8 : tunables 0 0 0 : slabdata 2 2 0
sgpool-16 2 68 960 34 8 : tunables 0 0 0 : slabdata 2 2 0
sgpool-8 2 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0
btree_node 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
bfq_io_cq 0 0 488 33 4 : tunables 0 0 0 : slabdata 0 0 0
bfq_queue 0 0 848 38 8 : tunables 0 0 0 : slabdata 0 0 0
mqueue_inode_cache 1 24 1344 24 8 : tunables 0 0 0 : slabdata 1 1 0
isofs_inode_cache 0 0 968 33 8 : tunables 0 0 0 : slabdata 0 0 0
io_kiocb 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0
kioctx 0 30 1088 30 8 : tunables 0 0 0 : slabdata 1 1 0
aio_kiocb 0 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0
userfaultfd_ctx_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
fanotify_path_event 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0
fanotify_fid_event 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0
fsnotify_mark 0 0 408 20 2 : tunables 0 0 0 : slabdata 0 0 0
dnotify_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0
dnotify_struct 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
dio 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0
bio-2 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0
fasync_cache 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0
audit_tree_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0
pid_namespace 30 34 480 34 4 : tunables 0 0 0 : slabdata 1 1 0
posix_timers_cache 0 27 592 27 4 : tunables 0 0 0 : slabdata 1 1 0
iommu_devinfo 24 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0
iommu_domain 10 10 3264 10 8 : tunables 0 0 0 : slabdata 1 1 0
iommu_iova 8682 8748 448 36 4 : tunables 0 0 0 : slabdata 243 243 0
UNIX 529 814 1472 22 8 : tunables 0 0 0 : slabdata 37 37 0
ip4-frags 0 0 536 30 4 : tunables 0 0 0 : slabdata 0 0 0
ip_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
UDP-Lite 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0
tcp_bind_bucket 7 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0
inet_peer_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
xfrm_dst_cache 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0
xfrm_state 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0
ip_fib_trie 7 21 384 21 2 : tunables 0 0 0 : slabdata 1 1 0
ip_fib_alias 9 20 392 20 2 : tunables 0 0 0 : slabdata 1 1 0
ip_dst_cache 27 84 576 28 4 : tunables 0 0 0 : slabdata 3 3 0
PING 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0
RAW 32 46 1408 23 8 : tunables 0 0 0 : slabdata 2 2 0
UDP 11 168 1536 21 8 : tunables 0 0 0 : slabdata 8 8 0
tw_sock_TCP 1 56 576 28 4 : tunables 0 0 0 : slabdata 2 2 0
request_sock_TCP 0 25 632 25 4 : tunables 0 0 0 : slabdata 1 1 0
TCP 10 60 2624 12 8 : tunables 0 0 0 : slabdata 5 5 0
hugetlbfs_inode_cache 2 35 928 35 8 : tunables 0 0 0 : slabdata 1 1 0
dquot 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0
bio-1 32 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0
eventpoll_pwq 409 600 408 20 2 : tunables 0 0 0 : slabdata 30 30 0
eventpoll_epi 408 672 576 28 4 : tunables 0 0 0 : slabdata 24 24 0
inotify_inode_mark 58 195 416 39 4 : tunables 0 0 0 : slabdata 5 5 0
scsi_data_buffer 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0
bio_crypt_ctx 128 147 376 21 2 : tunables 0 0 0 : slabdata 7 7 0
request_queue 29 39 2408 13 8 : tunables 0 0 0 : slabdata 3 3 0
blkdev_ioc 81 148 440 37 4 : tunables 0 0 0 : slabdata 4 4 0
bio-0 125 200 640 25 4 : tunables 0 0 0 : slabdata 8 8 0
biovec-max 166 196 4544 7 8 : tunables 0 0 0 : slabdata 28 28 0
biovec-128 0 52 2496 13 8 : tunables 0 0 0 : slabdata 4 4 0
biovec-64 0 88 1472 22 8 : tunables 0 0 0 : slabdata 4 4 0
biovec-16 0 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0
bio_integrity_payload 4 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0
khugepaged_mm_slot 59 180 448 36 4 : tunables 0 0 0 : slabdata 5 5 0
ksm_mm_slot 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0
ksm_stable_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0
ksm_rmap_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0
user_namespace 2 37 864 37 8 : tunables 0 0 0 : slabdata 1 1 0
uid_cache 5 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0
dmaengine-unmap-256 1 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0
dmaengine-unmap-128 1 22 1472 22 8 : tunables 0 0 0 : slabdata 1 1 0
dmaengine-unmap-16 1 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0
dmaengine-unmap-2 1 36 448 36 4 : tunables 0 0 0 : slabdata 1 1 0
audit_buffer 0 22 360 22 2 : tunables 0 0 0 : slabdata 1 1 0
sock_inode_cache 663 1170 1216 26 8 : tunables 0 0 0 : slabdata 45 45 0
skbuff_ext_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0
skbuff_fclone_cache 1 72 896 36 8 : tunables 0 0 0 : slabdata 2 2 0
skbuff_head_cache 3 650 640 25 4 : tunables 0 0 0 : slabdata 26 26 0
configfs_dir_cache 7 38 424 38 4 : tunables 0 0 0 : slabdata 1 1 0
file_lock_cache 27 116 552 29 4 : tunables 0 0 0 : slabdata 4 4 0
file_lock_ctx 106 120 392 20 2 : tunables 0 0 0 : slabdata 6 6 0
fsnotify_mark_connector 52 66 368 22 2 : tunables 0 0 0 : slabdata 3 3 0
net_namespace 1 6 5312 6 8 : tunables 0 0 0 : slabdata 1 1 0
task_delay_info 784 1560 416 39 4 : tunables 0 0 0 : slabdata 40 40 0
taskstats 45 92 688 23 4 : tunables 0 0 0 : slabdata 4 4 0
proc_dir_entry 678 682 528 31 4 : tunables 0 0 0 : slabdata 22 22 0
pde_opener 0 189 376 21 2 : tunables 0 0 0 : slabdata 9 9 0
proc_inode_cache 7150 8250 992 33 8 : tunables 0 0 0 : slabdata 250 250 0
seq_file 60 735 456 35 4 : tunables 0 0 0 : slabdata 21 21 0
sigqueue 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0
bdev_cache 36 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0
shmem_inode_cache 1599 2208 1016 32 8 : tunables 0 0 0 : slabdata 69 69 0
kernfs_iattrs_cache 1251 1254 424 38 4 : tunables 0 0 0 : slabdata 33 33 0
kernfs_node_cache 52898 52920 464 35 4 : tunables 0 0 0 : slabdata 1512 1512 0
mnt_cache 42 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0
filp 4314 6371 704 23 4 : tunables 0 0 0 : slabdata 277 277 0
inode_cache 28695 29505 920 35 8 : tunables 0 0 0 : slabdata 843 843 0
dentry 166069 169074 528 31 4 : tunables 0 0 0 : slabdata 5454 5454 0
names_cache 0 35 4544 7 8 : tunables 0 0 0 : slabdata 5 5 0
hashtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0
ebitmap_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0
avtab_extended_perms 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
avtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0
avc_xperms_data 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
avc_xperms_decision_node 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0
avc_xperms_node 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0
avc_node 37 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0
iint_cache 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0
lsm_inode_cache 122284 122340 392 20 2 : tunables 0 0 0 : slabdata 6117 6117 0
lsm_file_cache 4266 4485 352 23 2 : tunables 0 0 0 : slabdata 195 195 0
key_jar 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0
buffer_head 255622 257076 440 37 4 : tunables 0 0 0 : slabdata 6948 6948 0
uts_namespace 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0
nsproxy 31 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0
vm_area_struct 39115 43214 528 31 4 : tunables 0 0 0 : slabdata 1394 1394 0
mm_struct 96 529 1408 23 8 : tunables 0 0 0 : slabdata 23 23 0
fs_cache 102 756 448 36 4 : tunables 0 0 0 : slabdata 21 21 0
files_cache 102 588 1152 28 8 : tunables 0 0 0 : slabdata 21 21 0
signal_cache 266 672 1536 21 8 : tunables 0 0 0 : slabdata 32 32 0
sighand_cache 266 507 2496 13 8 : tunables 0 0 0 : slabdata 39 39 0
task_struct 783 963 10240 3 8 : tunables 0 0 0 : slabdata 321 321 0
cred_jar 364 952 576 28 4 : tunables 0 0 0 : slabdata 34 34 0
anon_vma_chain 63907 67821 416 39 4 : tunables 0 0 0 : slabdata 1739 1739 0
anon_vma 25891 28899 416 39 4 : tunables 0 0 0 : slabdata 741 741 0
pid 408 992 512 32 4 : tunables 0 0 0 : slabdata 31 31 0
Acpi-Operand 6682 6740 408 20 2 : tunables 0 0 0 : slabdata 337 337 0
Acpi-ParseExt 0 39 416 39 4 : tunables 0 0 0 : slabdata 1 1 0
Acpi-Parse 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0
Acpi-State 0 78 416 39 4 : tunables 0 0 0 : slabdata 2 2 0
Acpi-Namespace 3911 3948 384 21 2 : tunables 0 0 0 : slabdata 188 188 0
trace_event_file 2638 2660 424 38 4 : tunables 0 0 0 : slabdata 70 70 0
ftrace_event_field 6592 6594 384 21 2 : tunables 0 0 0 : slabdata 314 314 0
pool_workqueue 41 64 1024 32 8 : tunables 0 0 0 : slabdata 2 2 0
radix_tree_node 21638 24045 912 35 8 : tunables 0 0 0 : slabdata 687 687 0
task_group 48 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0
vmap_area 4411 4680 400 20 2 : tunables 0 0 0 : slabdata 234 234 0
dma-kmalloc-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-128 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-64 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0
dma-kmalloc-96 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-128 31 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0
kmalloc-rcl-96 3371 3626 432 37 4 : tunables 0 0 0 : slabdata 98 98 0
kmalloc-rcl-64 2080 2272 512 32 4 : tunables 0 0 0 : slabdata 71 71 0
kmalloc-rcl-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-8k 133 140 24576 1 8 : tunables 0 0 0 : slabdata 140 140 0
kmalloc-4k 403 444 12288 2 8 : tunables 0 0 0 : slabdata 222 222 0
kmalloc-2k 2391 2585 6144 5 8 : tunables 0 0 0 : slabdata 517 517 0
kmalloc-1k 2163 2420 3072 10 8 : tunables 0 0 0 : slabdata 242 242 0
kmalloc-512 2972 3633 1536 21 8 : tunables 0 0 0 : slabdata 173 173 0
kmalloc-256 1841 1856 1024 32 8 : tunables 0 0 0 : slabdata 58 58 0
kmalloc-192 2165 2914 528 31 4 : tunables 0 0 0 : slabdata 94 94 0
kmalloc-128 1137 1175 640 25 4 : tunables 0 0 0 : slabdata 47 47 0
kmalloc-96 1925 2590 432 37 4 : tunables 0 0 0 : slabdata 70 70 0
kmalloc-64 9433 10688 512 32 4 : tunables 0 0 0 : slabdata 334 334 0
kmalloc-32 9098 10062 416 39 4 : tunables 0 0 0 : slabdata 258 258 0
kmalloc-16 10914 10956 368 22 2 : tunables 0 0 0 : slabdata 498 498 0
kmalloc-8 7576 7705 344 23 2 : tunables 0 0 0 : slabdata 335 335 0
kmem_cache_node 904 928 512 32 4 : tunables 0 0 0 : slabdata 29 29 0
kmem_cache 904 936 832 39 8 : tunables 0 0 0 : slabdata 24 24 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/stat
Lines: 16
cpu 301854 612 111922 8979004 3552 2 3944 0 0 0
@ -4639,6 +4978,35 @@ Mode: 644
Directory: fixtures/sys/devices/system
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/node
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/node/node1
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/node/node1/vmstat
Lines: 6
nr_free_pages 1
nr_zone_inactive_anon 2
nr_zone_active_anon 3
nr_zone_inactive_file 4
nr_zone_active_file 5
nr_zone_unevictable 6
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/node/node2
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/node/node2/vmstat
Lines: 6
nr_free_pages 7
nr_zone_inactive_anon 8
nr_zone_active_anon 9
nr_zone_inactive_file 10
nr_zone_active_file 11
nr_zone_unevictable 12
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/system/clocksource
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -236,7 +236,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) {
m, err := parseFscacheinfo(bytes.NewReader(b))
if err != nil {
return Fscacheinfo{}, fmt.Errorf("failed to parse Fscacheinfo: %v", err)
return Fscacheinfo{}, fmt.Errorf("failed to parse Fscacheinfo: %w", err)
}
return *m, nil

View File

@ -39,10 +39,10 @@ type FS string
func NewFS(mountPoint string) (FS, error) {
info, err := os.Stat(mountPoint)
if err != nil {
return "", fmt.Errorf("could not read %s: %s", mountPoint, err)
return "", fmt.Errorf("could not read %q: %w", mountPoint, err)
}
if !info.IsDir() {
return "", fmt.Errorf("mount point %s is not a directory", mountPoint)
return "", fmt.Errorf("mount point %q is not a directory", mountPoint)
}
return FS(mountPoint), nil

View File

@ -44,14 +44,14 @@ func parseLoad(loadavgBytes []byte) (*LoadAvg, error) {
loads := make([]float64, 3)
parts := strings.Fields(string(loadavgBytes))
if len(parts) < 3 {
return nil, fmt.Errorf("malformed loadavg line: too few fields in loadavg string: %s", string(loadavgBytes))
return nil, fmt.Errorf("malformed loadavg line: too few fields in loadavg string: %q", string(loadavgBytes))
}
var err error
for i, load := range parts[0:3] {
loads[i], err = strconv.ParseFloat(load, 64)
if err != nil {
return nil, fmt.Errorf("could not parse load '%s': %s", load, err)
return nil, fmt.Errorf("could not parse load %q: %w", load, err)
}
}
return &LoadAvg{

View File

@ -22,8 +22,9 @@ import (
)
var (
statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
recoveryLineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
recoveryLineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
componentDeviceRE = regexp.MustCompile(`(.*)\[\d+\]`)
)
// MDStat holds info parsed from /proc/mdstat.
@ -44,6 +45,8 @@ type MDStat struct {
BlocksTotal int64
// Number of blocks on the device that are in sync.
BlocksSynced int64
// Name of md component devices
Devices []string
}
// MDStat parses an mdstat-file (/proc/mdstat) and returns a slice of
@ -56,7 +59,7 @@ func (fs FS) MDStat() ([]MDStat, error) {
}
mdstat, err := parseMDStat(data)
if err != nil {
return nil, fmt.Errorf("error parsing mdstat %s: %s", fs.proc.Path("mdstat"), err)
return nil, fmt.Errorf("error parsing mdstat %q: %w", fs.proc.Path("mdstat"), err)
}
return mdstat, nil
}
@ -82,10 +85,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
state := deviceFields[2] // active or inactive
if len(lines) <= i+3 {
return nil, fmt.Errorf(
"error parsing %s: too few lines for md device",
mdName,
)
return nil, fmt.Errorf("error parsing %q: too few lines for md device", mdName)
}
// Failed disks have the suffix (F) & Spare disks have the suffix (S).
@ -94,7 +94,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
active, total, size, err := evalStatusLine(lines[i], lines[i+1])
if err != nil {
return nil, fmt.Errorf("error parsing md device lines: %s", err)
return nil, fmt.Errorf("error parsing md device lines: %w", err)
}
syncLineIdx := i + 2
@ -126,7 +126,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
} else {
syncedBlocks, err = evalRecoveryLine(lines[syncLineIdx])
if err != nil {
return nil, fmt.Errorf("error parsing sync line in md device %s: %s", mdName, err)
return nil, fmt.Errorf("error parsing sync line in md device %q: %w", mdName, err)
}
}
}
@ -140,6 +140,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
DisksTotal: total,
BlocksTotal: size,
BlocksSynced: syncedBlocks,
Devices: evalComponentDevices(deviceFields),
})
}
@ -151,7 +152,7 @@ func evalStatusLine(deviceLine, statusLine string) (active, total, size int64, e
sizeStr := strings.Fields(statusLine)[0]
size, err = strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
return 0, 0, 0, fmt.Errorf("unexpected statusLine %s: %s", statusLine, err)
return 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err)
}
if strings.Contains(deviceLine, "raid0") || strings.Contains(deviceLine, "linear") {
@ -171,12 +172,12 @@ func evalStatusLine(deviceLine, statusLine string) (active, total, size int64, e
total, err = strconv.ParseInt(matches[2], 10, 64)
if err != nil {
return 0, 0, 0, fmt.Errorf("unexpected statusLine %s: %s", statusLine, err)
return 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err)
}
active, err = strconv.ParseInt(matches[3], 10, 64)
if err != nil {
return 0, 0, 0, fmt.Errorf("unexpected statusLine %s: %s", statusLine, err)
return 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err)
}
return active, total, size, nil
@ -190,8 +191,23 @@ func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, err error) {
syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64)
if err != nil {
return 0, fmt.Errorf("%s in recoveryLine: %s", err, recoveryLine)
return 0, fmt.Errorf("error parsing int from recoveryLine %q: %w", recoveryLine, err)
}
return syncedBlocks, nil
}
func evalComponentDevices(deviceFields []string) []string {
mdComponentDevices := make([]string, 0)
if len(deviceFields) > 3 {
for _, field := range deviceFields[4:] {
match := componentDeviceRE.FindStringSubmatch(field)
if match == nil {
continue
}
mdComponentDevices = append(mdComponentDevices, match[1])
}
}
return mdComponentDevices
}

View File

@ -28,9 +28,9 @@ import (
type Meminfo struct {
// Total usable ram (i.e. physical ram minus a few reserved
// bits and the kernel binary code)
MemTotal uint64
MemTotal *uint64
// The sum of LowFree+HighFree
MemFree uint64
MemFree *uint64
// An estimate of how much memory is available for starting
// new applications, without swapping. Calculated from
// MemFree, SReclaimable, the size of the file LRU lists, and
@ -39,59 +39,59 @@ type Meminfo struct {
// well, and that not all reclaimable slab will be
// reclaimable, due to items being in use. The impact of those
// factors will vary from system to system.
MemAvailable uint64
MemAvailable *uint64
// Relatively temporary storage for raw disk blocks shouldn't
// get tremendously large (20MB or so)
Buffers uint64
Cached uint64
Buffers *uint64
Cached *uint64
// Memory that once was swapped out, is swapped back in but
// still also is in the swapfile (if memory is needed it
// doesn't need to be swapped out AGAIN because it is already
// in the swapfile. This saves I/O)
SwapCached uint64
SwapCached *uint64
// Memory that has been used more recently and usually not
// reclaimed unless absolutely necessary.
Active uint64
Active *uint64
// Memory which has been less recently used. It is more
// eligible to be reclaimed for other purposes
Inactive uint64
ActiveAnon uint64
InactiveAnon uint64
ActiveFile uint64
InactiveFile uint64
Unevictable uint64
Mlocked uint64
Inactive *uint64
ActiveAnon *uint64
InactiveAnon *uint64
ActiveFile *uint64
InactiveFile *uint64
Unevictable *uint64
Mlocked *uint64
// total amount of swap space available
SwapTotal uint64
SwapTotal *uint64
// Memory which has been evicted from RAM, and is temporarily
// on the disk
SwapFree uint64
SwapFree *uint64
// Memory which is waiting to get written back to the disk
Dirty uint64
Dirty *uint64
// Memory which is actively being written back to the disk
Writeback uint64
Writeback *uint64
// Non-file backed pages mapped into userspace page tables
AnonPages uint64
AnonPages *uint64
// files which have been mapped, such as libraries
Mapped uint64
Shmem uint64
Mapped *uint64
Shmem *uint64
// in-kernel data structures cache
Slab uint64
Slab *uint64
// Part of Slab, that might be reclaimed, such as caches
SReclaimable uint64
SReclaimable *uint64
// Part of Slab, that cannot be reclaimed on memory pressure
SUnreclaim uint64
KernelStack uint64
SUnreclaim *uint64
KernelStack *uint64
// amount of memory dedicated to the lowest level of page
// tables.
PageTables uint64
PageTables *uint64
// NFS pages sent to the server, but not yet committed to
// stable storage
NFSUnstable uint64
NFSUnstable *uint64
// Memory used for block device "bounce buffers"
Bounce uint64
Bounce *uint64
// Memory used by FUSE for temporary writeback buffers
WritebackTmp uint64
WritebackTmp *uint64
// Based on the overcommit ratio ('vm.overcommit_ratio'),
// this is the total amount of memory currently available to
// be allocated on the system. This limit is only adhered to
@ -105,7 +105,7 @@ type Meminfo struct {
// yield a CommitLimit of 7.3G.
// For more details, see the memory overcommit documentation
// in vm/overcommit-accounting.
CommitLimit uint64
CommitLimit *uint64
// The amount of memory presently allocated on the system.
// The committed memory is a sum of all of the memory which
// has been allocated by processes, even if it has not been
@ -119,27 +119,27 @@ type Meminfo struct {
// This is useful if one needs to guarantee that processes will
// not fail due to lack of memory once that memory has been
// successfully allocated.
CommittedAS uint64
CommittedAS *uint64
// total size of vmalloc memory area
VmallocTotal uint64
VmallocTotal *uint64
// amount of vmalloc area which is used
VmallocUsed uint64
VmallocUsed *uint64
// largest contiguous block of vmalloc area which is free
VmallocChunk uint64
HardwareCorrupted uint64
AnonHugePages uint64
ShmemHugePages uint64
ShmemPmdMapped uint64
CmaTotal uint64
CmaFree uint64
HugePagesTotal uint64
HugePagesFree uint64
HugePagesRsvd uint64
HugePagesSurp uint64
Hugepagesize uint64
DirectMap4k uint64
DirectMap2M uint64
DirectMap1G uint64
VmallocChunk *uint64
HardwareCorrupted *uint64
AnonHugePages *uint64
ShmemHugePages *uint64
ShmemPmdMapped *uint64
CmaTotal *uint64
CmaFree *uint64
HugePagesTotal *uint64
HugePagesFree *uint64
HugePagesRsvd *uint64
HugePagesSurp *uint64
Hugepagesize *uint64
DirectMap4k *uint64
DirectMap2M *uint64
DirectMap1G *uint64
}
// Meminfo returns an information about current kernel/system memory statistics.
@ -152,7 +152,7 @@ func (fs FS) Meminfo() (Meminfo, error) {
m, err := parseMemInfo(bytes.NewReader(b))
if err != nil {
return Meminfo{}, fmt.Errorf("failed to parse meminfo: %v", err)
return Meminfo{}, fmt.Errorf("failed to parse meminfo: %w", err)
}
return *m, nil
@ -175,101 +175,101 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
switch fields[0] {
case "MemTotal:":
m.MemTotal = v
m.MemTotal = &v
case "MemFree:":
m.MemFree = v
m.MemFree = &v
case "MemAvailable:":
m.MemAvailable = v
m.MemAvailable = &v
case "Buffers:":
m.Buffers = v
m.Buffers = &v
case "Cached:":
m.Cached = v
m.Cached = &v
case "SwapCached:":
m.SwapCached = v
m.SwapCached = &v
case "Active:":
m.Active = v
m.Active = &v
case "Inactive:":
m.Inactive = v
m.Inactive = &v
case "Active(anon):":
m.ActiveAnon = v
m.ActiveAnon = &v
case "Inactive(anon):":
m.InactiveAnon = v
m.InactiveAnon = &v
case "Active(file):":
m.ActiveFile = v
m.ActiveFile = &v
case "Inactive(file):":
m.InactiveFile = v
m.InactiveFile = &v
case "Unevictable:":
m.Unevictable = v
m.Unevictable = &v
case "Mlocked:":
m.Mlocked = v
m.Mlocked = &v
case "SwapTotal:":
m.SwapTotal = v
m.SwapTotal = &v
case "SwapFree:":
m.SwapFree = v
m.SwapFree = &v
case "Dirty:":
m.Dirty = v
m.Dirty = &v
case "Writeback:":
m.Writeback = v
m.Writeback = &v
case "AnonPages:":
m.AnonPages = v
m.AnonPages = &v
case "Mapped:":
m.Mapped = v
m.Mapped = &v
case "Shmem:":
m.Shmem = v
m.Shmem = &v
case "Slab:":
m.Slab = v
m.Slab = &v
case "SReclaimable:":
m.SReclaimable = v
m.SReclaimable = &v
case "SUnreclaim:":
m.SUnreclaim = v
m.SUnreclaim = &v
case "KernelStack:":
m.KernelStack = v
m.KernelStack = &v
case "PageTables:":
m.PageTables = v
m.PageTables = &v
case "NFS_Unstable:":
m.NFSUnstable = v
m.NFSUnstable = &v
case "Bounce:":
m.Bounce = v
m.Bounce = &v
case "WritebackTmp:":
m.WritebackTmp = v
m.WritebackTmp = &v
case "CommitLimit:":
m.CommitLimit = v
m.CommitLimit = &v
case "Committed_AS:":
m.CommittedAS = v
m.CommittedAS = &v
case "VmallocTotal:":
m.VmallocTotal = v
m.VmallocTotal = &v
case "VmallocUsed:":
m.VmallocUsed = v
m.VmallocUsed = &v
case "VmallocChunk:":
m.VmallocChunk = v
m.VmallocChunk = &v
case "HardwareCorrupted:":
m.HardwareCorrupted = v
m.HardwareCorrupted = &v
case "AnonHugePages:":
m.AnonHugePages = v
m.AnonHugePages = &v
case "ShmemHugePages:":
m.ShmemHugePages = v
m.ShmemHugePages = &v
case "ShmemPmdMapped:":
m.ShmemPmdMapped = v
m.ShmemPmdMapped = &v
case "CmaTotal:":
m.CmaTotal = v
m.CmaTotal = &v
case "CmaFree:":
m.CmaFree = v
m.CmaFree = &v
case "HugePages_Total:":
m.HugePagesTotal = v
m.HugePagesTotal = &v
case "HugePages_Free:":
m.HugePagesFree = v
m.HugePagesFree = &v
case "HugePages_Rsvd:":
m.HugePagesRsvd = v
m.HugePagesRsvd = &v
case "HugePages_Surp:":
m.HugePagesSurp = v
m.HugePagesSurp = &v
case "Hugepagesize:":
m.Hugepagesize = v
m.Hugepagesize = &v
case "DirectMap4k:":
m.DirectMap4k = v
m.DirectMap4k = &v
case "DirectMap2M:":
m.DirectMap2M = v
m.DirectMap2M = &v
case "DirectMap1G:":
m.DirectMap1G = v
m.DirectMap1G = &v
}
}

View File

@ -338,12 +338,12 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
if len(ss) == 0 {
break
}
if len(ss) < 2 {
return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
}
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{}
}
@ -356,6 +356,9 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
}
}
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 {
@ -364,6 +367,9 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
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
@ -371,6 +377,9 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
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

View File

@ -55,7 +55,7 @@ func readConntrackStat(path string) ([]ConntrackStatEntry, error) {
stat, err := parseConntrackStat(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("failed to read conntrack stats from %q: %v", path, err)
return nil, fmt.Errorf("failed to read conntrack stats from %q: %w", path, err)
}
return stat, nil
@ -147,7 +147,7 @@ func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) {
func parseConntrackStatField(field string) (uint64, error) {
val, err := strconv.ParseUint(field, 16, 64)
if err != nil {
return 0, fmt.Errorf("couldn't parse \"%s\" field: %s", field, err)
return 0, fmt.Errorf("couldn't parse %q field: %w", field, err)
}
return val, err
}

220
vendor/github.com/prometheus/procfs/net_ip_socket.go generated vendored Normal file
View File

@ -0,0 +1,220 @@
// Copyright 2020 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"
"encoding/hex"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
)
const (
// readLimit is used by io.LimitReader while reading the content of the
// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
// as each line represents a single used socket.
// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
// With e.g. 150 Byte per line and the maximum number of 65535,
// the reader needs to handle 150 Byte * 65535 =~ 10 MB for a single IP.
readLimit = 4294967296 // Byte -> 4 GiB
)
// this contains generic data structures for both udp and tcp sockets
type (
// NetIPSocket represents the contents of /proc/net/{t,u}dp{,6} file without the header.
NetIPSocket []*netIPSocketLine
// NetIPSocketSummary provides already computed values like the total queue lengths or
// the total number of used sockets. In contrast to NetIPSocket it does not collect
// the parsed lines into a slice.
NetIPSocketSummary struct {
// TxQueueLength shows the total queue length of all parsed tx_queue lengths.
TxQueueLength uint64
// RxQueueLength shows the total queue length of all parsed rx_queue lengths.
RxQueueLength uint64
// UsedSockets shows the total number of parsed lines representing the
// number of used sockets.
UsedSockets uint64
}
// netIPSocketLine represents the fields parsed from a single line
// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
// For the proc file format details, see https://linux.die.net/man/5/proc.
netIPSocketLine struct {
Sl uint64
LocalAddr net.IP
LocalPort uint64
RemAddr net.IP
RemPort uint64
St uint64
TxQueue uint64
RxQueue uint64
UID uint64
}
)
func newNetIPSocket(file string) (NetIPSocket, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
var netIPSocket NetIPSocket
lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
line, err := parseNetIPSocketLine(fields)
if err != nil {
return nil, err
}
netIPSocket = append(netIPSocket, line)
}
if err := s.Err(); err != nil {
return nil, err
}
return netIPSocket, nil
}
// newNetIPSocketSummary creates a new NetIPSocket{,6} from the contents of the given file.
func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
var netIPSocketSummary NetIPSocketSummary
lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
line, err := parseNetIPSocketLine(fields)
if err != nil {
return nil, err
}
netIPSocketSummary.TxQueueLength += line.TxQueue
netIPSocketSummary.RxQueueLength += line.RxQueue
netIPSocketSummary.UsedSockets++
}
if err := s.Err(); err != nil {
return nil, err
}
return &netIPSocketSummary, nil
}
// the /proc/net/{t,u}dp{,6} files are network byte order for ipv4 and for ipv6 the address is four words consisting of four bytes each. In each of those four words the four bytes are written in reverse order.
func parseIP(hexIP string) (net.IP, error) {
var byteIP []byte
byteIP, err := hex.DecodeString(hexIP)
if err != nil {
return nil, fmt.Errorf("cannot parse address field in socket line %q", hexIP)
}
switch len(byteIP) {
case 4:
return net.IP{byteIP[3], byteIP[2], byteIP[1], byteIP[0]}, nil
case 16:
i := net.IP{
byteIP[3], byteIP[2], byteIP[1], byteIP[0],
byteIP[7], byteIP[6], byteIP[5], byteIP[4],
byteIP[11], byteIP[10], byteIP[9], byteIP[8],
byteIP[15], byteIP[14], byteIP[13], byteIP[12],
}
return i, nil
default:
return nil, fmt.Errorf("Unable to parse IP %s", hexIP)
}
}
// parseNetIPSocketLine parses a single line, represented by a list of fields.
func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
line := &netIPSocketLine{}
if len(fields) < 8 {
return nil, fmt.Errorf(
"cannot parse net socket line as it has less then 8 columns %q",
strings.Join(fields, " "),
)
}
var err error // parse error
// sl
s := strings.Split(fields[0], ":")
if len(s) != 2 {
return nil, fmt.Errorf("cannot parse sl field in socket line %q", fields[0])
}
if line.Sl, err = strconv.ParseUint(s[0], 0, 64); err != nil {
return nil, fmt.Errorf("cannot parse sl value in socket line: %w", err)
}
// local_address
l := strings.Split(fields[1], ":")
if len(l) != 2 {
return nil, fmt.Errorf("cannot parse local_address field in socket line %q", fields[1])
}
if line.LocalAddr, err = parseIP(l[0]); err != nil {
return nil, err
}
if line.LocalPort, err = strconv.ParseUint(l[1], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse local_address port value in socket line: %w", err)
}
// remote_address
r := strings.Split(fields[2], ":")
if len(r) != 2 {
return nil, fmt.Errorf("cannot parse rem_address field in socket line %q", fields[1])
}
if line.RemAddr, err = parseIP(r[0]); err != nil {
return nil, err
}
if line.RemPort, err = strconv.ParseUint(r[1], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse rem_address port value in socket line: %w", err)
}
// st
if line.St, err = strconv.ParseUint(fields[3], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse st value in socket line: %w", err)
}
// tx_queue and rx_queue
q := strings.Split(fields[4], ":")
if len(q) != 2 {
return nil, fmt.Errorf(
"cannot parse tx/rx queues in socket line as it has a missing colon %q",
fields[4],
)
}
if line.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse tx_queue value in socket line: %w", err)
}
if line.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse rx_queue value in socket line: %w", err)
}
// uid
if line.UID, err = strconv.ParseUint(fields[7], 0, 64); err != nil {
return nil, fmt.Errorf("cannot parse uid value in socket line: %w", err)
}
return line, nil
}

180
vendor/github.com/prometheus/procfs/net_protocols.go generated vendored Normal file
View File

@ -0,0 +1,180 @@
// Copyright 2020 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"
"bytes"
"fmt"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
)
// NetProtocolStats stores the contents from /proc/net/protocols
type NetProtocolStats map[string]NetProtocolStatLine
// NetProtocolStatLine contains a single line parsed from /proc/net/protocols. We
// only care about the first six columns as the rest are not likely to change
// and only serve to provide a set of capabilities for each protocol.
type NetProtocolStatLine struct {
Name string // 0 The name of the protocol
Size uint64 // 1 The size, in bytes, of a given protocol structure. e.g. sizeof(struct tcp_sock) or sizeof(struct unix_sock)
Sockets int64 // 2 Number of sockets in use by this protocol
Memory int64 // 3 Number of 4KB pages allocated by all sockets of this protocol
Pressure int // 4 This is either yes, no, or NI (not implemented). For the sake of simplicity we treat NI as not experiencing memory pressure.
MaxHeader uint64 // 5 Protocol specific max header size
Slab bool // 6 Indicates whether or not memory is allocated from the SLAB
ModuleName string // 7 The name of the module that implemented this protocol or "kernel" if not from a module
Capabilities NetProtocolCapabilities
}
// NetProtocolCapabilities contains a list of capabilities for each protocol
type NetProtocolCapabilities struct {
Close bool // 8
Connect bool // 9
Disconnect bool // 10
Accept bool // 11
IoCtl bool // 12
Init bool // 13
Destroy bool // 14
Shutdown bool // 15
SetSockOpt bool // 16
GetSockOpt bool // 17
SendMsg bool // 18
RecvMsg bool // 19
SendPage bool // 20
Bind bool // 21
BacklogRcv bool // 22
Hash bool // 23
UnHash bool // 24
GetPort bool // 25
EnterMemoryPressure bool // 26
}
// NetProtocols reads stats from /proc/net/protocols and returns a map of
// PortocolStatLine entries. As of this writing no official Linux Documentation
// exists, however the source is fairly self-explanatory and the format seems
// stable since its introduction in 2.6.12-rc2
// Linux 2.6.12-rc2 - https://elixir.bootlin.com/linux/v2.6.12-rc2/source/net/core/sock.c#L1452
// Linux 5.10 - https://elixir.bootlin.com/linux/v5.10.4/source/net/core/sock.c#L3586
func (fs FS) NetProtocols() (NetProtocolStats, error) {
data, err := util.ReadFileNoStat(fs.proc.Path("net/protocols"))
if err != nil {
return NetProtocolStats{}, err
}
return parseNetProtocols(bufio.NewScanner(bytes.NewReader(data)))
}
func parseNetProtocols(s *bufio.Scanner) (NetProtocolStats, error) {
nps := NetProtocolStats{}
// Skip the header line
s.Scan()
for s.Scan() {
line, err := nps.parseLine(s.Text())
if err != nil {
return NetProtocolStats{}, err
}
nps[line.Name] = *line
}
return nps, nil
}
func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, error) {
line := &NetProtocolStatLine{Capabilities: NetProtocolCapabilities{}}
var err error
const enabled = "yes"
const disabled = "no"
fields := strings.Fields(rawLine)
line.Name = fields[0]
line.Size, err = strconv.ParseUint(fields[1], 10, 64)
if err != nil {
return nil, err
}
line.Sockets, err = strconv.ParseInt(fields[2], 10, 64)
if err != nil {
return nil, err
}
line.Memory, err = strconv.ParseInt(fields[3], 10, 64)
if err != nil {
return nil, err
}
if fields[4] == enabled {
line.Pressure = 1
} else if fields[4] == disabled {
line.Pressure = 0
} else {
line.Pressure = -1
}
line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64)
if err != nil {
return nil, err
}
if fields[6] == enabled {
line.Slab = true
} else if fields[6] == disabled {
line.Slab = false
} else {
return nil, fmt.Errorf("unable to parse capability for protocol: %s", line.Name)
}
line.ModuleName = fields[7]
err = line.Capabilities.parseCapabilities(fields[8:])
if err != nil {
return nil, err
}
return line, nil
}
func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) error {
// The capabilities are all bools so we can loop over to map them
capabilityFields := [...]*bool{
&pc.Close,
&pc.Connect,
&pc.Disconnect,
&pc.Accept,
&pc.IoCtl,
&pc.Init,
&pc.Destroy,
&pc.Shutdown,
&pc.SetSockOpt,
&pc.GetSockOpt,
&pc.SendMsg,
&pc.RecvMsg,
&pc.SendPage,
&pc.Bind,
&pc.BacklogRcv,
&pc.Hash,
&pc.UnHash,
&pc.GetPort,
&pc.EnterMemoryPressure,
}
for i := 0; i < len(capabilities); i++ {
if capabilities[i] == "y" {
*capabilityFields[i] = true
} else if capabilities[i] == "n" {
*capabilityFields[i] = false
} else {
return fmt.Errorf("unable to parse capability block for protocol: position %d", i)
}
}
return nil
}

View File

@ -70,7 +70,7 @@ func readSockstat(name string) (*NetSockstat, error) {
stat, err := parseSockstat(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("failed to read sockstats from %q: %v", name, err)
return nil, fmt.Errorf("failed to read sockstats from %q: %w", name, err)
}
return stat, nil
@ -90,7 +90,7 @@ func parseSockstat(r io.Reader) (*NetSockstat, error) {
// The remaining fields are key/value pairs.
kvs, err := parseSockstatKVs(fields[1:])
if err != nil {
return nil, fmt.Errorf("error parsing sockstat key/value pairs from %q: %v", s.Text(), err)
return nil, fmt.Errorf("error parsing sockstat key/value pairs from %q: %w", s.Text(), err)
}
// The first field is the protocol. We must trim its colon suffix.

View File

@ -51,7 +51,7 @@ func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) {
entries, err := parseSoftnet(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("failed to parse /proc/net/softnet_stat: %v", err)
return nil, fmt.Errorf("failed to parse /proc/net/softnet_stat: %w", err)
}
return entries, nil

64
vendor/github.com/prometheus/procfs/net_tcp.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
// Copyright 2020 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
type (
// NetTCP represents the contents of /proc/net/tcp{,6} file without the header.
NetTCP []*netIPSocketLine
// NetTCPSummary provides already computed values like the total queue lengths or
// the total number of used sockets. In contrast to NetTCP it does not collect
// the parsed lines into a slice.
NetTCPSummary NetIPSocketSummary
)
// NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams
// read from /proc/net/tcp.
func (fs FS) NetTCP() (NetTCP, error) {
return newNetTCP(fs.proc.Path("net/tcp"))
}
// NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams
// read from /proc/net/tcp6.
func (fs FS) NetTCP6() (NetTCP, error) {
return newNetTCP(fs.proc.Path("net/tcp6"))
}
// NetTCPSummary returns already computed statistics like the total queue lengths
// for TCP datagrams read from /proc/net/tcp.
func (fs FS) NetTCPSummary() (*NetTCPSummary, error) {
return newNetTCPSummary(fs.proc.Path("net/tcp"))
}
// NetTCP6Summary returns already computed statistics like the total queue lengths
// for TCP datagrams read from /proc/net/tcp6.
func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) {
return newNetTCPSummary(fs.proc.Path("net/tcp6"))
}
// newNetTCP creates a new NetTCP{,6} from the contents of the given file.
func newNetTCP(file string) (NetTCP, error) {
n, err := newNetIPSocket(file)
n1 := NetTCP(n)
return n1, err
}
func newNetTCPSummary(file string) (*NetTCPSummary, error) {
n, err := newNetIPSocketSummary(file)
if n == nil {
return nil, err
}
n1 := NetTCPSummary(*n)
return &n1, err
}

View File

@ -13,58 +13,14 @@
package procfs
import (
"bufio"
"encoding/hex"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
)
const (
// readLimit is used by io.LimitReader while reading the content of the
// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
// as each line represents a single used socket.
// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
// With e.g. 150 Byte per line and the maximum number of 65535,
// the reader needs to handle 150 Byte * 65535 =~ 10 MB for a single IP.
readLimit = 4294967296 // Byte -> 4 GiB
)
type (
// NetUDP represents the contents of /proc/net/udp{,6} file without the header.
NetUDP []*netUDPLine
NetUDP []*netIPSocketLine
// NetUDPSummary provides already computed values like the total queue lengths or
// the total number of used sockets. In contrast to NetUDP it does not collect
// the parsed lines into a slice.
NetUDPSummary struct {
// TxQueueLength shows the total queue length of all parsed tx_queue lengths.
TxQueueLength uint64
// RxQueueLength shows the total queue length of all parsed rx_queue lengths.
RxQueueLength uint64
// UsedSockets shows the total number of parsed lines representing the
// number of used sockets.
UsedSockets uint64
}
// netUDPLine represents the fields parsed from a single line
// in /proc/net/udp{,6}. Fields which are not used by UDP are skipped.
// For the proc file format details, see https://linux.die.net/man/5/proc.
netUDPLine struct {
Sl uint64
LocalAddr net.IP
LocalPort uint64
RemAddr net.IP
RemPort uint64
St uint64
TxQueue uint64
RxQueue uint64
UID uint64
}
NetUDPSummary NetIPSocketSummary
)
// NetUDP returns the IPv4 kernel/networking statistics for UDP datagrams
@ -93,137 +49,16 @@ func (fs FS) NetUDP6Summary() (*NetUDPSummary, error) {
// newNetUDP creates a new NetUDP{,6} from the contents of the given file.
func newNetUDP(file string) (NetUDP, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
netUDP := NetUDP{}
lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
line, err := parseNetUDPLine(fields)
if err != nil {
return nil, err
}
netUDP = append(netUDP, line)
}
if err := s.Err(); err != nil {
return nil, err
}
return netUDP, nil
n, err := newNetIPSocket(file)
n1 := NetUDP(n)
return n1, err
}
// newNetUDPSummary creates a new NetUDP{,6} from the contents of the given file.
func newNetUDPSummary(file string) (*NetUDPSummary, error) {
f, err := os.Open(file)
if err != nil {
n, err := newNetIPSocketSummary(file)
if n == nil {
return nil, err
}
defer f.Close()
netUDPSummary := &NetUDPSummary{}
lr := io.LimitReader(f, readLimit)
s := bufio.NewScanner(lr)
s.Scan() // skip first line with headers
for s.Scan() {
fields := strings.Fields(s.Text())
line, err := parseNetUDPLine(fields)
if err != nil {
return nil, err
}
netUDPSummary.TxQueueLength += line.TxQueue
netUDPSummary.RxQueueLength += line.RxQueue
netUDPSummary.UsedSockets++
}
if err := s.Err(); err != nil {
return nil, err
}
return netUDPSummary, nil
}
// parseNetUDPLine parses a single line, represented by a list of fields.
func parseNetUDPLine(fields []string) (*netUDPLine, error) {
line := &netUDPLine{}
if len(fields) < 8 {
return nil, fmt.Errorf(
"cannot parse net udp socket line as it has less then 8 columns: %s",
strings.Join(fields, " "),
)
}
var err error // parse error
// sl
s := strings.Split(fields[0], ":")
if len(s) != 2 {
return nil, fmt.Errorf(
"cannot parse sl field in udp socket line: %s", fields[0])
}
if line.Sl, err = strconv.ParseUint(s[0], 0, 64); err != nil {
return nil, fmt.Errorf("cannot parse sl value in udp socket line: %s", err)
}
// local_address
l := strings.Split(fields[1], ":")
if len(l) != 2 {
return nil, fmt.Errorf(
"cannot parse local_address field in udp socket line: %s", fields[1])
}
if line.LocalAddr, err = hex.DecodeString(l[0]); err != nil {
return nil, fmt.Errorf(
"cannot parse local_address value in udp socket line: %s", err)
}
if line.LocalPort, err = strconv.ParseUint(l[1], 16, 64); err != nil {
return nil, fmt.Errorf(
"cannot parse local_address port value in udp socket line: %s", err)
}
// remote_address
r := strings.Split(fields[2], ":")
if len(r) != 2 {
return nil, fmt.Errorf(
"cannot parse rem_address field in udp socket line: %s", fields[1])
}
if line.RemAddr, err = hex.DecodeString(r[0]); err != nil {
return nil, fmt.Errorf(
"cannot parse rem_address value in udp socket line: %s", err)
}
if line.RemPort, err = strconv.ParseUint(r[1], 16, 64); err != nil {
return nil, fmt.Errorf(
"cannot parse rem_address port value in udp socket line: %s", err)
}
// st
if line.St, err = strconv.ParseUint(fields[3], 16, 64); err != nil {
return nil, fmt.Errorf(
"cannot parse st value in udp socket line: %s", err)
}
// tx_queue and rx_queue
q := strings.Split(fields[4], ":")
if len(q) != 2 {
return nil, fmt.Errorf(
"cannot parse tx/rx queues in udp socket line as it has a missing colon: %s",
fields[4],
)
}
if line.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse tx_queue value in udp socket line: %s", err)
}
if line.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil {
return nil, fmt.Errorf("cannot parse rx_queue value in udp socket line: %s", err)
}
// uid
if line.UID, err = strconv.ParseUint(fields[7], 0, 64); err != nil {
return nil, fmt.Errorf(
"cannot parse uid value in udp socket line: %s", err)
}
return line, nil
n1 := NetUDPSummary(*n)
return &n1, err
}

View File

@ -108,14 +108,14 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
line := s.Text()
item, err := nu.parseLine(line, hasInode, minFields)
if err != nil {
return nil, fmt.Errorf("failed to parse /proc/net/unix data %q: %v", line, err)
return nil, fmt.Errorf("failed to parse /proc/net/unix data %q: %w", line, err)
}
nu.Rows = append(nu.Rows, item)
}
if err := s.Err(); err != nil {
return nil, fmt.Errorf("failed to scan /proc/net/unix data: %v", err)
return nil, fmt.Errorf("failed to scan /proc/net/unix data: %w", err)
}
return &nu, nil
@ -136,29 +136,29 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine,
users, err := u.parseUsers(fields[1])
if err != nil {
return nil, fmt.Errorf("failed to parse ref count(%s): %v", fields[1], err)
return nil, fmt.Errorf("failed to parse ref count %q: %w", fields[1], err)
}
flags, err := u.parseFlags(fields[3])
if err != nil {
return nil, fmt.Errorf("failed to parse flags(%s): %v", fields[3], err)
return nil, fmt.Errorf("failed to parse flags %q: %w", fields[3], err)
}
typ, err := u.parseType(fields[4])
if err != nil {
return nil, fmt.Errorf("failed to parse type(%s): %v", fields[4], err)
return nil, fmt.Errorf("failed to parse type %q: %w", fields[4], err)
}
state, err := u.parseState(fields[5])
if err != nil {
return nil, fmt.Errorf("failed to parse state(%s): %v", fields[5], err)
return nil, fmt.Errorf("failed to parse state %q: %w", fields[5], err)
}
var inode uint64
if hasInode {
inode, err = u.parseInode(fields[6])
if err != nil {
return nil, fmt.Errorf("failed to parse inode(%s): %v", fields[6], err)
return nil, fmt.Errorf("failed to parse inode %q: %w", fields[6], err)
}
}

View File

@ -105,7 +105,7 @@ func (fs FS) AllProcs() (Procs, error) {
names, err := d.Readdirnames(-1)
if err != nil {
return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err)
return Procs{}, fmt.Errorf("could not read %q: %w", d.Name(), err)
}
p := Procs{}
@ -206,7 +206,7 @@ func (p Proc) FileDescriptors() ([]uintptr, error) {
for i, n := range names {
fd, err := strconv.ParseInt(n, 10, 32)
if err != nil {
return nil, fmt.Errorf("could not parse fd %s: %s", n, err)
return nil, fmt.Errorf("could not parse fd %q: %w", n, err)
}
fds[i] = uintptr(fd)
}
@ -278,7 +278,7 @@ func (p Proc) fileDescriptors() ([]string, error) {
names, err := d.Readdirnames(-1)
if err != nil {
return nil, fmt.Errorf("could not read %s: %s", d.Name(), err)
return nil, fmt.Errorf("could not read %q: %w", d.Name(), err)
}
return names, nil

View File

@ -49,7 +49,7 @@ type Cgroup struct {
func parseCgroupString(cgroupStr string) (*Cgroup, error) {
var err error
fields := strings.Split(cgroupStr, ":")
fields := strings.SplitN(cgroupStr, ":", 3)
if len(fields) < 3 {
return nil, fmt.Errorf("at least 3 fields required, found %d fields in cgroup string: %s", len(fields), cgroupStr)
}

View File

@ -16,7 +16,7 @@ package procfs
import (
"bufio"
"bytes"
"errors"
"fmt"
"regexp"
"github.com/prometheus/procfs/internal/util"
@ -112,7 +112,7 @@ func parseInotifyInfo(line string) (*InotifyInfo, error) {
}
return i, nil
}
return nil, errors.New("invalid inode entry: " + line)
return nil, fmt.Errorf("invalid inode entry: %q", line)
}
// ProcFDInfos represents a list of ProcFDInfo structs.

View File

@ -26,55 +26,55 @@ import (
// http://man7.org/linux/man-pages/man2/getrlimit.2.html.
type ProcLimits struct {
// CPU time limit in seconds.
CPUTime int64
CPUTime uint64
// Maximum size of files that the process may create.
FileSize int64
FileSize uint64
// Maximum size of the process's data segment (initialized data,
// uninitialized data, and heap).
DataSize int64
DataSize uint64
// Maximum size of the process stack in bytes.
StackSize int64
StackSize uint64
// Maximum size of a core file.
CoreFileSize int64
CoreFileSize uint64
// Limit of the process's resident set in pages.
ResidentSet int64
ResidentSet uint64
// Maximum number of processes that can be created for the real user ID of
// the calling process.
Processes int64
Processes uint64
// Value one greater than the maximum file descriptor number that can be
// opened by this process.
OpenFiles int64
OpenFiles uint64
// Maximum number of bytes of memory that may be locked into RAM.
LockedMemory int64
LockedMemory uint64
// Maximum size of the process's virtual memory address space in bytes.
AddressSpace int64
AddressSpace uint64
// Limit on the combined number of flock(2) locks and fcntl(2) leases that
// this process may establish.
FileLocks int64
FileLocks uint64
// Limit of signals that may be queued for the real user ID of the calling
// process.
PendingSignals int64
PendingSignals uint64
// Limit on the number of bytes that can be allocated for POSIX message
// queues for the real user ID of the calling process.
MsqqueueSize int64
MsqqueueSize uint64
// Limit of the nice priority set using setpriority(2) or nice(2).
NicePriority int64
NicePriority uint64
// Limit of the real-time priority set using sched_setscheduler(2) or
// sched_setparam(2).
RealtimePriority int64
RealtimePriority uint64
// Limit (in microseconds) on the amount of CPU time that a process
// scheduled under a real-time scheduling policy may consume without making
// a blocking system call.
RealtimeTimeout int64
RealtimeTimeout uint64
}
const (
limitsFields = 3
limitsFields = 4
limitsUnlimited = "unlimited"
)
var (
limitsDelimiter = regexp.MustCompile(" +")
limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`)
)
// NewLimits returns the current soft limits of the process.
@ -96,46 +96,49 @@ func (p Proc) Limits() (ProcLimits, error) {
l = ProcLimits{}
s = bufio.NewScanner(f)
)
s.Scan() // Skip limits header
for s.Scan() {
fields := limitsDelimiter.Split(s.Text(), limitsFields)
//fields := limitsMatch.Split(s.Text(), limitsFields)
fields := limitsMatch.FindStringSubmatch(s.Text())
if len(fields) != limitsFields {
return ProcLimits{}, fmt.Errorf(
"couldn't parse %s line %s", f.Name(), s.Text())
return ProcLimits{}, fmt.Errorf("couldn't parse %q line %q", f.Name(), s.Text())
}
switch fields[0] {
switch fields[1] {
case "Max cpu time":
l.CPUTime, err = parseInt(fields[1])
l.CPUTime, err = parseUint(fields[2])
case "Max file size":
l.FileSize, err = parseInt(fields[1])
l.FileSize, err = parseUint(fields[2])
case "Max data size":
l.DataSize, err = parseInt(fields[1])
l.DataSize, err = parseUint(fields[2])
case "Max stack size":
l.StackSize, err = parseInt(fields[1])
l.StackSize, err = parseUint(fields[2])
case "Max core file size":
l.CoreFileSize, err = parseInt(fields[1])
l.CoreFileSize, err = parseUint(fields[2])
case "Max resident set":
l.ResidentSet, err = parseInt(fields[1])
l.ResidentSet, err = parseUint(fields[2])
case "Max processes":
l.Processes, err = parseInt(fields[1])
l.Processes, err = parseUint(fields[2])
case "Max open files":
l.OpenFiles, err = parseInt(fields[1])
l.OpenFiles, err = parseUint(fields[2])
case "Max locked memory":
l.LockedMemory, err = parseInt(fields[1])
l.LockedMemory, err = parseUint(fields[2])
case "Max address space":
l.AddressSpace, err = parseInt(fields[1])
l.AddressSpace, err = parseUint(fields[2])
case "Max file locks":
l.FileLocks, err = parseInt(fields[1])
l.FileLocks, err = parseUint(fields[2])
case "Max pending signals":
l.PendingSignals, err = parseInt(fields[1])
l.PendingSignals, err = parseUint(fields[2])
case "Max msgqueue size":
l.MsqqueueSize, err = parseInt(fields[1])
l.MsqqueueSize, err = parseUint(fields[2])
case "Max nice priority":
l.NicePriority, err = parseInt(fields[1])
l.NicePriority, err = parseUint(fields[2])
case "Max realtime priority":
l.RealtimePriority, err = parseInt(fields[1])
l.RealtimePriority, err = parseUint(fields[2])
case "Max realtime timeout":
l.RealtimeTimeout, err = parseInt(fields[1])
l.RealtimeTimeout, err = parseUint(fields[2])
}
if err != nil {
return ProcLimits{}, err
@ -145,13 +148,13 @@ func (p Proc) Limits() (ProcLimits, error) {
return l, s.Err()
}
func parseInt(s string) (int64, error) {
func parseUint(s string) (uint64, error) {
if s == limitsUnlimited {
return -1, nil
return 18446744073709551615, nil
}
i, err := strconv.ParseInt(s, 10, 64)
i, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return 0, fmt.Errorf("couldn't parse value %s: %s", s, err)
return 0, fmt.Errorf("couldn't parse value %q: %w", s, err)
}
return i, nil
}

View File

@ -40,7 +40,7 @@ func (p Proc) Namespaces() (Namespaces, error) {
names, err := d.Readdirnames(-1)
if err != nil {
return nil, fmt.Errorf("failed to read contents of ns dir: %v", err)
return nil, fmt.Errorf("failed to read contents of ns dir: %w", err)
}
ns := make(Namespaces, len(names))
@ -52,13 +52,13 @@ func (p Proc) Namespaces() (Namespaces, error) {
fields := strings.SplitN(target, ":", 2)
if len(fields) != 2 {
return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target)
return nil, fmt.Errorf("failed to parse namespace type and inode from %q", target)
}
typ := fields[0]
inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32)
if err != nil {
return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err)
return nil, fmt.Errorf("failed to parse inode from %q: %w", fields[1], err)
}
ns[name] = Namespace{typ, uint32(inode)}

View File

@ -59,7 +59,7 @@ type PSIStats struct {
func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) {
data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource)))
if err != nil {
return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %s", resource)
return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %q: %w", resource, err)
}
return parsePSIStats(resource, bytes.NewReader(data))

View File

@ -127,10 +127,7 @@ func (p Proc) Stat() (ProcStat, error) {
)
if l < 0 || r < 0 {
return ProcStat{}, fmt.Errorf(
"unexpected format, couldn't extract comm: %s",
data,
)
return ProcStat{}, fmt.Errorf("unexpected format, couldn't extract comm %q", data)
}
s.Comm = string(data[l+1 : r])

View File

@ -95,24 +95,27 @@ func (fs FS) Schedstat() (*Schedstat, error) {
return stats, nil
}
func parseProcSchedstat(contents string) (stats ProcSchedstat, err error) {
func parseProcSchedstat(contents string) (ProcSchedstat, error) {
var (
stats ProcSchedstat
err error
)
match := procLineRE.FindStringSubmatch(contents)
if match != nil {
stats.RunningNanoseconds, err = strconv.ParseUint(match[1], 10, 64)
if err != nil {
return
return stats, err
}
stats.WaitingNanoseconds, err = strconv.ParseUint(match[2], 10, 64)
if err != nil {
return
return stats, err
}
stats.RunTimeslices, err = strconv.ParseUint(match[3], 10, 64)
return
return stats, err
}
err = errors.New("could not parse schedstat")
return
return stats, errors.New("could not parse schedstat")
}

151
vendor/github.com/prometheus/procfs/slab.go generated vendored Normal file
View File

@ -0,0 +1,151 @@
// Copyright 2020 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"
"bytes"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
)
var (
slabSpace = regexp.MustCompile(`\s+`)
slabVer = regexp.MustCompile(`slabinfo -`)
slabHeader = regexp.MustCompile(`# name`)
)
// Slab represents a slab pool in the kernel.
type Slab struct {
Name string
ObjActive int64
ObjNum int64
ObjSize int64
ObjPerSlab int64
PagesPerSlab int64
// tunables
Limit int64
Batch int64
SharedFactor int64
SlabActive int64
SlabNum int64
SharedAvail int64
}
// SlabInfo represents info for all slabs.
type SlabInfo struct {
Slabs []*Slab
}
func shouldParseSlab(line string) bool {
if slabVer.MatchString(line) {
return false
}
if slabHeader.MatchString(line) {
return false
}
return true
}
// parseV21SlabEntry is used to parse a line from /proc/slabinfo version 2.1.
func parseV21SlabEntry(line string) (*Slab, error) {
// First cleanup whitespace.
l := slabSpace.ReplaceAllString(line, " ")
s := strings.Split(l, " ")
if len(s) != 16 {
return nil, fmt.Errorf("unable to parse: %q", line)
}
var err error
i := &Slab{Name: s[0]}
i.ObjActive, err = strconv.ParseInt(s[1], 10, 64)
if err != nil {
return nil, err
}
i.ObjNum, err = strconv.ParseInt(s[2], 10, 64)
if err != nil {
return nil, err
}
i.ObjSize, err = strconv.ParseInt(s[3], 10, 64)
if err != nil {
return nil, err
}
i.ObjPerSlab, err = strconv.ParseInt(s[4], 10, 64)
if err != nil {
return nil, err
}
i.PagesPerSlab, err = strconv.ParseInt(s[5], 10, 64)
if err != nil {
return nil, err
}
i.Limit, err = strconv.ParseInt(s[8], 10, 64)
if err != nil {
return nil, err
}
i.Batch, err = strconv.ParseInt(s[9], 10, 64)
if err != nil {
return nil, err
}
i.SharedFactor, err = strconv.ParseInt(s[10], 10, 64)
if err != nil {
return nil, err
}
i.SlabActive, err = strconv.ParseInt(s[13], 10, 64)
if err != nil {
return nil, err
}
i.SlabNum, err = strconv.ParseInt(s[14], 10, 64)
if err != nil {
return nil, err
}
i.SharedAvail, err = strconv.ParseInt(s[15], 10, 64)
if err != nil {
return nil, err
}
return i, nil
}
// parseSlabInfo21 is used to parse a slabinfo 2.1 file.
func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) {
scanner := bufio.NewScanner(r)
s := SlabInfo{Slabs: []*Slab{}}
for scanner.Scan() {
line := scanner.Text()
if !shouldParseSlab(line) {
continue
}
slab, err := parseV21SlabEntry(line)
if err != nil {
return s, err
}
s.Slabs = append(s.Slabs, slab)
}
return s, nil
}
// SlabInfo reads data from /proc/slabinfo
func (fs FS) SlabInfo() (SlabInfo, error) {
// TODO: Consider passing options to allow for parsing different
// slabinfo versions. However, slabinfo 2.1 has been stable since
// kernel 2.6.10 and later.
data, err := util.ReadFileNoStat(fs.proc.Path("slabinfo"))
if err != nil {
return SlabInfo{}, err
}
return parseSlabInfo21(bytes.NewReader(data))
}

View File

@ -93,10 +93,10 @@ func parseCPUStat(line string) (CPUStat, int64, error) {
&cpuStat.Guest, &cpuStat.GuestNice)
if err != nil && err != io.EOF {
return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): %s", line, err)
return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu): %w", line, err)
}
if count == 0 {
return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): 0 elements parsed", line)
return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu): 0 elements parsed", line)
}
cpuStat.User /= userHZ
@ -116,7 +116,7 @@ func parseCPUStat(line string) (CPUStat, int64, error) {
cpuID, err := strconv.ParseInt(cpu[3:], 10, 64)
if err != nil {
return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu/cpuid): %s", line, err)
return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu/cpuid): %w", line, err)
}
return cpuStat, cpuID, nil
@ -136,7 +136,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) {
&softIRQStat.Hrtimer, &softIRQStat.Rcu)
if err != nil {
return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %s (softirq): %s", line, err)
return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %q (softirq): %w", line, err)
}
return softIRQStat, total, nil
@ -184,34 +184,34 @@ func (fs FS) Stat() (Stat, error) {
switch {
case parts[0] == "btime":
if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (btime): %s", parts[1], err)
return Stat{}, fmt.Errorf("couldn't parse %q (btime): %w", parts[1], err)
}
case parts[0] == "intr":
if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (intr): %s", parts[1], err)
return Stat{}, fmt.Errorf("couldn't parse %q (intr): %w", parts[1], err)
}
numberedIRQs := parts[2:]
stat.IRQ = make([]uint64, len(numberedIRQs))
for i, count := range numberedIRQs {
if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (intr%d): %s", count, i, err)
return Stat{}, fmt.Errorf("couldn't parse %q (intr%d): %w", count, i, err)
}
}
case parts[0] == "ctxt":
if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (ctxt): %s", parts[1], err)
return Stat{}, fmt.Errorf("couldn't parse %q (ctxt): %w", parts[1], err)
}
case parts[0] == "processes":
if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (processes): %s", parts[1], err)
return Stat{}, fmt.Errorf("couldn't parse %q (processes): %w", parts[1], err)
}
case parts[0] == "procs_running":
if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (procs_running): %s", parts[1], err)
return Stat{}, fmt.Errorf("couldn't parse %q (procs_running): %w", parts[1], err)
}
case parts[0] == "procs_blocked":
if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s (procs_blocked): %s", parts[1], err)
return Stat{}, fmt.Errorf("couldn't parse %q (procs_blocked): %w", parts[1], err)
}
case parts[0] == "softirq":
softIRQStats, total, err := parseSoftIRQStat(line)
@ -237,7 +237,7 @@ func (fs FS) Stat() (Stat, error) {
}
if err := scanner.Err(); err != nil {
return Stat{}, fmt.Errorf("couldn't parse %s: %s", fileName, err)
return Stat{}, fmt.Errorf("couldn't parse %q: %w", fileName, err)
}
return stat, nil

View File

@ -112,8 +112,7 @@ func (fs FS) NewXfrmStat() (XfrmStat, error) {
fields := strings.Fields(s.Text())
if len(fields) != 2 {
return XfrmStat{}, fmt.Errorf(
"couldn't parse %s line %s", file.Name(), s.Text())
return XfrmStat{}, fmt.Errorf("couldn't parse %q line %q", file.Name(), s.Text())
}
name := fields[0]

View File

@ -74,11 +74,11 @@ var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`)
func (fs FS) Zoneinfo() ([]Zoneinfo, error) {
data, err := ioutil.ReadFile(fs.proc.Path("zoneinfo"))
if err != nil {
return nil, fmt.Errorf("error reading zoneinfo %s: %s", fs.proc.Path("zoneinfo"), err)
return nil, fmt.Errorf("error reading zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err)
}
zoneinfo, err := parseZoneinfo(data)
if err != nil {
return nil, fmt.Errorf("error parsing zoneinfo %s: %s", fs.proc.Path("zoneinfo"), err)
return nil, fmt.Errorf("error parsing zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err)
}
return zoneinfo, nil
}

View File

@ -76,7 +76,7 @@ arguments can be passed to the kernel. The third is for low-level use by the
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
let it know that a system call is running.
When porting Go to an new architecture/OS, this file must be implemented for
When porting Go to a new architecture/OS, this file must be implemented for
each GOOS/GOARCH pair.
### mksysnum
@ -107,7 +107,7 @@ prototype can be exported (capitalized) or not.
Adding a new syscall often just requires adding a new `//sys` function prototype
with the desired arguments and a capitalized name so it is exported. However, if
you want the interface to the syscall to be different, often one will make an
unexported `//sys` prototype, an then write a custom wrapper in
unexported `//sys` prototype, and then write a custom wrapper in
`syscall_${GOOS}.go`.
### types files
@ -137,7 +137,7 @@ some `#if/#elif` macros in your include statements.
This script is used to generate the system's various constants. This doesn't
just include the error numbers and error strings, but also the signal numbers
an a wide variety of miscellaneous constants. The constants come from the list
and a wide variety of miscellaneous constants. The constants come from the list
of include files in the `includes_${uname}` variable. A regex then picks out
the desired `#define` statements, and generates the corresponding Go constants.
The error numbers and strings are generated from `#include <errno.h>`, and the

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (darwin || freebsd || netbsd || openbsd) && gc
// +build darwin freebsd netbsd openbsd
//go:build (freebsd || netbsd || openbsd) && gc
// +build freebsd netbsd openbsd
// +build gc
#include "textflag.h"

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (darwin || freebsd || netbsd || openbsd) && gc
// +build darwin freebsd netbsd openbsd
//go:build (freebsd || netbsd || openbsd) && gc
// +build freebsd netbsd openbsd
// +build gc
#include "textflag.h"

View File

@ -258,6 +258,7 @@ struct ltchars {
#include <linux/watchdog.h>
#include <mtd/ubi-user.h>
#include <mtd/mtd-user.h>
#include <net/route.h>
#if defined(__sparc__)
@ -593,6 +594,9 @@ ccflags="$@"
$2 == "HID_MAX_DESCRIPTOR_SIZE" ||
$2 ~ /^_?HIDIOC/ ||
$2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ ||
$2 ~ /^MTD/ ||
$2 ~ /^OTP/ ||
$2 ~ /^MEM/ ||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}

View File

@ -1406,6 +1406,10 @@ const (
MCAST_LEAVE_SOURCE_GROUP = 0x2f
MCAST_MSFILTER = 0x30
MCAST_UNBLOCK_SOURCE = 0x2c
MEMGETREGIONINFO = 0xc0104d08
MEMREADOOB64 = 0xc0184d16
MEMWRITE = 0xc0304d18
MEMWRITEOOB64 = 0xc0184d15
MFD_ALLOW_SEALING = 0x2
MFD_CLOEXEC = 0x1
MFD_HUGETLB = 0x4
@ -1494,7 +1498,35 @@ const (
MS_SYNCHRONOUS = 0x10
MS_UNBINDABLE = 0x20000
MS_VERBOSE = 0x8000
MTD_ABSENT = 0x0
MTD_BIT_WRITEABLE = 0x800
MTD_CAP_NANDFLASH = 0x400
MTD_CAP_NORFLASH = 0xc00
MTD_CAP_NVRAM = 0x1c00
MTD_CAP_RAM = 0x1c00
MTD_CAP_ROM = 0x0
MTD_DATAFLASH = 0x6
MTD_INODE_FS_MAGIC = 0x11307854
MTD_MAX_ECCPOS_ENTRIES = 0x40
MTD_MAX_OOBFREE_ENTRIES = 0x8
MTD_MLCNANDFLASH = 0x8
MTD_NANDECC_AUTOPLACE = 0x2
MTD_NANDECC_AUTOPL_USR = 0x4
MTD_NANDECC_OFF = 0x0
MTD_NANDECC_PLACE = 0x1
MTD_NANDECC_PLACEONLY = 0x3
MTD_NANDFLASH = 0x4
MTD_NORFLASH = 0x3
MTD_NO_ERASE = 0x1000
MTD_OTP_FACTORY = 0x1
MTD_OTP_OFF = 0x0
MTD_OTP_USER = 0x2
MTD_POWERUP_LOCK = 0x2000
MTD_RAM = 0x1
MTD_ROM = 0x2
MTD_SLC_ON_MLC_EMULATION = 0x4000
MTD_UBIVOLUME = 0x7
MTD_WRITEABLE = 0x400
NAME_MAX = 0xff
NCP_SUPER_MAGIC = 0x564c
NETLINK_ADD_MEMBERSHIP = 0x1

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x81484d11
ECCGETSTATS = 0x80104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -123,6 +125,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x40084d02
MEMERASE64 = 0x40104d14
MEMGETBADBLOCK = 0x40084d0b
MEMGETINFO = 0x80204d01
MEMGETOOBSEL = 0x80c84d0a
MEMGETREGIONCOUNT = 0x80044d07
MEMISLOCKED = 0x80084d17
MEMLOCK = 0x40084d05
MEMREADOOB = 0xc00c4d04
MEMSETBADBLOCK = 0x40084d0c
MEMUNLOCK = 0x40084d06
MEMWRITEOOB = 0xc00c4d03
MTDFILEMODE = 0x4d13
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
@ -132,6 +147,10 @@ const (
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x40044d0e
OTPGETREGIONINFO = 0x400c4d0f
OTPLOCK = 0x800c4d10
OTPSELECT = 0x80044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x81484d11
ECCGETSTATS = 0x80104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -123,6 +125,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x40084d02
MEMERASE64 = 0x40104d14
MEMGETBADBLOCK = 0x40084d0b
MEMGETINFO = 0x80204d01
MEMGETOOBSEL = 0x80c84d0a
MEMGETREGIONCOUNT = 0x80044d07
MEMISLOCKED = 0x80084d17
MEMLOCK = 0x40084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x40084d0c
MEMUNLOCK = 0x40084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x4d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -132,6 +147,10 @@ const (
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x40044d0e
OTPGETREGIONINFO = 0x400c4d0f
OTPLOCK = 0x800c4d10
OTPSELECT = 0x80044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x81484d11
ECCGETSTATS = 0x80104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x40084d02
MEMERASE64 = 0x40104d14
MEMGETBADBLOCK = 0x40084d0b
MEMGETINFO = 0x80204d01
MEMGETOOBSEL = 0x80c84d0a
MEMGETREGIONCOUNT = 0x80044d07
MEMISLOCKED = 0x80084d17
MEMLOCK = 0x40084d05
MEMREADOOB = 0xc00c4d04
MEMSETBADBLOCK = 0x40084d0c
MEMUNLOCK = 0x40084d06
MEMWRITEOOB = 0xc00c4d03
MTDFILEMODE = 0x4d13
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x40044d0e
OTPGETREGIONINFO = 0x400c4d0f
OTPLOCK = 0x800c4d10
OTPSELECT = 0x80044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x81484d11
ECCGETSTATS = 0x80104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -124,6 +126,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x40084d02
MEMERASE64 = 0x40104d14
MEMGETBADBLOCK = 0x40084d0b
MEMGETINFO = 0x80204d01
MEMGETOOBSEL = 0x80c84d0a
MEMGETREGIONCOUNT = 0x80044d07
MEMISLOCKED = 0x80084d17
MEMLOCK = 0x40084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x40084d0c
MEMUNLOCK = 0x40084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x4d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -133,6 +148,10 @@ const (
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x40044d0e
OTPGETREGIONINFO = 0x400c4d0f
OTPLOCK = 0x800c4d10
OTPSELECT = 0x80044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc00c4d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc00c4d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x8
O_ASYNC = 0x1000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x8
O_ASYNC = 0x1000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x8
O_ASYNC = 0x1000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc00c4d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc00c4d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x8
O_ASYNC = 0x1000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x300
CSIZE = 0x300
CSTOPB = 0x400
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x40
ECHOE = 0x2
ECHOK = 0x4
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x2000
MCL_FUTURE = 0x4000
MCL_ONFAULT = 0x8000
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc00c4d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc00c4d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x20
NL2 = 0x200
NL3 = 0x300
@ -132,6 +147,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x4
ONLCR = 0x2
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x300
CSIZE = 0x300
CSTOPB = 0x400
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x40
ECHOE = 0x2
ECHOK = 0x4
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x2000
MCL_FUTURE = 0x4000
MCL_ONFAULT = 0x8000
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x40
NL2 = 0x200
NL3 = 0x300
@ -132,6 +147,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x4
ONLCR = 0x2
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x300
CSIZE = 0x300
CSTOPB = 0x400
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x40
ECHOE = 0x2
ECHOK = 0x4
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x2000
MCL_FUTURE = 0x4000
MCL_ONFAULT = 0x8000
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x40
NL2 = 0x200
NL3 = 0x300
@ -132,6 +147,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x4
ONLCR = 0x2
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x81484d11
ECCGETSTATS = 0x80104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x40084d02
MEMERASE64 = 0x40104d14
MEMGETBADBLOCK = 0x40084d0b
MEMGETINFO = 0x80204d01
MEMGETOOBSEL = 0x80c84d0a
MEMGETREGIONCOUNT = 0x80044d07
MEMISLOCKED = 0x80084d17
MEMLOCK = 0x40084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x40084d0c
MEMUNLOCK = 0x40084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x4d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x40044d0e
OTPGETREGIONINFO = 0x400c4d0f
OTPLOCK = 0x800c4d10
OTPSELECT = 0x80044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -60,6 +60,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x81484d11
ECCGETSTATS = 0x80104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -121,6 +123,19 @@ const (
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MCL_ONFAULT = 0x4
MEMERASE = 0x40084d02
MEMERASE64 = 0x40104d14
MEMGETBADBLOCK = 0x40084d0b
MEMGETINFO = 0x80204d01
MEMGETOOBSEL = 0x80c84d0a
MEMGETREGIONCOUNT = 0x80044d07
MEMISLOCKED = 0x80084d17
MEMLOCK = 0x40084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x40084d0c
MEMUNLOCK = 0x40084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x4d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -130,6 +145,10 @@ const (
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x40044d0e
OTPGETREGIONINFO = 0x400c4d0f
OTPLOCK = 0x800c4d10
OTPSELECT = 0x80044d0d
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000

View File

@ -63,6 +63,8 @@ const (
CS8 = 0x30
CSIZE = 0x30
CSTOPB = 0x40
ECCGETLAYOUT = 0x41484d11
ECCGETSTATS = 0x40104d12
ECHOCTL = 0x200
ECHOE = 0x10
ECHOK = 0x20
@ -126,6 +128,19 @@ const (
MCL_CURRENT = 0x2000
MCL_FUTURE = 0x4000
MCL_ONFAULT = 0x8000
MEMERASE = 0x80084d02
MEMERASE64 = 0x80104d14
MEMGETBADBLOCK = 0x80084d0b
MEMGETINFO = 0x40204d01
MEMGETOOBSEL = 0x40c84d0a
MEMGETREGIONCOUNT = 0x40044d07
MEMISLOCKED = 0x40084d17
MEMLOCK = 0x80084d05
MEMREADOOB = 0xc0104d04
MEMSETBADBLOCK = 0x80084d0c
MEMUNLOCK = 0x80084d06
MEMWRITEOOB = 0xc0104d03
MTDFILEMODE = 0x20004d13
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
@ -135,6 +150,10 @@ const (
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
OTPGETREGIONCOUNT = 0x80044d0e
OTPGETREGIONINFO = 0x800c4d0f
OTPLOCK = 0x400c4d10
OTPSELECT = 0x40044d0d
O_APPEND = 0x8
O_ASYNC = 0x40
O_CLOEXEC = 0x400000

View File

@ -3742,3 +3742,89 @@ const (
NLMSGERR_ATTR_OFFS = 0x2
NLMSGERR_ATTR_COOKIE = 0x3
)
type (
EraseInfo struct {
Start uint32
Length uint32
}
EraseInfo64 struct {
Start uint64
Length uint64
}
MtdOobBuf struct {
Start uint32
Length uint32
Ptr *uint8
}
MtdOobBuf64 struct {
Start uint64
Pad uint32
Length uint32
Ptr uint64
}
MtdWriteReq struct {
Start uint64
Len uint64
Ooblen uint64
Data uint64
Oob uint64
Mode uint8
_ [7]uint8
}
MtdInfo struct {
Type uint8
Flags uint32
Size uint32
Erasesize uint32
Writesize uint32
Oobsize uint32
_ uint64
}
RegionInfo struct {
Offset uint32
Erasesize uint32
Numblocks uint32
Regionindex uint32
}
OtpInfo struct {
Start uint32
Length uint32
Locked uint32
}
NandOobinfo struct {
Useecc uint32
Eccbytes uint32
Oobfree [8][2]uint32
Eccpos [32]uint32
}
NandOobfree struct {
Offset uint32
Length uint32
}
NandEcclayout struct {
Eccbytes uint32
Eccpos [64]uint32
Oobavail uint32
Oobfree [8]NandOobfree
}
MtdEccStats struct {
Corrected uint32
Failed uint32
Badblocks uint32
Bbtblocks uint32
}
)
const (
MTD_OPS_PLACE_OOB = 0x0
MTD_OPS_AUTO_OOB = 0x1
MTD_OPS_RAW = 0x2
)
const (
MTD_FILE_MODE_NORMAL = 0x0
MTD_FILE_MODE_OTP_FACTORY = 0x1
MTD_FILE_MODE_OTP_USER = 0x2
MTD_FILE_MODE_RAW = 0x3
)

Some files were not shown because too many files have changed in this diff Show More