@@ -1,13 +1,13 @@ | |||
module backfeed | |||
go 1.18 | |||
go 1.19 | |||
require ( | |||
github.com/globocom/go-redis-prometheus v0.4.0 | |||
github.com/go-redis/redis/v8 v8.11.4 | |||
github.com/go-redis/redis/v8 v8.11.5 | |||
github.com/gorilla/mux v1.8.0 | |||
github.com/prometheus/client_golang v1.12.1 | |||
github.com/tevino/abool/v2 v2.0.1 | |||
github.com/prometheus/client_golang v1.12.2 | |||
github.com/tevino/abool/v2 v2.1.0 | |||
) | |||
require ( | |||
@@ -17,8 +17,8 @@ require ( | |||
github.com/golang/protobuf v1.5.2 // indirect | |||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect | |||
github.com/prometheus/client_model v0.2.0 // indirect | |||
github.com/prometheus/common v0.32.1 // indirect | |||
github.com/prometheus/procfs v0.7.3 // indirect | |||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect | |||
google.golang.org/protobuf v1.26.0 // indirect | |||
github.com/prometheus/common v0.37.0 // indirect | |||
github.com/prometheus/procfs v0.8.0 // indirect | |||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 // indirect | |||
google.golang.org/protobuf v1.28.1 // indirect | |||
) |
@@ -108,15 +108,16 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 | |||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= | |||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= | |||
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= | |||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | |||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | |||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= | |||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= | |||
github.com/go-redis/redis/v8 v8.3.3/go.mod h1:jszGxBCez8QA1HWSmQxJO9Y82kNibbUmeYhKWrBejTU= | |||
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= | |||
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= | |||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= | |||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= | |||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= | |||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= | |||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= | |||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= | |||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||
@@ -163,8 +164,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||
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= | |||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= | |||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | |||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= | |||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= | |||
@@ -269,7 +269,6 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi | |||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= | |||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | |||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | |||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | |||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= | |||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= | |||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= | |||
@@ -277,14 +276,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W | |||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | |||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= | |||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= | |||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= | |||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= | |||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= | |||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | |||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | |||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= | |||
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= | |||
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= | |||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= | |||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= | |||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= | |||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= | |||
@@ -314,8 +311,9 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD | |||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= | |||
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= | |||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= | |||
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= | |||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= | |||
github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= | |||
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= | |||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||
@@ -329,8 +327,9 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 | |||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= | |||
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= | |||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= | |||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= | |||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= | |||
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= | |||
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= | |||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= | |||
@@ -338,8 +337,9 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx | |||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | |||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | |||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | |||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= | |||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | |||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= | |||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= | |||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= | |||
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= | |||
@@ -365,11 +365,10 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ | |||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | |||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | |||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | |||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | |||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= | |||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||
github.com/tevino/abool/v2 v2.0.1 h1:OF7FC5V5z3yAWyixbc32ecEzrgAJCsPkVOsPM2qoZPI= | |||
github.com/tevino/abool/v2 v2.0.1/go.mod h1:+Lmlqk6bHDWHqN1cbxqhwEAwMPXgc8I1SDEamtseuXY= | |||
github.com/tevino/abool/v2 v2.1.0 h1:7w+Vf9f/5gmKT4m4qkayb33/92M+Um45F2BkHOR+L/c= | |||
github.com/tevino/abool/v2 v2.1.0/go.mod h1:+Lmlqk6bHDWHqN1cbxqhwEAwMPXgc8I1SDEamtseuXY= | |||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | |||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= | |||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= | |||
@@ -377,7 +376,6 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q | |||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= | |||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= | |||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||
@@ -469,16 +467,17 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R | |||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | |||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | |||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= | |||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= | |||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | |||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= | |||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= | |||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= | |||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | |||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= | |||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
@@ -487,7 +486,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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/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= | |||
@@ -534,20 +532,24 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w | |||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= | |||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 h1:9vYwv7OjYaky/tlAeD7C4oC9EsPTlaFl1H2jS++V+ME= | |||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | |||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= | |||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | |||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | |||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
@@ -598,11 +600,9 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY | |||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | |||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | |||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | |||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= | |||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= | |||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= | |||
@@ -686,8 +686,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD | |||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= | |||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | |||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= | |||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | |||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= | |||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | |||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
@@ -53,7 +53,6 @@ type ProjectBackfeedManager struct { | |||
Name string | |||
BackfeedRedis *redis.ClusterClient | |||
ProjectRedis *redis.Client | |||
LegacyRedis *redis.Client | |||
//Lock sync.RWMutex | |||
ProjectConfig ProjectConfig | |||
} | |||
@@ -151,8 +150,15 @@ func (that *ProjectBackfeedManager) Do() { | |||
break | |||
default: | |||
} | |||
now := time.Now() | |||
resultMap := map[string]*redis.Cmd{} | |||
pipe := that.BackfeedRedis.Pipeline() | |||
lastTS := make([]interface{}, 0, len(keyMap)*2) | |||
for key := range keyMap { | |||
lastTS = append(lastTS, key) | |||
lastTS = append(lastTS, fmt.Sprintf("%d", now.Unix())) | |||
} | |||
pipe.HSet(context.Background(), ":last_ts", lastTS...) | |||
for key, items := range keyMap { | |||
args := []interface{}{ | |||
"bf.madd", | |||
@@ -163,8 +169,7 @@ func (that *ProjectBackfeedManager) Do() { | |||
} | |||
resultMap[key] = pipe.Do(context.Background(), args...) | |||
} | |||
_, err := pipe.Exec(context.Background()) | |||
if err != nil { | |||
if _, err := pipe.Exec(context.Background()); err != nil { | |||
log.Printf("%s", err) | |||
} | |||
var sAddItems []interface{} | |||
@@ -185,28 +190,7 @@ func (that *ProjectBackfeedManager) Do() { | |||
} | |||
dupes := wrapped - len(sAddItems) | |||
if len(sAddItems) != 0 { | |||
args := []interface{}{ | |||
"bf.mexists", | |||
that.Name, | |||
} | |||
args = append(args, sAddItems...) | |||
res, err := that.LegacyRedis.Do(context.Background(), args...).BoolSlice() | |||
if err != nil { | |||
log.Printf("unable to dedupe against %s legacy backfeed: %s", that.Name, err) | |||
} else if len(res) == len(sAddItems) { | |||
var filteredSAddItems []interface{} | |||
for i, v := range res { | |||
if !v { | |||
filteredSAddItems = append(filteredSAddItems, sAddItems[i]) | |||
} | |||
} | |||
sAddItems = filteredSAddItems | |||
} | |||
} | |||
if len(sAddItems) != 0 { | |||
err := that.ProjectRedis.SAdd(context.Background(), fmt.Sprintf("%s:todo:backfeed", that.Name), sAddItems...).Err() | |||
if err != nil { | |||
if err := that.ProjectRedis.SAdd(context.Background(), fmt.Sprintf("%s:todo:backfeed", that.Name), sAddItems...).Err(); err != nil { | |||
log.Printf("failed to sadd items for %s: %s", that.Name, err) | |||
} | |||
} | |||
@@ -223,7 +207,6 @@ type GlobalBackfeedManager struct { | |||
ActiveSlugs map[string]string | |||
TrackerRedis *redis.Client | |||
BackfeedRedis *redis.ClusterClient | |||
LegacyRedis *redis.Client | |||
Lock sync.RWMutex | |||
Populated *abool.AtomicBool | |||
} | |||
@@ -256,8 +239,7 @@ func (that *GlobalBackfeedManager) RefreshFeeds() error { | |||
continue | |||
} | |||
config := ProjectConfig{} | |||
err := json.Unmarshal([]byte(configString), &config) | |||
if err != nil { | |||
if err := json.Unmarshal([]byte(configString), &config); err != nil { | |||
continue | |||
} | |||
projectConfigs[project] = config | |||
@@ -296,7 +278,6 @@ func (that *GlobalBackfeedManager) RefreshFeeds() error { | |||
BackfeedRedis: that.BackfeedRedis, | |||
Name: project, | |||
ProjectConfig: projectConfig, | |||
LegacyRedis: that.LegacyRedis, | |||
} | |||
if projectConfig.RedisConfig != nil { | |||
projectBackfeedManager.ProjectRedis = redis.NewClient(&redis.Options{ | |||
@@ -440,15 +421,13 @@ func (that *GlobalBackfeedManager) HandleLegacy(res http.ResponseWriter, req *ht | |||
SecondaryShard: secondaryShard, | |||
Item: bcopy, | |||
} | |||
err := projectBackfeedManager.PushItem(req.Context(), item) | |||
if err != nil { | |||
if err := projectBackfeedManager.PushItem(req.Context(), item); err != nil { | |||
WriteResponse(res, http.StatusServiceUnavailable, err) | |||
return | |||
} | |||
n++ | |||
} | |||
err := scanner.Err() | |||
if err != nil { | |||
if err := scanner.Err(); err != nil { | |||
WriteResponse(res, statusCode, err) | |||
return | |||
} | |||
@@ -461,16 +440,10 @@ func (that *GlobalBackfeedManager) HandleHealth(res http.ResponseWriter, req *ht | |||
WriteResponse(res, http.StatusServiceUnavailable, fmt.Errorf("%s", "backfeed not populated")) | |||
return | |||
} | |||
err := that.LegacyRedis.Ping(req.Context()).Err() | |||
if err != nil { | |||
WriteResponse(res, http.StatusInternalServerError, fmt.Errorf("failed to ping legacy redis: %s", err)) | |||
return | |||
} | |||
err = that.BackfeedRedis.ForEachShard(req.Context(), func(ctx context.Context, client *redis.Client) error { | |||
if err := that.BackfeedRedis.ForEachShard(req.Context(), func(ctx context.Context, client *redis.Client) error { | |||
client.ClientGetName(ctx) | |||
return client.Ping(ctx).Err() | |||
}) | |||
if err != nil { | |||
}); err != nil { | |||
WriteResponse(res, http.StatusInternalServerError, fmt.Errorf("failed to ping backfeed redis: %s", err)) | |||
return | |||
} | |||
@@ -549,15 +522,13 @@ func main() { | |||
ActiveSlugs: map[string]string{}, | |||
TrackerRedis: trackerRedisClient, | |||
BackfeedRedis: backfeedRedisClient, | |||
LegacyRedis: legacyRedisClient, | |||
Populated: abool.New(), | |||
} | |||
globalBackfeedManager.Context, globalBackfeedManager.Cancel = context.WithCancel(context.Background()) | |||
defer globalBackfeedManager.CancelAllFeeds() | |||
err = globalBackfeedManager.RefreshFeeds() | |||
if err != nil { | |||
if err := globalBackfeedManager.RefreshFeeds(); err != nil { | |||
log.Panicf("unable to set up backfeed projects: %s", err) | |||
} | |||
r := mux.NewRouter() | |||
@@ -606,8 +577,7 @@ func main() { | |||
return | |||
case <-ticker.C: | |||
} | |||
err = globalBackfeedManager.RefreshFeeds() | |||
if err != nil { | |||
if err := globalBackfeedManager.RefreshFeeds(); err != nil { | |||
log.Printf("unable to refresh backfeed projects: %s", err) | |||
} | |||
} | |||
@@ -2,26 +2,3 @@ run: | |||
concurrency: 8 | |||
deadline: 5m | |||
tests: false | |||
linters: | |||
enable-all: true | |||
disable: | |||
- funlen | |||
- gochecknoglobals | |||
- gochecknoinits | |||
- gocognit | |||
- goconst | |||
- godox | |||
- gosec | |||
- maligned | |||
- wsl | |||
- gomnd | |||
- goerr113 | |||
- exhaustive | |||
- nestif | |||
- nlreturn | |||
- exhaustivestruct | |||
- wrapcheck | |||
- errorlint | |||
- cyclop | |||
- forcetypeassert | |||
- forbidigo |
@@ -1,3 +1,31 @@ | |||
## [8.11.5](https://github.com/go-redis/redis/compare/v8.11.4...v8.11.5) (2022-03-17) | |||
### Bug Fixes | |||
* add missing Expire methods to Cmdable ([17e3b43](https://github.com/go-redis/redis/commit/17e3b43879d516437ada71cf9c0deac6a382ed9a)) | |||
* add whitespace for avoid unlikely colisions ([7f7c181](https://github.com/go-redis/redis/commit/7f7c1817617cfec909efb13d14ad22ef05a6ad4c)) | |||
* example/otel compile error ([#2028](https://github.com/go-redis/redis/issues/2028)) ([187c07c](https://github.com/go-redis/redis/commit/187c07c41bf68dc3ab280bc3a925e960bbef6475)) | |||
* **extra/redisotel:** set span.kind attribute to client ([065b200](https://github.com/go-redis/redis/commit/065b200070b41e6e949710b4f9e01b50ccc60ab2)) | |||
* format ([96f53a0](https://github.com/go-redis/redis/commit/96f53a0159a28affa94beec1543a62234e7f8b32)) | |||
* invalid type assert in stringArg ([de6c131](https://github.com/go-redis/redis/commit/de6c131865b8263400c8491777b295035f2408e4)) | |||
* rename Golang to Go ([#2030](https://github.com/go-redis/redis/issues/2030)) ([b82a2d9](https://github.com/go-redis/redis/commit/b82a2d9d4d2de7b7cbe8fcd4895be62dbcacacbc)) | |||
* set timeout for WAIT command. Fixes [#1963](https://github.com/go-redis/redis/issues/1963) ([333fee1](https://github.com/go-redis/redis/commit/333fee1a8fd98a2fbff1ab187c1b03246a7eb01f)) | |||
* update some argument counts in pre-allocs ([f6974eb](https://github.com/go-redis/redis/commit/f6974ebb5c40a8adf90d2cacab6dc297f4eba4c2)) | |||
### Features | |||
* Add redis v7's NX, XX, GT, LT expire variants ([e19bbb2](https://github.com/go-redis/redis/commit/e19bbb26e2e395c6e077b48d80d79e99f729a8b8)) | |||
* add support for acl sentinel auth in universal client ([ab0ccc4](https://github.com/go-redis/redis/commit/ab0ccc47413f9b2a6eabc852fed5005a3ee1af6e)) | |||
* add support for COPY command ([#2016](https://github.com/go-redis/redis/issues/2016)) ([730afbc](https://github.com/go-redis/redis/commit/730afbcffb93760e8a36cc06cfe55ab102b693a7)) | |||
* add support for passing extra attributes added to spans ([39faaa1](https://github.com/go-redis/redis/commit/39faaa171523834ba527c9789710c4fde87f5a2e)) | |||
* add support for time.Duration write and scan ([2f1b74e](https://github.com/go-redis/redis/commit/2f1b74e20cdd7719b2aecf0768d3e3ae7c3e781b)) | |||
* **redisotel:** ability to override TracerProvider ([#1998](https://github.com/go-redis/redis/issues/1998)) ([bf8d4aa](https://github.com/go-redis/redis/commit/bf8d4aa60c00366cda2e98c3ddddc8cf68507417)) | |||
* set net.peer.name and net.peer.port in otel example ([69bf454](https://github.com/go-redis/redis/commit/69bf454f706204211cd34835f76b2e8192d3766d)) | |||
## [8.11.4](https://github.com/go-redis/redis/compare/v8.11.3...v8.11.4) (2021-10-04) | |||
@@ -1,19 +1,16 @@ | |||
<p align="center"> | |||
<a href="https://uptrace.dev/?utm_source=gh-redis&utm_campaign=gh-redis-banner1"> | |||
<img src="https://raw.githubusercontent.com/uptrace/roadmap/master/banner1.png" alt="All-in-one tool to optimize performance and monitor errors & logs"> | |||
</a> | |||
</p> | |||
# Redis client for Golang | |||
# Redis client for Go | |||
![build workflow](https://github.com/go-redis/redis/actions/workflows/build.yml/badge.svg) | |||
[![PkgGoDev](https://pkg.go.dev/badge/github.com/go-redis/redis/v8)](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc) | |||
[![Documentation](https://img.shields.io/badge/redis-documentation-informational)](https://redis.uptrace.dev/) | |||
[![Chat](https://discordapp.com/api/guilds/752070105847955518/widget.png)](https://discord.gg/rWtp5Aj) | |||
- To ask questions, join [Discord](https://discord.gg/rWtp5Aj) or use | |||
[Discussions](https://github.com/go-redis/redis/discussions). | |||
- [Newsletter](https://blog.uptrace.dev/pages/newsletter.html) to get latest updates. | |||
go-redis is brought to you by :star: [**uptrace/uptrace**](https://github.com/uptrace/uptrace). | |||
Uptrace is an open source and blazingly fast **distributed tracing** backend powered by | |||
OpenTelemetry and ClickHouse. Give it a star as well! | |||
## Resources | |||
- [Discussions](https://github.com/go-redis/redis/discussions) | |||
- [Documentation](https://redis.uptrace.dev) | |||
- [Reference](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc) | |||
- [Examples](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#pkg-examples) | |||
@@ -22,15 +19,14 @@ | |||
Other projects you may like: | |||
- [Bun](https://bun.uptrace.dev) - fast and simple SQL client for PostgreSQL, MySQL, and SQLite. | |||
- [treemux](https://github.com/vmihailenco/treemux) - high-speed, flexible, tree-based HTTP router | |||
for Go. | |||
- [BunRouter](https://bunrouter.uptrace.dev/) - fast and flexible HTTP router for Go. | |||
## Ecosystem | |||
- [Redis Mock](https://github.com/go-redis/redismock). | |||
- [Distributed Locks](https://github.com/bsm/redislock). | |||
- [Redis Cache](https://github.com/go-redis/cache). | |||
- [Rate limiting](https://github.com/go-redis/redis_rate). | |||
- [Redis Mock](https://github.com/go-redis/redismock) | |||
- [Distributed Locks](https://github.com/bsm/redislock) | |||
- [Redis Cache](https://github.com/go-redis/cache) | |||
- [Rate limiting](https://github.com/go-redis/redis_rate) | |||
## Features | |||
@@ -39,16 +35,16 @@ Other projects you may like: | |||
[circuit breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) support. | |||
- [Pub/Sub](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#PubSub). | |||
- [Transactions](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client-TxPipeline). | |||
- [Pipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client-Pipeline) and | |||
[TxPipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client-TxPipeline). | |||
- [Pipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client.Pipeline) and | |||
[TxPipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client.TxPipeline). | |||
- [Scripting](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#Script). | |||
- [Timeouts](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#Options). | |||
- [Redis Sentinel](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#NewFailoverClient). | |||
- [Redis Cluster](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#NewClusterClient). | |||
- [Cluster of Redis Servers](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-NewClusterClient--ManualSetup) | |||
- [Cluster of Redis Servers](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-NewClusterClient-ManualSetup) | |||
without using cluster mode and Redis Sentinel. | |||
- [Ring](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#NewRing). | |||
- [Instrumentation](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#ex-package--Instrumentation). | |||
- [Instrumentation](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-package-Instrumentation). | |||
## Installation | |||
@@ -72,6 +68,7 @@ go get github.com/go-redis/redis/v8 | |||
import ( | |||
"context" | |||
"github.com/go-redis/redis/v8" | |||
"fmt" | |||
) | |||
var ctx = context.Background() | |||
@@ -20,7 +20,7 @@ type Cmder interface { | |||
String() string | |||
stringArg(int) string | |||
firstKeyPos() int8 | |||
setFirstKeyPos(int8) | |||
SetFirstKeyPos(int8) | |||
readTimeout() *time.Duration | |||
readReply(rd *proto.Reader) error | |||
@@ -151,15 +151,21 @@ func (cmd *baseCmd) stringArg(pos int) string { | |||
if pos < 0 || pos >= len(cmd.args) { | |||
return "" | |||
} | |||
s, _ := cmd.args[pos].(string) | |||
return s | |||
arg := cmd.args[pos] | |||
switch v := arg.(type) { | |||
case string: | |||
return v | |||
default: | |||
// TODO: consider using appendArg | |||
return fmt.Sprint(v) | |||
} | |||
} | |||
func (cmd *baseCmd) firstKeyPos() int8 { | |||
return cmd.keyPos | |||
} | |||
func (cmd *baseCmd) setFirstKeyPos(keyPos int8) { | |||
func (cmd *baseCmd) SetFirstKeyPos(keyPos int8) { | |||
cmd.keyPos = keyPos | |||
} | |||
@@ -96,6 +96,10 @@ type Cmdable interface { | |||
Exists(ctx context.Context, keys ...string) *IntCmd | |||
Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd | |||
ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd | |||
ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd | |||
ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd | |||
ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd | |||
ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd | |||
Keys(ctx context.Context, pattern string) *StringSliceCmd | |||
Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd | |||
Move(ctx context.Context, key string, db int) *BoolCmd | |||
@@ -139,6 +143,7 @@ type Cmdable interface { | |||
SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd | |||
SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd | |||
StrLen(ctx context.Context, key string) *IntCmd | |||
Copy(ctx context.Context, sourceKey string, destKey string, db int, replace bool) *IntCmd | |||
GetBit(ctx context.Context, key string, offset int64) *IntCmd | |||
SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd | |||
@@ -431,6 +436,7 @@ func (c statefulCmdable) AuthACL(ctx context.Context, username, password string) | |||
func (c cmdable) Wait(ctx context.Context, numSlaves int, timeout time.Duration) *IntCmd { | |||
cmd := NewIntCmd(ctx, "wait", numSlaves, int(timeout/time.Millisecond)) | |||
cmd.setReadTimeout(timeout) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -525,7 +531,37 @@ func (c cmdable) Exists(ctx context.Context, keys ...string) *IntCmd { | |||
} | |||
func (c cmdable) Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd { | |||
cmd := NewBoolCmd(ctx, "expire", key, formatSec(ctx, expiration)) | |||
return c.expire(ctx, key, expiration, "") | |||
} | |||
func (c cmdable) ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd { | |||
return c.expire(ctx, key, expiration, "NX") | |||
} | |||
func (c cmdable) ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd { | |||
return c.expire(ctx, key, expiration, "XX") | |||
} | |||
func (c cmdable) ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd { | |||
return c.expire(ctx, key, expiration, "GT") | |||
} | |||
func (c cmdable) ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd { | |||
return c.expire(ctx, key, expiration, "LT") | |||
} | |||
func (c cmdable) expire( | |||
ctx context.Context, key string, expiration time.Duration, mode string, | |||
) *BoolCmd { | |||
args := make([]interface{}, 3, 4) | |||
args[0] = "expire" | |||
args[1] = key | |||
args[2] = formatSec(ctx, expiration) | |||
if mode != "" { | |||
args = append(args, mode) | |||
} | |||
cmd := NewBoolCmd(ctx, args...) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -990,6 +1026,16 @@ func (c cmdable) StrLen(ctx context.Context, key string) *IntCmd { | |||
return cmd | |||
} | |||
func (c cmdable) Copy(ctx context.Context, sourceKey, destKey string, db int, replace bool) *IntCmd { | |||
args := []interface{}{"copy", sourceKey, destKey, "DB", db} | |||
if replace { | |||
args = append(args, "REPLACE") | |||
} | |||
cmd := NewIntCmd(ctx, args...) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
//------------------------------------------------------------------------------ | |||
func (c cmdable) GetBit(ctx context.Context, key string, offset int64) *IntCmd { | |||
@@ -1778,7 +1824,7 @@ type XReadArgs struct { | |||
} | |||
func (c cmdable) XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd { | |||
args := make([]interface{}, 0, 5+len(a.Streams)) | |||
args := make([]interface{}, 0, 6+len(a.Streams)) | |||
args = append(args, "xread") | |||
keyPos := int8(1) | |||
@@ -1802,7 +1848,7 @@ func (c cmdable) XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd { | |||
if a.Block >= 0 { | |||
cmd.setReadTimeout(a.Block) | |||
} | |||
cmd.setFirstKeyPos(keyPos) | |||
cmd.SetFirstKeyPos(keyPos) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -1860,7 +1906,7 @@ type XReadGroupArgs struct { | |||
} | |||
func (c cmdable) XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd { | |||
args := make([]interface{}, 0, 8+len(a.Streams)) | |||
args := make([]interface{}, 0, 10+len(a.Streams)) | |||
args = append(args, "xreadgroup", "group", a.Group, a.Consumer) | |||
keyPos := int8(4) | |||
@@ -1886,7 +1932,7 @@ func (c cmdable) XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSlic | |||
if a.Block >= 0 { | |||
cmd.setReadTimeout(a.Block) | |||
} | |||
cmd.setFirstKeyPos(keyPos) | |||
cmd.SetFirstKeyPos(keyPos) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -1957,7 +2003,7 @@ func (c cmdable) XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAuto | |||
} | |||
func xAutoClaimArgs(ctx context.Context, a *XAutoClaimArgs) []interface{} { | |||
args := make([]interface{}, 0, 9) | |||
args := make([]interface{}, 0, 8) | |||
args = append(args, "xautoclaim", a.Stream, a.Group, a.Consumer, formatMs(ctx, a.MinIdle), a.Start) | |||
if a.Count > 0 { | |||
args = append(args, "count", a.Count) | |||
@@ -1989,7 +2035,7 @@ func (c cmdable) XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCm | |||
} | |||
func xClaimArgs(a *XClaimArgs) []interface{} { | |||
args := make([]interface{}, 0, 4+len(a.Messages)) | |||
args := make([]interface{}, 0, 5+len(a.Messages)) | |||
args = append(args, | |||
"xclaim", | |||
a.Stream, | |||
@@ -2362,7 +2408,7 @@ func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZSt | |||
args = append(args, "zinterstore", destination, len(store.Keys)) | |||
args = store.appendArgs(args) | |||
cmd := NewIntCmd(ctx, args...) | |||
cmd.setFirstKeyPos(3) | |||
cmd.SetFirstKeyPos(3) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2372,7 +2418,7 @@ func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd { | |||
args = append(args, "zinter", len(store.Keys)) | |||
args = store.appendArgs(args) | |||
cmd := NewStringSliceCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2383,7 +2429,7 @@ func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd | |||
args = store.appendArgs(args) | |||
args = append(args, "withscores") | |||
cmd := NewZSliceCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2710,7 +2756,7 @@ func (c cmdable) ZUnion(ctx context.Context, store ZStore) *StringSliceCmd { | |||
args = append(args, "zunion", len(store.Keys)) | |||
args = store.appendArgs(args) | |||
cmd := NewStringSliceCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2721,7 +2767,7 @@ func (c cmdable) ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd | |||
args = store.appendArgs(args) | |||
args = append(args, "withscores") | |||
cmd := NewZSliceCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2731,7 +2777,7 @@ func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *I | |||
args = append(args, "zunionstore", dest, len(store.Keys)) | |||
args = store.appendArgs(args) | |||
cmd := NewIntCmd(ctx, args...) | |||
cmd.setFirstKeyPos(3) | |||
cmd.SetFirstKeyPos(3) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2761,7 +2807,7 @@ func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd { | |||
} | |||
cmd := NewStringSliceCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -2777,7 +2823,7 @@ func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd | |||
args[len(keys)+2] = "withscores" | |||
cmd := NewZSliceCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -3053,7 +3099,7 @@ func (c cmdable) MemoryUsage(ctx context.Context, key string, samples ...int) *I | |||
args = append(args, "SAMPLES", samples[0]) | |||
} | |||
cmd := NewIntCmd(ctx, args...) | |||
cmd.setFirstKeyPos(2) | |||
cmd.SetFirstKeyPos(2) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -3070,7 +3116,7 @@ func (c cmdable) Eval(ctx context.Context, script string, keys []string, args .. | |||
} | |||
cmdArgs = appendArgs(cmdArgs, args) | |||
cmd := NewCmd(ctx, cmdArgs...) | |||
cmd.setFirstKeyPos(3) | |||
cmd.SetFirstKeyPos(3) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -3085,7 +3131,7 @@ func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args . | |||
} | |||
cmdArgs = appendArgs(cmdArgs, args) | |||
cmd := NewCmd(ctx, cmdArgs...) | |||
cmd.setFirstKeyPos(3) | |||
cmd.SetFirstKeyPos(3) | |||
_ = c(ctx, cmd) | |||
return cmd | |||
} | |||
@@ -134,7 +134,7 @@ func isMovedSameConnAddr(err error, addr string) bool { | |||
if !strings.HasPrefix(redisError, "MOVED ") { | |||
return false | |||
} | |||
return strings.HasSuffix(redisError, addr) | |||
return strings.HasSuffix(redisError, " "+addr) | |||
} | |||
//------------------------------------------------------------------------------ | |||
@@ -10,6 +10,7 @@ import ( | |||
) | |||
// Scan parses bytes `b` to `v` with appropriate type. | |||
//nolint:gocyclo | |||
func Scan(b []byte, v interface{}) error { | |||
switch v := v.(type) { | |||
case nil: | |||
@@ -105,6 +106,13 @@ func Scan(b []byte, v interface{}) error { | |||
var err error | |||
*v, err = time.Parse(time.RFC3339Nano, util.BytesToString(b)) | |||
return err | |||
case *time.Duration: | |||
n, err := util.ParseInt(b, 10, 64) | |||
if err != nil { | |||
return err | |||
} | |||
*v = time.Duration(n) | |||
return nil | |||
case encoding.BinaryUnmarshaler: | |||
return v.UnmarshalBinary(b) | |||
default: | |||
@@ -98,6 +98,8 @@ func (w *Writer) WriteArg(v interface{}) error { | |||
case time.Time: | |||
w.numBuf = v.AppendFormat(w.numBuf[:0], time.RFC3339Nano) | |||
return w.bytes(w.numBuf) | |||
case time.Duration: | |||
return w.int(v.Nanoseconds()) | |||
case encoding.BinaryMarshaler: | |||
b, err := v.MarshalBinary() | |||
if err != nil { | |||
@@ -1,6 +1,6 @@ | |||
{ | |||
"name": "redis", | |||
"version": "8.11.4", | |||
"version": "8.11.5", | |||
"main": "index.js", | |||
"repository": "git@github.com:go-redis/redis.git", | |||
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>", | |||
@@ -24,6 +24,7 @@ type pipelineExecer func(context.Context, []Cmder) error | |||
// depends of your batch size and/or use TxPipeline. | |||
type Pipeliner interface { | |||
StatefulCmdable | |||
Len() int | |||
Do(ctx context.Context, args ...interface{}) *Cmd | |||
Process(ctx context.Context, cmd Cmder) error | |||
Close() error | |||
@@ -53,6 +54,15 @@ func (c *Pipeline) init() { | |||
c.statefulCmdable = c.Process | |||
} | |||
// Len returns the number of queued commands. | |||
func (c *Pipeline) Len() int { | |||
c.mu.Lock() | |||
ln := len(c.cmds) | |||
c.mu.Unlock() | |||
return ln | |||
} | |||
// Do queues the custom command for later execution. | |||
func (c *Pipeline) Do(ctx context.Context, args ...interface{}) *Cmd { | |||
cmd := NewCmd(ctx, args...) | |||
_ = c.Process(ctx, cmd) | |||
@@ -576,7 +576,7 @@ func (c *Ring) cmdInfo(ctx context.Context, name string) *CommandInfo { | |||
} | |||
info := cmdsInfo[name] | |||
if info == nil { | |||
internal.Logger.Printf(c.Context(), "info for cmd=%s not found", name) | |||
internal.Logger.Printf(ctx, "info for cmd=%s not found", name) | |||
} | |||
return info | |||
} | |||
@@ -25,6 +25,7 @@ type UniversalOptions struct { | |||
Username string | |||
Password string | |||
SentinelUsername string | |||
SentinelPassword string | |||
MaxRetries int | |||
@@ -114,6 +115,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions { | |||
DB: o.DB, | |||
Username: o.Username, | |||
Password: o.Password, | |||
SentinelUsername: o.SentinelUsername, | |||
SentinelPassword: o.SentinelPassword, | |||
MaxRetries: o.MaxRetries, | |||
@@ -2,5 +2,5 @@ package redis | |||
// Version is the current release version. | |||
func Version() string { | |||
return "8.11.4" | |||
return "8.11.5" | |||
} |
@@ -1,179 +0,0 @@ | |||
// Copyright 2016 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. | |||
package ptypes | |||
import ( | |||
"fmt" | |||
"strings" | |||
"github.com/golang/protobuf/proto" | |||
"google.golang.org/protobuf/reflect/protoreflect" | |||
"google.golang.org/protobuf/reflect/protoregistry" | |||
anypb "github.com/golang/protobuf/ptypes/any" | |||
) | |||
const urlPrefix = "type.googleapis.com/" | |||
// AnyMessageName returns the message name contained in an anypb.Any message. | |||
// Most type assertions should use the Is function instead. | |||
// | |||
// Deprecated: Call the any.MessageName method instead. | |||
func AnyMessageName(any *anypb.Any) (string, error) { | |||
name, err := anyMessageName(any) | |||
return string(name), err | |||
} | |||
func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) { | |||
if any == nil { | |||
return "", fmt.Errorf("message is nil") | |||
} | |||
name := protoreflect.FullName(any.TypeUrl) | |||
if i := strings.LastIndex(any.TypeUrl, "/"); i >= 0 { | |||
name = name[i+len("/"):] | |||
} | |||
if !name.IsValid() { | |||
return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) | |||
} | |||
return name, nil | |||
} | |||
// MarshalAny marshals the given message m into an anypb.Any message. | |||
// | |||
// Deprecated: Call the anypb.New function instead. | |||
func MarshalAny(m proto.Message) (*anypb.Any, error) { | |||
switch dm := m.(type) { | |||
case DynamicAny: | |||
m = dm.Message | |||
case *DynamicAny: | |||
if dm == nil { | |||
return nil, proto.ErrNil | |||
} | |||
m = dm.Message | |||
} | |||
b, err := proto.Marshal(m) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return &anypb.Any{TypeUrl: urlPrefix + proto.MessageName(m), Value: b}, nil | |||
} | |||
// Empty returns a new message of the type specified in an anypb.Any message. | |||
// It returns protoregistry.NotFound if the corresponding message type could not | |||
// be resolved in the global registry. | |||
// | |||
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead | |||
// to resolve the message name and create a new instance of it. | |||
func Empty(any *anypb.Any) (proto.Message, error) { | |||
name, err := anyMessageName(any) | |||
if err != nil { | |||
return nil, err | |||
} | |||
mt, err := protoregistry.GlobalTypes.FindMessageByName(name) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return proto.MessageV1(mt.New().Interface()), nil | |||
} | |||
// UnmarshalAny unmarshals the encoded value contained in the anypb.Any message | |||
// into the provided message m. It returns an error if the target message | |||
// does not match the type in the Any message or if an unmarshal error occurs. | |||
// | |||
// The target message m may be a *DynamicAny message. If the underlying message | |||
// type could not be resolved, then this returns protoregistry.NotFound. | |||
// | |||
// Deprecated: Call the any.UnmarshalTo method instead. | |||
func UnmarshalAny(any *anypb.Any, m proto.Message) error { | |||
if dm, ok := m.(*DynamicAny); ok { | |||
if dm.Message == nil { | |||
var err error | |||
dm.Message, err = Empty(any) | |||
if err != nil { | |||
return err | |||
} | |||
} | |||
m = dm.Message | |||
} | |||
anyName, err := AnyMessageName(any) | |||
if err != nil { | |||
return err | |||
} | |||
msgName := proto.MessageName(m) | |||
if anyName != msgName { | |||
return fmt.Errorf("mismatched message type: got %q want %q", anyName, msgName) | |||
} | |||
return proto.Unmarshal(any.Value, m) | |||
} | |||
// Is reports whether the Any message contains a message of the specified type. | |||
// | |||
// Deprecated: Call the any.MessageIs method instead. | |||
func Is(any *anypb.Any, m proto.Message) bool { | |||
if any == nil || m == nil { | |||
return false | |||
} | |||
name := proto.MessageName(m) | |||
if !strings.HasSuffix(any.TypeUrl, name) { | |||
return false | |||
} | |||
return len(any.TypeUrl) == len(name) || any.TypeUrl[len(any.TypeUrl)-len(name)-1] == '/' | |||
} | |||
// DynamicAny is a value that can be passed to UnmarshalAny to automatically | |||
// allocate a proto.Message for the type specified in an anypb.Any message. | |||
// The allocated message is stored in the embedded proto.Message. | |||
// | |||
// Example: | |||
// var x ptypes.DynamicAny | |||
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } | |||
// fmt.Printf("unmarshaled message: %v", x.Message) | |||
// | |||
// Deprecated: Use the any.UnmarshalNew method instead to unmarshal | |||
// the any message contents into a new instance of the underlying message. | |||
type DynamicAny struct{ proto.Message } | |||
func (m DynamicAny) String() string { | |||
if m.Message == nil { | |||
return "<nil>" | |||
} | |||
return m.Message.String() | |||
} | |||
func (m DynamicAny) Reset() { | |||
if m.Message == nil { | |||
return | |||
} | |||
m.Message.Reset() | |||
} | |||
func (m DynamicAny) ProtoMessage() { | |||
return | |||
} | |||
func (m DynamicAny) ProtoReflect() protoreflect.Message { | |||
if m.Message == nil { | |||
return nil | |||
} | |||
return dynamicAny{proto.MessageReflect(m.Message)} | |||
} | |||
type dynamicAny struct{ protoreflect.Message } | |||
func (m dynamicAny) Type() protoreflect.MessageType { | |||
return dynamicAnyType{m.Message.Type()} | |||
} | |||
func (m dynamicAny) New() protoreflect.Message { | |||
return dynamicAnyType{m.Message.Type()}.New() | |||
} | |||
func (m dynamicAny) Interface() protoreflect.ProtoMessage { | |||
return DynamicAny{proto.MessageV1(m.Message.Interface())} | |||
} | |||
type dynamicAnyType struct{ protoreflect.MessageType } | |||
func (t dynamicAnyType) New() protoreflect.Message { | |||
return dynamicAny{t.MessageType.New()} | |||
} | |||
func (t dynamicAnyType) Zero() protoreflect.Message { | |||
return dynamicAny{t.MessageType.Zero()} | |||
} |
@@ -1,62 +0,0 @@ | |||
// Code generated by protoc-gen-go. DO NOT EDIT. | |||
// source: github.com/golang/protobuf/ptypes/any/any.proto | |||
package any | |||
import ( | |||
protoreflect "google.golang.org/protobuf/reflect/protoreflect" | |||
protoimpl "google.golang.org/protobuf/runtime/protoimpl" | |||
anypb "google.golang.org/protobuf/types/known/anypb" | |||
reflect "reflect" | |||
) | |||
// Symbols defined in public import of google/protobuf/any.proto. | |||
type Any = anypb.Any | |||
var File_github_com_golang_protobuf_ptypes_any_any_proto protoreflect.FileDescriptor | |||
var file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = []byte{ | |||
0x0a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, | |||
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, | |||
0x70, 0x65, 0x73, 0x2f, 0x61, 0x6e, 0x79, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, | |||
0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, | |||
0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x2b, 0x5a, 0x29, | |||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, | |||
0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, | |||
0x73, 0x2f, 0x61, 0x6e, 0x79, 0x3b, 0x61, 0x6e, 0x79, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, | |||
0x74, 0x6f, 0x33, | |||
} | |||
var file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = []interface{}{} | |||
var file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = []int32{ | |||
0, // [0:0] is the sub-list for method output_type | |||
0, // [0:0] is the sub-list for method input_type | |||
0, // [0:0] is the sub-list for extension type_name | |||
0, // [0:0] is the sub-list for extension extendee | |||
0, // [0:0] is the sub-list for field type_name | |||
} | |||
func init() { file_github_com_golang_protobuf_ptypes_any_any_proto_init() } | |||
func file_github_com_golang_protobuf_ptypes_any_any_proto_init() { | |||
if File_github_com_golang_protobuf_ptypes_any_any_proto != nil { | |||
return | |||
} | |||
type x struct{} | |||
out := protoimpl.TypeBuilder{ | |||
File: protoimpl.DescBuilder{ | |||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | |||
RawDescriptor: file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc, | |||
NumEnums: 0, | |||
NumMessages: 0, | |||
NumExtensions: 0, | |||
NumServices: 0, | |||
}, | |||
GoTypes: file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes, | |||
DependencyIndexes: file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs, | |||
}.Build() | |||
File_github_com_golang_protobuf_ptypes_any_any_proto = out.File | |||
file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = nil | |||
file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = nil | |||
file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = nil | |||
} |
@@ -1,10 +0,0 @@ | |||
// Copyright 2016 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. | |||
// Package ptypes provides functionality for interacting with well-known types. | |||
// | |||
// Deprecated: Well-known types have specialized functionality directly | |||
// injected into the generated packages for each message type. | |||
// See the deprecation notice for each function for the suggested alternative. | |||
package ptypes |
@@ -1,76 +0,0 @@ | |||
// Copyright 2016 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. | |||
package ptypes | |||
import ( | |||
"errors" | |||
"fmt" | |||
"time" | |||
durationpb "github.com/golang/protobuf/ptypes/duration" | |||
) | |||
// Range of google.protobuf.Duration as specified in duration.proto. | |||
// This is about 10,000 years in seconds. | |||
const ( | |||
maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) | |||
minSeconds = -maxSeconds | |||
) | |||
// Duration converts a durationpb.Duration to a time.Duration. | |||
// Duration returns an error if dur is invalid or overflows a time.Duration. | |||
// | |||
// Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead. | |||
func Duration(dur *durationpb.Duration) (time.Duration, error) { | |||
if err := validateDuration(dur); err != nil { | |||
return 0, err | |||
} | |||
d := time.Duration(dur.Seconds) * time.Second | |||
if int64(d/time.Second) != dur.Seconds { | |||
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur) | |||
} | |||
if dur.Nanos != 0 { | |||
d += time.Duration(dur.Nanos) * time.Nanosecond | |||
if (d < 0) != (dur.Nanos < 0) { | |||
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur) | |||
} | |||
} | |||
return d, nil | |||
} | |||
// DurationProto converts a time.Duration to a durationpb.Duration. | |||
// | |||
// Deprecated: Call the durationpb.New function instead. | |||
func DurationProto(d time.Duration) *durationpb.Duration { | |||
nanos := d.Nanoseconds() | |||
secs := nanos / 1e9 | |||
nanos -= secs * 1e9 | |||
return &durationpb.Duration{ | |||
Seconds: int64(secs), | |||
Nanos: int32(nanos), | |||
} | |||
} | |||
// validateDuration determines whether the durationpb.Duration is valid | |||
// according to the definition in google/protobuf/duration.proto. | |||
// A valid durpb.Duration may still be too large to fit into a time.Duration | |||
// Note that the range of durationpb.Duration is about 10,000 years, | |||
// while the range of time.Duration is about 290 years. | |||
func validateDuration(dur *durationpb.Duration) error { | |||
if dur == nil { | |||
return errors.New("duration: nil Duration") | |||
} | |||
if dur.Seconds < minSeconds || dur.Seconds > maxSeconds { | |||
return fmt.Errorf("duration: %v: seconds out of range", dur) | |||
} | |||
if dur.Nanos <= -1e9 || dur.Nanos >= 1e9 { | |||
return fmt.Errorf("duration: %v: nanos out of range", dur) | |||
} | |||
// Seconds and Nanos must have the same sign, unless d.Nanos is zero. | |||
if (dur.Seconds < 0 && dur.Nanos > 0) || (dur.Seconds > 0 && dur.Nanos < 0) { | |||
return fmt.Errorf("duration: %v: seconds and nanos have different signs", dur) | |||
} | |||
return nil | |||
} |
@@ -1,63 +0,0 @@ | |||
// Code generated by protoc-gen-go. DO NOT EDIT. | |||
// source: github.com/golang/protobuf/ptypes/duration/duration.proto | |||
package duration | |||
import ( | |||
protoreflect "google.golang.org/protobuf/reflect/protoreflect" | |||
protoimpl "google.golang.org/protobuf/runtime/protoimpl" | |||
durationpb "google.golang.org/protobuf/types/known/durationpb" | |||
reflect "reflect" | |||
) | |||
// Symbols defined in public import of google/protobuf/duration.proto. | |||
type Duration = durationpb.Duration | |||
var File_github_com_golang_protobuf_ptypes_duration_duration_proto protoreflect.FileDescriptor | |||
var file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = []byte{ | |||
0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, | |||
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, | |||
0x70, 0x65, 0x73, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x75, 0x72, | |||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, | |||
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, | |||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x35, 0x5a, 0x33, 0x67, | |||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, | |||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, | |||
0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, | |||
0x6f, 0x6e, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | |||
} | |||
var file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = []interface{}{} | |||
var file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = []int32{ | |||
0, // [0:0] is the sub-list for method output_type | |||
0, // [0:0] is the sub-list for method input_type | |||
0, // [0:0] is the sub-list for extension type_name | |||
0, // [0:0] is the sub-list for extension extendee | |||
0, // [0:0] is the sub-list for field type_name | |||
} | |||
func init() { file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() } | |||
func file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() { | |||
if File_github_com_golang_protobuf_ptypes_duration_duration_proto != nil { | |||
return | |||
} | |||
type x struct{} | |||
out := protoimpl.TypeBuilder{ | |||
File: protoimpl.DescBuilder{ | |||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | |||
RawDescriptor: file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc, | |||
NumEnums: 0, | |||
NumMessages: 0, | |||
NumExtensions: 0, | |||
NumServices: 0, | |||
}, | |||
GoTypes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes, | |||
DependencyIndexes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs, | |||
}.Build() | |||
File_github_com_golang_protobuf_ptypes_duration_duration_proto = out.File | |||
file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = nil | |||
file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = nil | |||
file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = nil | |||
} |
@@ -1,112 +0,0 @@ | |||
// Copyright 2016 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. | |||
package ptypes | |||
import ( | |||
"errors" | |||
"fmt" | |||
"time" | |||
timestamppb "github.com/golang/protobuf/ptypes/timestamp" | |||
) | |||
// Range of google.protobuf.Duration as specified in timestamp.proto. | |||
const ( | |||
// Seconds field of the earliest valid Timestamp. | |||
// This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). | |||
minValidSeconds = -62135596800 | |||
// Seconds field just after the latest valid Timestamp. | |||
// This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). | |||
maxValidSeconds = 253402300800 | |||
) | |||
// Timestamp converts a timestamppb.Timestamp to a time.Time. | |||
// It returns an error if the argument is invalid. | |||
// | |||
// Unlike most Go functions, if Timestamp returns an error, the first return | |||
// value is not the zero time.Time. Instead, it is the value obtained from the | |||
// time.Unix function when passed the contents of the Timestamp, in the UTC | |||
// locale. This may or may not be a meaningful time; many invalid Timestamps | |||
// do map to valid time.Times. | |||
// | |||
// A nil Timestamp returns an error. The first return value in that case is | |||
// undefined. | |||
// | |||
// Deprecated: Call the ts.AsTime and ts.CheckValid methods instead. | |||
func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { | |||
// Don't return the zero value on error, because corresponds to a valid | |||
// timestamp. Instead return whatever time.Unix gives us. | |||
var t time.Time | |||
if ts == nil { | |||
t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp | |||
} else { | |||
t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() | |||
} | |||
return t, validateTimestamp(ts) | |||
} | |||
// TimestampNow returns a google.protobuf.Timestamp for the current time. | |||
// | |||
// Deprecated: Call the timestamppb.Now function instead. | |||
func TimestampNow() *timestamppb.Timestamp { | |||
ts, err := TimestampProto(time.Now()) | |||
if err != nil { | |||
panic("ptypes: time.Now() out of Timestamp range") | |||
} | |||
return ts | |||
} | |||
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. | |||
// It returns an error if the resulting Timestamp is invalid. | |||
// | |||
// Deprecated: Call the timestamppb.New function instead. | |||
func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { | |||
ts := ×tamppb.Timestamp{ | |||
Seconds: t.Unix(), | |||
Nanos: int32(t.Nanosecond()), | |||
} | |||
if err := validateTimestamp(ts); err != nil { | |||
return nil, err | |||
} | |||
return ts, nil | |||
} | |||
// TimestampString returns the RFC 3339 string for valid Timestamps. | |||
// For invalid Timestamps, it returns an error message in parentheses. | |||
// | |||
// Deprecated: Call the ts.AsTime method instead, | |||
// followed by a call to the Format method on the time.Time value. | |||
func TimestampString(ts *timestamppb.Timestamp) string { | |||
t, err := Timestamp(ts) | |||
if err != nil { | |||
return fmt.Sprintf("(%v)", err) | |||
} | |||
return t.Format(time.RFC3339Nano) | |||
} | |||
// validateTimestamp determines whether a Timestamp is valid. | |||
// A valid timestamp represents a time in the range [0001-01-01, 10000-01-01) | |||
// and has a Nanos field in the range [0, 1e9). | |||
// | |||
// If the Timestamp is valid, validateTimestamp returns nil. | |||
// Otherwise, it returns an error that describes the problem. | |||
// | |||
// Every valid Timestamp can be represented by a time.Time, | |||
// but the converse is not true. | |||
func validateTimestamp(ts *timestamppb.Timestamp) error { | |||
if ts == nil { | |||
return errors.New("timestamp: nil Timestamp") | |||
} | |||
if ts.Seconds < minValidSeconds { | |||
return fmt.Errorf("timestamp: %v before 0001-01-01", ts) | |||
} | |||
if ts.Seconds >= maxValidSeconds { | |||
return fmt.Errorf("timestamp: %v after 10000-01-01", ts) | |||
} | |||
if ts.Nanos < 0 || ts.Nanos >= 1e9 { | |||
return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts) | |||
} | |||
return nil | |||
} |
@@ -197,14 +197,6 @@ func goRuntimeMemStats() memStatsMetrics { | |||
), | |||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, | |||
valType: GaugeValue, | |||
}, { | |||
desc: NewDesc( | |||
memstatNamespace("gc_cpu_fraction"), | |||
"The fraction of this program's available CPU time used by the GC since the program started.", | |||
nil, nil, | |||
), | |||
eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction }, | |||
valType: GaugeValue, | |||
}, | |||
} | |||
} | |||
@@ -268,7 +260,6 @@ func (c *baseGoCollector) Collect(ch chan<- Metric) { | |||
quantiles[0.0] = stats.PauseQuantiles[0].Seconds() | |||
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles) | |||
ch <- MustNewConstMetric(c.gcLastTimeDesc, GaugeValue, float64(stats.LastGC.UnixNano())/1e9) | |||
ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1) | |||
} | |||
@@ -278,6 +269,7 @@ func memstatNamespace(s string) string { | |||
// memStatsMetrics provide description, evaluator, runtime/metrics name, and | |||
// value type for memstat metrics. | |||
// TODO(bwplotka): Remove with end Go 1.16 EOL and replace with runtime/metrics.Description | |||
type memStatsMetrics []struct { | |||
desc *Desc | |||
eval func(*runtime.MemStats) float64 | |||
@@ -40,13 +40,28 @@ type goCollector struct { | |||
// | |||
// Deprecated: Use collectors.NewGoCollector instead. | |||
func NewGoCollector() Collector { | |||
msMetrics := goRuntimeMemStats() | |||
msMetrics = append(msMetrics, struct { | |||
desc *Desc | |||
eval func(*runtime.MemStats) float64 | |||
valType ValueType | |||
}{ | |||
// This metric is omitted in Go1.17+, see https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 | |||
desc: NewDesc( | |||
memstatNamespace("gc_cpu_fraction"), | |||
"The fraction of this program's available CPU time used by the GC since the program started.", | |||
nil, nil, | |||
), | |||
eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction }, | |||
valType: GaugeValue, | |||
}) | |||
return &goCollector{ | |||
base: newBaseGoCollector(), | |||
msLast: &runtime.MemStats{}, | |||
msRead: runtime.ReadMemStats, | |||
msMaxWait: time.Second, | |||
msMaxAge: 5 * time.Minute, | |||
msMetrics: goRuntimeMemStats(), | |||
msMetrics: msMetrics, | |||
} | |||
} | |||
@@ -25,11 +25,71 @@ import ( | |||
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. | |||
"github.com/golang/protobuf/proto" | |||
"github.com/prometheus/client_golang/prometheus/internal" | |||
dto "github.com/prometheus/client_model/go" | |||
"github.com/prometheus/client_golang/prometheus/internal" | |||
) | |||
const ( | |||
goGCHeapTinyAllocsObjects = "/gc/heap/tiny/allocs:objects" | |||
goGCHeapAllocsObjects = "/gc/heap/allocs:objects" | |||
goGCHeapFreesObjects = "/gc/heap/frees:objects" | |||
goGCHeapAllocsBytes = "/gc/heap/allocs:bytes" | |||
goGCHeapObjects = "/gc/heap/objects:objects" | |||
goGCHeapGoalBytes = "/gc/heap/goal:bytes" | |||
goMemoryClassesTotalBytes = "/memory/classes/total:bytes" | |||
goMemoryClassesHeapObjectsBytes = "/memory/classes/heap/objects:bytes" | |||
goMemoryClassesHeapUnusedBytes = "/memory/classes/heap/unused:bytes" | |||
goMemoryClassesHeapReleasedBytes = "/memory/classes/heap/released:bytes" | |||
goMemoryClassesHeapFreeBytes = "/memory/classes/heap/free:bytes" | |||
goMemoryClassesHeapStacksBytes = "/memory/classes/heap/stacks:bytes" | |||
goMemoryClassesOSStacksBytes = "/memory/classes/os-stacks:bytes" | |||
goMemoryClassesMetadataMSpanInuseBytes = "/memory/classes/metadata/mspan/inuse:bytes" | |||
goMemoryClassesMetadataMSPanFreeBytes = "/memory/classes/metadata/mspan/free:bytes" | |||
goMemoryClassesMetadataMCacheInuseBytes = "/memory/classes/metadata/mcache/inuse:bytes" | |||
goMemoryClassesMetadataMCacheFreeBytes = "/memory/classes/metadata/mcache/free:bytes" | |||
goMemoryClassesProfilingBucketsBytes = "/memory/classes/profiling/buckets:bytes" | |||
goMemoryClassesMetadataOtherBytes = "/memory/classes/metadata/other:bytes" | |||
goMemoryClassesOtherBytes = "/memory/classes/other:bytes" | |||
) | |||
// runtime/metrics names required for runtimeMemStats like logic. | |||
var rmForMemStats = []string{goGCHeapTinyAllocsObjects, | |||
goGCHeapAllocsObjects, | |||
goGCHeapFreesObjects, | |||
goGCHeapAllocsBytes, | |||
goGCHeapObjects, | |||
goGCHeapGoalBytes, | |||
goMemoryClassesTotalBytes, | |||
goMemoryClassesHeapObjectsBytes, | |||
goMemoryClassesHeapUnusedBytes, | |||
goMemoryClassesHeapReleasedBytes, | |||
goMemoryClassesHeapFreeBytes, | |||
goMemoryClassesHeapStacksBytes, | |||
goMemoryClassesOSStacksBytes, | |||
goMemoryClassesMetadataMSpanInuseBytes, | |||
goMemoryClassesMetadataMSPanFreeBytes, | |||
goMemoryClassesMetadataMCacheInuseBytes, | |||
goMemoryClassesMetadataMCacheFreeBytes, | |||
goMemoryClassesProfilingBucketsBytes, | |||
goMemoryClassesMetadataOtherBytes, | |||
goMemoryClassesOtherBytes, | |||
} | |||
func bestEffortLookupRM(lookup []string) []metrics.Description { | |||
ret := make([]metrics.Description, 0, len(lookup)) | |||
for _, rm := range metrics.All() { | |||
for _, m := range lookup { | |||
if m == rm.Name { | |||
ret = append(ret, rm) | |||
} | |||
} | |||
} | |||
return ret | |||
} | |||
type goCollector struct { | |||
opt GoCollectorOptions | |||
base baseGoCollector | |||
// mu protects updates to all fields ensuring a consistent | |||
@@ -51,12 +111,46 @@ type goCollector struct { | |||
msMetrics memStatsMetrics | |||
} | |||
const ( | |||
// Those are not exposed due to need to move Go collector to another package in v2. | |||
// See issue https://github.com/prometheus/client_golang/issues/1030. | |||
goRuntimeMemStatsCollection uint32 = 1 << iota | |||
goRuntimeMetricsCollection | |||
) | |||
// GoCollectorOptions should not be used be directly by anything, except `collectors` package. | |||
// Use it via collectors package instead. See issue | |||
// https://github.com/prometheus/client_golang/issues/1030. | |||
// | |||
// Deprecated: Use collectors.WithGoCollections | |||
type GoCollectorOptions struct { | |||
// EnabledCollection sets what type of collections collector should expose on top of base collection. | |||
// By default it's goMemStatsCollection | goRuntimeMetricsCollection. | |||
EnabledCollections uint32 | |||
} | |||
func (c GoCollectorOptions) isEnabled(flag uint32) bool { | |||
return c.EnabledCollections&flag != 0 | |||
} | |||
const defaultGoCollections = goRuntimeMemStatsCollection | |||
// NewGoCollector is the obsolete version of collectors.NewGoCollector. | |||
// See there for documentation. | |||
// | |||
// Deprecated: Use collectors.NewGoCollector instead. | |||
func NewGoCollector() Collector { | |||
descriptions := metrics.All() | |||
func NewGoCollector(opts ...func(o *GoCollectorOptions)) Collector { | |||
opt := GoCollectorOptions{EnabledCollections: defaultGoCollections} | |||
for _, o := range opts { | |||
o(&opt) | |||
} | |||
var descriptions []metrics.Description | |||
if opt.isEnabled(goRuntimeMetricsCollection) { | |||
descriptions = metrics.All() | |||
} else if opt.isEnabled(goRuntimeMemStatsCollection) { | |||
descriptions = bestEffortLookupRM(rmForMemStats) | |||
} | |||
// Collect all histogram samples so that we can get their buckets. | |||
// The API guarantees that the buckets are always fixed for the lifetime | |||
@@ -67,7 +161,11 @@ func NewGoCollector() Collector { | |||
histograms = append(histograms, metrics.Sample{Name: d.Name}) | |||
} | |||
} | |||
metrics.Read(histograms) | |||
if len(histograms) > 0 { | |||
metrics.Read(histograms) | |||
} | |||
bucketsMap := make(map[string][]float64) | |||
for i := range histograms { | |||
bucketsMap[histograms[i].Name] = histograms[i].Value.Float64Histogram().Buckets | |||
@@ -83,7 +181,7 @@ func NewGoCollector() Collector { | |||
if !ok { | |||
// Just ignore this metric; we can't do anything with it here. | |||
// If a user decides to use the latest version of Go, we don't want | |||
// to fail here. This condition is tested elsewhere. | |||
// to fail here. This condition is tested in TestExpectedRuntimeMetrics. | |||
continue | |||
} | |||
@@ -123,12 +221,18 @@ func NewGoCollector() Collector { | |||
} | |||
metricSet = append(metricSet, m) | |||
} | |||
var msMetrics memStatsMetrics | |||
if opt.isEnabled(goRuntimeMemStatsCollection) { | |||
msMetrics = goRuntimeMemStats() | |||
} | |||
return &goCollector{ | |||
opt: opt, | |||
base: newBaseGoCollector(), | |||
rmSampleBuf: sampleBuf, | |||
rmSampleMap: sampleMap, | |||
rmMetrics: metricSet, | |||
msMetrics: goRuntimeMemStats(), | |||
msMetrics: msMetrics, | |||
} | |||
} | |||
@@ -163,40 +267,47 @@ func (c *goCollector) Collect(ch chan<- Metric) { | |||
c.mu.Lock() | |||
defer c.mu.Unlock() | |||
// Populate runtime/metrics sample buffer. | |||
metrics.Read(c.rmSampleBuf) | |||
// Update all our metrics from rmSampleBuf. | |||
for i, sample := range c.rmSampleBuf { | |||
// N.B. switch on concrete type because it's significantly more efficient | |||
// than checking for the Counter and Gauge interface implementations. In | |||
// this case, we control all the types here. | |||
switch m := c.rmMetrics[i].(type) { | |||
case *counter: | |||
// Guard against decreases. This should never happen, but a failure | |||
// to do so will result in a panic, which is a harsh consequence for | |||
// a metrics collection bug. | |||
v0, v1 := m.get(), unwrapScalarRMValue(sample.Value) | |||
if v1 > v0 { | |||
m.Add(unwrapScalarRMValue(sample.Value) - m.get()) | |||
if len(c.rmSampleBuf) > 0 { | |||
// Populate runtime/metrics sample buffer. | |||
metrics.Read(c.rmSampleBuf) | |||
} | |||
if c.opt.isEnabled(goRuntimeMetricsCollection) { | |||
// Collect all our metrics from rmSampleBuf. | |||
for i, sample := range c.rmSampleBuf { | |||
// N.B. switch on concrete type because it's significantly more efficient | |||
// than checking for the Counter and Gauge interface implementations. In | |||
// this case, we control all the types here. | |||
switch m := c.rmMetrics[i].(type) { | |||
case *counter: | |||
// Guard against decreases. This should never happen, but a failure | |||
// to do so will result in a panic, which is a harsh consequence for | |||
// a metrics collection bug. | |||
v0, v1 := m.get(), unwrapScalarRMValue(sample.Value) | |||
if v1 > v0 { | |||
m.Add(unwrapScalarRMValue(sample.Value) - m.get()) | |||
} | |||
m.Collect(ch) | |||
case *gauge: | |||
m.Set(unwrapScalarRMValue(sample.Value)) | |||
m.Collect(ch) | |||
case *batchHistogram: | |||
m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name)) | |||
m.Collect(ch) | |||
default: | |||
panic("unexpected metric type") | |||
} | |||
m.Collect(ch) | |||
case *gauge: | |||
m.Set(unwrapScalarRMValue(sample.Value)) | |||
m.Collect(ch) | |||
case *batchHistogram: | |||
m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name)) | |||
m.Collect(ch) | |||
default: | |||
panic("unexpected metric type") | |||
} | |||
} | |||
// ms is a dummy MemStats that we populate ourselves so that we can | |||
// populate the old metrics from it. | |||
var ms runtime.MemStats | |||
memStatsFromRM(&ms, c.rmSampleMap) | |||
for _, i := range c.msMetrics { | |||
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(&ms)) | |||
// populate the old metrics from it if goMemStatsCollection is enabled. | |||
if c.opt.isEnabled(goRuntimeMemStatsCollection) { | |||
var ms runtime.MemStats | |||
memStatsFromRM(&ms, c.rmSampleMap) | |||
for _, i := range c.msMetrics { | |||
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(&ms)) | |||
} | |||
} | |||
} | |||
@@ -261,35 +372,30 @@ func memStatsFromRM(ms *runtime.MemStats, rm map[string]*metrics.Sample) { | |||
// while having Mallocs - Frees still represent a live object count. | |||
// Unfortunately, MemStats doesn't actually export a large allocation count, | |||
// so it's impossible to pull this number out directly. | |||
tinyAllocs := lookupOrZero("/gc/heap/tiny/allocs:objects") | |||
ms.Mallocs = lookupOrZero("/gc/heap/allocs:objects") + tinyAllocs | |||
ms.Frees = lookupOrZero("/gc/heap/frees:objects") + tinyAllocs | |||
tinyAllocs := lookupOrZero(goGCHeapTinyAllocsObjects) | |||
ms.Mallocs = lookupOrZero(goGCHeapAllocsObjects) + tinyAllocs | |||
ms.Frees = lookupOrZero(goGCHeapFreesObjects) + tinyAllocs | |||
ms.TotalAlloc = lookupOrZero("/gc/heap/allocs:bytes") | |||
ms.Sys = lookupOrZero("/memory/classes/total:bytes") | |||
ms.TotalAlloc = lookupOrZero(goGCHeapAllocsBytes) | |||
ms.Sys = lookupOrZero(goMemoryClassesTotalBytes) | |||
ms.Lookups = 0 // Already always zero. | |||
ms.HeapAlloc = lookupOrZero("/memory/classes/heap/objects:bytes") | |||
ms.HeapAlloc = lookupOrZero(goMemoryClassesHeapObjectsBytes) | |||
ms.Alloc = ms.HeapAlloc | |||
ms.HeapInuse = ms.HeapAlloc + lookupOrZero("/memory/classes/heap/unused:bytes") | |||
ms.HeapReleased = lookupOrZero("/memory/classes/heap/released:bytes") | |||
ms.HeapIdle = ms.HeapReleased + lookupOrZero("/memory/classes/heap/free:bytes") | |||
ms.HeapInuse = ms.HeapAlloc + lookupOrZero(goMemoryClassesHeapUnusedBytes) | |||
ms.HeapReleased = lookupOrZero(goMemoryClassesHeapReleasedBytes) | |||
ms.HeapIdle = ms.HeapReleased + lookupOrZero(goMemoryClassesHeapFreeBytes) | |||
ms.HeapSys = ms.HeapInuse + ms.HeapIdle | |||
ms.HeapObjects = lookupOrZero("/gc/heap/objects:objects") | |||
ms.StackInuse = lookupOrZero("/memory/classes/heap/stacks:bytes") | |||
ms.StackSys = ms.StackInuse + lookupOrZero("/memory/classes/os-stacks:bytes") | |||
ms.MSpanInuse = lookupOrZero("/memory/classes/metadata/mspan/inuse:bytes") | |||
ms.MSpanSys = ms.MSpanInuse + lookupOrZero("/memory/classes/metadata/mspan/free:bytes") | |||
ms.MCacheInuse = lookupOrZero("/memory/classes/metadata/mcache/inuse:bytes") | |||
ms.MCacheSys = ms.MCacheInuse + lookupOrZero("/memory/classes/metadata/mcache/free:bytes") | |||
ms.BuckHashSys = lookupOrZero("/memory/classes/profiling/buckets:bytes") | |||
ms.GCSys = lookupOrZero("/memory/classes/metadata/other:bytes") | |||
ms.OtherSys = lookupOrZero("/memory/classes/other:bytes") | |||
ms.NextGC = lookupOrZero("/gc/heap/goal:bytes") | |||
// N.B. LastGC is omitted because runtime.GCStats already has this. | |||
// See https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 | |||
// for more details. | |||
ms.LastGC = 0 | |||
ms.HeapObjects = lookupOrZero(goGCHeapObjects) | |||
ms.StackInuse = lookupOrZero(goMemoryClassesHeapStacksBytes) | |||
ms.StackSys = ms.StackInuse + lookupOrZero(goMemoryClassesOSStacksBytes) | |||
ms.MSpanInuse = lookupOrZero(goMemoryClassesMetadataMSpanInuseBytes) | |||
ms.MSpanSys = ms.MSpanInuse + lookupOrZero(goMemoryClassesMetadataMSPanFreeBytes) | |||
ms.MCacheInuse = lookupOrZero(goMemoryClassesMetadataMCacheInuseBytes) | |||
ms.MCacheSys = ms.MCacheInuse + lookupOrZero(goMemoryClassesMetadataMCacheFreeBytes) | |||
ms.BuckHashSys = lookupOrZero(goMemoryClassesProfilingBucketsBytes) | |||
ms.GCSys = lookupOrZero(goMemoryClassesMetadataOtherBytes) | |||
ms.OtherSys = lookupOrZero(goMemoryClassesOtherBytes) | |||
ms.NextGC = lookupOrZero(goGCHeapGoalBytes) | |||
// N.B. GCCPUFraction is intentionally omitted. This metric is not useful, | |||
// and often misleading due to the fact that it's an average over the lifetime | |||
@@ -324,6 +430,11 @@ type batchHistogram struct { | |||
// buckets must always be from the runtime/metrics package, following | |||
// the same conventions. | |||
func newBatchHistogram(desc *Desc, buckets []float64, hasSum bool) *batchHistogram { | |||
// We need to remove -Inf values. runtime/metrics keeps them around. | |||
// But -Inf bucket should not be allowed for prometheus histograms. | |||
if buckets[0] == math.Inf(-1) { | |||
buckets = buckets[1:] | |||
} | |||
h := &batchHistogram{ | |||
desc: desc, | |||
buckets: buckets, | |||
@@ -382,8 +493,10 @@ func (h *batchHistogram) Write(out *dto.Metric) error { | |||
for i, count := range h.counts { | |||
totalCount += count | |||
if !h.hasSum { | |||
// N.B. This computed sum is an underestimate. | |||
sum += h.buckets[i] * float64(count) | |||
if count != 0 { | |||
// N.B. This computed sum is an underestimate. | |||
sum += h.buckets[i] * float64(count) | |||
} | |||
} | |||
// Skip the +Inf bucket, but only for the bucket list. |
@@ -62,7 +62,7 @@ func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool) | |||
// other data. | |||
name = strings.ReplaceAll(name, "-", "_") | |||
name = name + "_" + unit | |||
if d.Cumulative { | |||
if d.Cumulative && d.Kind != metrics.KindFloat64Histogram { | |||
name = name + "_total" | |||
} | |||
@@ -84,12 +84,12 @@ func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool) | |||
func RuntimeMetricsBucketsForUnit(buckets []float64, unit string) []float64 { | |||
switch unit { | |||
case "bytes": | |||
// Rebucket as powers of 2. | |||
return rebucketExp(buckets, 2) | |||
// Re-bucket as powers of 2. | |||
return reBucketExp(buckets, 2) | |||
case "seconds": | |||
// Rebucket as powers of 10 and then merge all buckets greater | |||
// Re-bucket as powers of 10 and then merge all buckets greater | |||
// than 1 second into the +Inf bucket. | |||
b := rebucketExp(buckets, 10) | |||
b := reBucketExp(buckets, 10) | |||
for i := range b { | |||
if b[i] <= 1 { | |||
continue | |||
@@ -103,11 +103,11 @@ func RuntimeMetricsBucketsForUnit(buckets []float64, unit string) []float64 { | |||
return buckets | |||
} | |||
// rebucketExp takes a list of bucket boundaries (lower bound inclusive) and | |||
// reBucketExp takes a list of bucket boundaries (lower bound inclusive) and | |||
// downsamples the buckets to those a multiple of base apart. The end result | |||
// is a roughly exponential (in many cases, perfectly exponential) bucketing | |||
// scheme. | |||
func rebucketExp(buckets []float64, base float64) []float64 { | |||
func reBucketExp(buckets []float64, base float64) []float64 { | |||
bucket := buckets[0] | |||
var newBuckets []float64 | |||
// We may see a -Inf here, in which case, add it and skip it | |||
@@ -12,6 +12,7 @@ | |||
// limitations under the License. | |||
// Build only when actually fuzzing | |||
//go:build gofuzz | |||
// +build gofuzz | |||
package expfmt | |||
@@ -22,7 +22,6 @@ import ( | |||
"strconv" | |||
"strings" | |||
"github.com/golang/protobuf/ptypes" | |||
"github.com/prometheus/common/model" | |||
dto "github.com/prometheus/client_model/go" | |||
@@ -473,10 +472,11 @@ func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { | |||
if err != nil { | |||
return written, err | |||
} | |||
ts, err := ptypes.Timestamp((*e).Timestamp) | |||
err = (*e).Timestamp.CheckValid() | |||
if err != nil { | |||
return written, err | |||
} | |||
ts := (*e).Timestamp.AsTime() | |||
// TODO(beorn7): Format this directly from components of ts to | |||
// avoid overflow/underflow and precision issues of the float | |||
// conversion. | |||
@@ -193,7 +193,7 @@ func ParseDuration(durationStr string) (Duration, error) { | |||
// Allow 0 without a unit. | |||
return 0, nil | |||
case "": | |||
return 0, fmt.Errorf("empty duration string") | |||
return 0, errors.New("empty duration string") | |||
} | |||
matches := durationRE.FindStringSubmatch(durationStr) | |||
if matches == nil { | |||
@@ -1 +1,2 @@ | |||
/fixtures/ | |||
/testdata/fixtures/ | |||
/fixtures |
@@ -1,4 +1,12 @@ | |||
--- | |||
linters: | |||
enable: | |||
- golint | |||
- godot | |||
- revive | |||
linter-settings: | |||
godot: | |||
capital: true | |||
exclude: | |||
# Ignore "See: URL" | |||
- 'See:' |
@@ -1,3 +1,3 @@ | |||
## Prometheus Community Code of Conduct | |||
# Prometheus Community Code of Conduct | |||
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). | |||
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). |
@@ -97,7 +97,7 @@ Many of the files are changing continuously and the data being read can in some | |||
reads in the same file. Also, most of the files are relatively small (less than a few KBs), and system calls | |||
to the `stat` function will often return the wrong size. Therefore, for most files it's recommended to read the | |||
full file in a single operation using an internal utility function called `util.ReadFileNoStat`. | |||
This function is similar to `ioutil.ReadFile`, but it avoids the system call to `stat` to get the current size of | |||
This function is similar to `os.ReadFile`, but it avoids the system call to `stat` to get the current size of | |||
the file. | |||
Note that parsing the file's contents can still be performed one line at a time. This is done by first reading | |||
@@ -113,7 +113,7 @@ the full file, and then using a scanner on the `[]byte` or `string` containing t | |||
``` | |||
The `/sys` filesystem contains many very small files which contain only a single numeric or text value. These files | |||
can be read using an internal function called `util.SysReadFile` which is similar to `ioutil.ReadFile` but does | |||
can be read using an internal function called `util.SysReadFile` which is similar to `os.ReadFile` but does | |||
not bother to check the size of the file before reading. | |||
``` | |||
data, err := util.SysReadFile("/sys/class/power_supply/BAT0/capacity") | |||
@@ -14,18 +14,18 @@ | |||
include Makefile.common | |||
%/.unpacked: %.ttar | |||
@echo ">> extracting fixtures" | |||
@echo ">> extracting fixtures $*" | |||
./ttar -C $(dir $*) -x -f $*.ttar | |||
touch $@ | |||
fixtures: fixtures/.unpacked | |||
fixtures: testdata/fixtures/.unpacked | |||
update_fixtures: | |||
rm -vf fixtures/.unpacked | |||
./ttar -c -f fixtures.ttar fixtures/ | |||
rm -vf testdata/fixtures/.unpacked | |||
./ttar -c -f testdata/fixtures.ttar -C testdata/ fixtures/ | |||
.PHONY: build | |||
build: | |||
.PHONY: test | |||
test: fixtures/.unpacked common-test | |||
test: testdata/fixtures/.unpacked common-test |
@@ -36,29 +36,6 @@ GO_VERSION ?= $(shell $(GO) version) | |||
GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) | |||
PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') | |||
GOVENDOR := | |||
GO111MODULE := | |||
ifeq (, $(PRE_GO_111)) | |||
ifneq (,$(wildcard go.mod)) | |||
# Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). | |||
GO111MODULE := on | |||
ifneq (,$(wildcard vendor)) | |||
# Always use the local vendor/ directory to satisfy the dependencies. | |||
GOOPTS := $(GOOPTS) -mod=vendor | |||
endif | |||
endif | |||
else | |||
ifneq (,$(wildcard go.mod)) | |||
ifneq (,$(wildcard vendor)) | |||
$(warning This repository requires Go >= 1.11 because of Go modules) | |||
$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)') | |||
endif | |||
else | |||
# This repository isn't using Go modules (yet). | |||
GOVENDOR := $(FIRST_GOPATH)/bin/govendor | |||
endif | |||
endif | |||
PROMU := $(FIRST_GOPATH)/bin/promu | |||
pkgs = ./... | |||
@@ -78,17 +55,23 @@ ifneq ($(shell which gotestsum),) | |||
endif | |||
endif | |||
PROMU_VERSION ?= 0.12.0 | |||
PROMU_VERSION ?= 0.13.0 | |||
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz | |||
GOLANGCI_LINT := | |||
GOLANGCI_LINT_OPTS ?= | |||
GOLANGCI_LINT_VERSION ?= v1.39.0 | |||
GOLANGCI_LINT_VERSION ?= v1.45.2 | |||
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64. | |||
# windows isn't included here because of the path separator being different. | |||
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) | |||
ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) | |||
GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint | |||
# If we're in CI and there is an Actions file, that means the linter | |||
# is being run in Actions, so we don't need to run it here. | |||
ifeq (,$(CIRCLE_JOB)) | |||
GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint | |||
else ifeq (,$(wildcard .github/workflows/golangci-lint.yml)) | |||
GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint | |||
endif | |||
endif | |||
endif | |||
@@ -144,32 +127,25 @@ common-check_license: | |||
.PHONY: common-deps | |||
common-deps: | |||
@echo ">> getting dependencies" | |||
ifdef GO111MODULE | |||
GO111MODULE=$(GO111MODULE) $(GO) mod download | |||
else | |||
$(GO) get $(GOOPTS) -t ./... | |||
endif | |||
$(GO) mod download | |||
.PHONY: update-go-deps | |||
update-go-deps: | |||
@echo ">> updating Go dependencies" | |||
@for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ | |||
$(GO) get $$m; \ | |||
$(GO) get -d $$m; \ | |||
done | |||
GO111MODULE=$(GO111MODULE) $(GO) mod tidy | |||
ifneq (,$(wildcard vendor)) | |||
GO111MODULE=$(GO111MODULE) $(GO) mod vendor | |||
endif | |||
$(GO) mod tidy | |||
.PHONY: common-test-short | |||
common-test-short: $(GOTEST_DIR) | |||
@echo ">> running short tests" | |||
GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) | |||
$(GOTEST) -short $(GOOPTS) $(pkgs) | |||
.PHONY: common-test | |||
common-test: $(GOTEST_DIR) | |||
@echo ">> running all tests" | |||
GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) | |||
$(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) | |||
$(GOTEST_DIR): | |||
@mkdir -p $@ | |||
@@ -177,25 +153,21 @@ $(GOTEST_DIR): | |||
.PHONY: common-format | |||
common-format: | |||
@echo ">> formatting code" | |||
GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) | |||
$(GO) fmt $(pkgs) | |||
.PHONY: common-vet | |||
common-vet: | |||
@echo ">> vetting code" | |||
GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) | |||
$(GO) vet $(GOOPTS) $(pkgs) | |||
.PHONY: common-lint | |||
common-lint: $(GOLANGCI_LINT) | |||
ifdef GOLANGCI_LINT | |||
@echo ">> running golangci-lint" | |||
ifdef GO111MODULE | |||
# 'go list' needs to be executed before staticcheck to prepopulate the modules cache. | |||
# Otherwise staticcheck might fail randomly for some reason not yet explained. | |||
GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null | |||
GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) | |||
else | |||
$(GOLANGCI_LINT) run $(pkgs) | |||
endif | |||
$(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null | |||
$(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) | |||
endif | |||
.PHONY: common-yamllint | |||
@@ -212,28 +184,15 @@ endif | |||
common-staticcheck: lint | |||
.PHONY: common-unused | |||
common-unused: $(GOVENDOR) | |||
ifdef GOVENDOR | |||
@echo ">> running check for unused packages" | |||
@$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages' | |||
else | |||
ifdef GO111MODULE | |||
common-unused: | |||
@echo ">> running check for unused/missing packages in go.mod" | |||
GO111MODULE=$(GO111MODULE) $(GO) mod tidy | |||
ifeq (,$(wildcard vendor)) | |||
$(GO) mod tidy | |||
@git diff --exit-code -- go.sum go.mod | |||
else | |||
@echo ">> running check for unused packages in vendor/" | |||
GO111MODULE=$(GO111MODULE) $(GO) mod vendor | |||
@git diff --exit-code -- go.sum go.mod vendor/ | |||
endif | |||
endif | |||
endif | |||
.PHONY: common-build | |||
common-build: promu | |||
@echo ">> building binaries" | |||
GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) | |||
$(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) | |||
.PHONY: common-tarball | |||
common-tarball: promu | |||
@@ -289,12 +248,6 @@ $(GOLANGCI_LINT): | |||
| sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) | |||
endif | |||
ifdef GOVENDOR | |||
.PHONY: $(GOVENDOR) | |||
$(GOVENDOR): | |||
GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor | |||
endif | |||
.PHONY: precheck | |||
precheck:: | |||
@@ -3,4 +3,4 @@ | |||
The Prometheus security policy, including how to report vulnerabilities, can be | |||
found here: | |||
https://prometheus.io/docs/operating/security/ | |||
<https://prometheus.io/docs/operating/security/> |
@@ -15,11 +15,28 @@ package procfs | |||
import ( | |||
"fmt" | |||
"io/ioutil" | |||
"net" | |||
"os" | |||
"strconv" | |||
"strings" | |||
) | |||
// Learned from include/uapi/linux/if_arp.h. | |||
const ( | |||
// completed entry (ha valid). | |||
ATFComplete = 0x02 | |||
// permanent entry. | |||
ATFPermanent = 0x04 | |||
// Publish entry. | |||
ATFPublish = 0x08 | |||
// Has requested trailers. | |||
ATFUseTrailers = 0x10 | |||
// Obsoleted: Want to use a netmask (only for proxy entries). | |||
ATFNetmask = 0x20 | |||
// Don't answer this addresses. | |||
ATFDontPublish = 0x40 | |||
) | |||
// ARPEntry contains a single row of the columnar data represented in | |||
// /proc/net/arp. | |||
type ARPEntry struct { | |||
@@ -29,12 +46,14 @@ type ARPEntry struct { | |||
HWAddr net.HardwareAddr | |||
// Name of the device | |||
Device string | |||
// Flags | |||
Flags byte | |||
} | |||
// GatherARPEntries retrieves all the ARP entries, parse the relevant columns, | |||
// and then return a slice of ARPEntry's. | |||
func (fs FS) GatherARPEntries() ([]ARPEntry, error) { | |||
data, err := ioutil.ReadFile(fs.proc.Path("net/arp")) | |||
data, err := os.ReadFile(fs.proc.Path("net/arp")) | |||
if err != nil { | |||
return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err) | |||
} | |||
@@ -72,14 +91,26 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) { | |||
} | |||
func parseARPEntry(columns []string) (ARPEntry, error) { | |||
entry := ARPEntry{Device: columns[5]} | |||
ip := net.ParseIP(columns[0]) | |||
mac := net.HardwareAddr(columns[3]) | |||
entry.IPAddr = ip | |||
if mac, err := net.ParseMAC(columns[3]); err == nil { | |||
entry.HWAddr = mac | |||
} else { | |||
return ARPEntry{}, err | |||
} | |||
entry := ARPEntry{ | |||
IPAddr: ip, | |||
HWAddr: mac, | |||
Device: columns[5], | |||
if flags, err := strconv.ParseUint(columns[2], 0, 8); err == nil { | |||
entry.Flags = byte(flags) | |||
} else { | |||
return ARPEntry{}, err | |||
} | |||
return entry, nil | |||
} | |||
// IsComplete returns true if ARP entry is marked with complete flag. | |||
func (entry *ARPEntry) IsComplete() bool { | |||
return entry.Flags&ATFComplete != 0 | |||
} |
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux | |||
// +build linux | |||
package procfs | |||
@@ -27,7 +28,7 @@ import ( | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// CPUInfo contains general information about a system CPU found in /proc/cpuinfo | |||
// CPUInfo contains general information about a system CPU found in /proc/cpuinfo. | |||
type CPUInfo struct { | |||
Processor uint | |||
VendorID string | |||
@@ -469,7 +470,7 @@ func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode | |||
} | |||
// firstNonEmptyLine advances the scanner to the first non-empty line | |||
// and returns the contents of that line | |||
// and returns the contents of that line. | |||
func firstNonEmptyLine(scanner *bufio.Scanner) string { | |||
for scanner.Scan() { | |||
line := scanner.Text() | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux && (arm || arm64) | |||
// +build linux | |||
// +build arm arm64 | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux && (mips || mipsle || mips64 || mips64le) | |||
// +build linux | |||
// +build mips mipsle mips64 mips64le | |||
@@ -11,8 +11,8 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
// +build linux | |||
// +build !386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x | |||
//go:build linux && !386 && !amd64 && !arm && !arm64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x | |||
// +build linux,!386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x | |||
package procfs | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux && (ppc64 || ppc64le) | |||
// +build linux | |||
// +build ppc64 ppc64le | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux && (riscv || riscv64) | |||
// +build linux | |||
// +build riscv riscv64 | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux | |||
// +build linux | |||
package procfs | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build linux && (386 || amd64) | |||
// +build linux | |||
// +build 386 amd64 | |||
@@ -26,7 +26,7 @@ const ( | |||
// DefaultSysMountPoint is the common mount point of the sys filesystem. | |||
DefaultSysMountPoint = "/sys" | |||
// DefaultConfigfsMountPoint is the common mount point of the configfs | |||
// DefaultConfigfsMountPoint is the common mount point of the configfs. | |||
DefaultConfigfsMountPoint = "/sys/kernel/config" | |||
) | |||
@@ -14,7 +14,7 @@ | |||
package util | |||
import ( | |||
"io/ioutil" | |||
"os" | |||
"strconv" | |||
"strings" | |||
) | |||
@@ -66,7 +66,7 @@ func ParsePInt64s(ss []string) ([]*int64, error) { | |||
// ReadUintFromFile reads a file and attempts to parse a uint64 from it. | |||
func ReadUintFromFile(path string) (uint64, error) { | |||
data, err := ioutil.ReadFile(path) | |||
data, err := os.ReadFile(path) | |||
if err != nil { | |||
return 0, err | |||
} | |||
@@ -75,7 +75,7 @@ func ReadUintFromFile(path string) (uint64, error) { | |||
// ReadIntFromFile reads a file and attempts to parse a int64 from it. | |||
func ReadIntFromFile(path string) (int64, error) { | |||
data, err := ioutil.ReadFile(path) | |||
data, err := os.ReadFile(path) | |||
if err != nil { | |||
return 0, err | |||
} | |||
@@ -15,17 +15,16 @@ package util | |||
import ( | |||
"io" | |||
"io/ioutil" | |||
"os" | |||
) | |||
// ReadFileNoStat uses ioutil.ReadAll to read contents of entire file. | |||
// This is similar to ioutil.ReadFile but without the call to os.Stat, because | |||
// ReadFileNoStat uses io.ReadAll to read contents of entire file. | |||
// This is similar to os.ReadFile but without the call to os.Stat, because | |||
// many files in /proc and /sys report incorrect file sizes (either 0 or 4096). | |||
// Reads a max file size of 512kB. For files larger than this, a scanner | |||
// Reads a max file size of 1024kB. For files larger than this, a scanner | |||
// should be used. | |||
func ReadFileNoStat(filename string) ([]byte, error) { | |||
const maxBufferSize = 1024 * 512 | |||
const maxBufferSize = 1024 * 1024 | |||
f, err := os.Open(filename) | |||
if err != nil { | |||
@@ -34,5 +33,5 @@ func ReadFileNoStat(filename string) ([]byte, error) { | |||
defer f.Close() | |||
reader := io.LimitReader(f, maxBufferSize) | |||
return ioutil.ReadAll(reader) | |||
return io.ReadAll(reader) | |||
} |
@@ -11,7 +11,9 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
// +build linux,!appengine | |||
//go:build (linux || darwin) && !appengine | |||
// +build linux darwin | |||
// +build !appengine | |||
package util | |||
@@ -21,7 +23,7 @@ import ( | |||
"syscall" | |||
) | |||
// SysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly. | |||
// SysReadFile is a simplified os.ReadFile that invokes syscall.Read directly. | |||
// https://github.com/prometheus/node_exporter/pull/728/files | |||
// | |||
// Note that this function will not read files larger than 128 bytes. | |||
@@ -33,7 +35,7 @@ func SysReadFile(file string) (string, error) { | |||
defer f.Close() | |||
// On some machines, hwmon drivers are broken and return EAGAIN. This causes | |||
// Go's ioutil.ReadFile implementation to poll forever. | |||
// Go's os.ReadFile implementation to poll forever. | |||
// | |||
// Since we either want to read data or bail immediately, do the simplest | |||
// possible read using syscall directly. | |||
@@ -11,7 +11,8 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
// +build linux,appengine !linux | |||
//go:build (linux && appengine) || (!linux && !darwin) | |||
// +build linux,appengine !linux,!darwin | |||
package util | |||
@@ -20,7 +20,6 @@ import ( | |||
"errors" | |||
"fmt" | |||
"io" | |||
"io/ioutil" | |||
"net" | |||
"os" | |||
"strconv" | |||
@@ -84,7 +83,7 @@ func parseIPVSStats(r io.Reader) (IPVSStats, error) { | |||
stats IPVSStats | |||
) | |||
statContent, err := ioutil.ReadAll(r) | |||
statContent, err := io.ReadAll(r) | |||
if err != nil { | |||
return IPVSStats{}, err | |||
} | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build !windows | |||
// +build !windows | |||
package procfs | |||
@@ -21,7 +21,7 @@ import ( | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// LoadAvg represents an entry in /proc/loadavg | |||
// LoadAvg represents an entry in /proc/loadavg. | |||
type LoadAvg struct { | |||
Load1 float64 | |||
Load5 float64 | |||
@@ -15,7 +15,7 @@ package procfs | |||
import ( | |||
"fmt" | |||
"io/ioutil" | |||
"os" | |||
"regexp" | |||
"strconv" | |||
"strings" | |||
@@ -64,7 +64,7 @@ type MDStat struct { | |||
// structs containing the relevant info. More information available here: | |||
// https://raid.wiki.kernel.org/index.php/Mdstat | |||
func (fs FS) MDStat() ([]MDStat, error) { | |||
data, err := ioutil.ReadFile(fs.proc.Path("mdstat")) | |||
data, err := os.ReadFile(fs.proc.Path("mdstat")) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -166,8 +166,12 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { | |||
} | |||
func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) { | |||
statusFields := strings.Fields(statusLine) | |||
if len(statusFields) < 1 { | |||
return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q", statusLine) | |||
} | |||
sizeStr := strings.Fields(statusLine)[0] | |||
sizeStr := statusFields[0] | |||
size, err = strconv.ParseInt(sizeStr, 10, 64) | |||
if err != nil { | |||
return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err) | |||
@@ -25,7 +25,7 @@ import ( | |||
) | |||
// A ConntrackStatEntry represents one line from net/stat/nf_conntrack | |||
// and contains netfilter conntrack statistics at one CPU core | |||
// and contains netfilter conntrack statistics at one CPU core. | |||
type ConntrackStatEntry struct { | |||
Entries uint64 | |||
Found uint64 | |||
@@ -38,12 +38,12 @@ type ConntrackStatEntry struct { | |||
SearchRestart uint64 | |||
} | |||
// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores | |||
// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores. | |||
func (fs FS) ConntrackStat() ([]ConntrackStatEntry, error) { | |||
return readConntrackStat(fs.proc.Path("net", "stat", "nf_conntrack")) | |||
} | |||
// Parses a slice of ConntrackStatEntries from the given filepath | |||
// Parses a slice of ConntrackStatEntries from the given filepath. | |||
func readConntrackStat(path string) ([]ConntrackStatEntry, error) { | |||
// This file is small and can be read with one syscall. | |||
b, err := util.ReadFileNoStat(path) | |||
@@ -61,7 +61,7 @@ func readConntrackStat(path string) ([]ConntrackStatEntry, error) { | |||
return stat, nil | |||
} | |||
// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries | |||
// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries. | |||
func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { | |||
var entries []ConntrackStatEntry | |||
@@ -79,7 +79,7 @@ func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { | |||
return entries, nil | |||
} | |||
// Parses a ConntrackStatEntry from given array of fields | |||
// Parses a ConntrackStatEntry from given array of fields. | |||
func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { | |||
if len(fields) != 17 { | |||
return nil, fmt.Errorf("invalid conntrackstat entry, missing fields") | |||
@@ -143,7 +143,7 @@ func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { | |||
return entry, nil | |||
} | |||
// Parses a uint64 from given hex in string | |||
// Parses a uint64 from given hex in string. | |||
func parseConntrackStatField(field string) (uint64, error) { | |||
val, err := strconv.ParseUint(field, 16, 64) | |||
if err != nil { | |||
@@ -87,17 +87,17 @@ func newNetDev(file string) (NetDev, error) { | |||
// parseLine parses a single line from the /proc/net/dev file. Header lines | |||
// must be filtered prior to calling this method. | |||
func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) { | |||
parts := strings.SplitN(rawLine, ":", 2) | |||
if len(parts) != 2 { | |||
idx := strings.LastIndex(rawLine, ":") | |||
if idx == -1 { | |||
return nil, errors.New("invalid net/dev line, missing colon") | |||
} | |||
fields := strings.Fields(strings.TrimSpace(parts[1])) | |||
fields := strings.Fields(strings.TrimSpace(rawLine[idx+1:])) | |||
var err error | |||
line := &NetDevLine{} | |||
// Interface Name | |||
line.Name = strings.TrimSpace(parts[0]) | |||
line.Name = strings.TrimSpace(rawLine[:idx]) | |||
if line.Name == "" { | |||
return nil, errors.New("invalid net/dev line, empty interface name") | |||
} | |||
@@ -34,7 +34,7 @@ const ( | |||
readLimit = 4294967296 // Byte -> 4 GiB | |||
) | |||
// this contains generic data structures for both udp and tcp sockets | |||
// 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 | |||
@@ -23,7 +23,7 @@ import ( | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// NetProtocolStats stores the contents from /proc/net/protocols | |||
// NetProtocolStats stores the contents from /proc/net/protocols. | |||
type NetProtocolStats map[string]NetProtocolStatLine | |||
// NetProtocolStatLine contains a single line parsed from /proc/net/protocols. We | |||
@@ -41,7 +41,7 @@ type NetProtocolStatLine struct { | |||
Capabilities NetProtocolCapabilities | |||
} | |||
// NetProtocolCapabilities contains a list of capabilities for each protocol | |||
// NetProtocolCapabilities contains a list of capabilities for each protocol. | |||
type NetProtocolCapabilities struct { | |||
Close bool // 8 | |||
Connect bool // 9 | |||
@@ -30,13 +30,13 @@ import ( | |||
// * Linux 4.17 https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162 | |||
// and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810. | |||
// SoftnetStat contains a single row of data from /proc/net/softnet_stat | |||
// SoftnetStat contains a single row of data from /proc/net/softnet_stat. | |||
type SoftnetStat struct { | |||
// Number of processed packets | |||
// Number of processed packets. | |||
Processed uint32 | |||
// Number of dropped packets | |||
// Number of dropped packets. | |||
Dropped uint32 | |||
// Number of times processing packets ran out of quota | |||
// Number of times processing packets ran out of quota. | |||
TimeSqueezed uint32 | |||
} | |||
@@ -79,10 +79,13 @@ type XfrmStat struct { | |||
// Policy is dead | |||
XfrmOutPolDead int | |||
// Policy Error | |||
XfrmOutPolError int | |||
XfrmFwdHdrError int | |||
XfrmOutPolError int | |||
// Forward routing of a packet is not allowed | |||
XfrmFwdHdrError int | |||
// State is invalid, perhaps expired | |||
XfrmOutStateInvalid int | |||
XfrmAcquireError int | |||
// State hasn’t been fully acquired before use | |||
XfrmAcquireError int | |||
} | |||
// NewXfrmStat reads the xfrm_stat statistics. |
@@ -21,13 +21,13 @@ import ( | |||
"strings" | |||
) | |||
// NetStat contains statistics for all the counters from one file | |||
// NetStat contains statistics for all the counters from one file. | |||
type NetStat struct { | |||
Filename string | |||
Stats map[string][]uint64 | |||
Filename string | |||
} | |||
// NetStat retrieves stats from /proc/net/stat/ | |||
// NetStat retrieves stats from `/proc/net/stat/`. | |||
func (fs FS) NetStat() ([]NetStat, error) { | |||
statFiles, err := filepath.Glob(fs.proc.Path("net/stat/*")) | |||
if err != nil { | |||
@@ -55,7 +55,7 @@ func (fs FS) NetStat() ([]NetStat, error) { | |||
// Other strings represent per-CPU counters | |||
for scanner.Scan() { | |||
for num, counter := range strings.Fields(scanner.Text()) { | |||
value, err := strconv.ParseUint(counter, 16, 32) | |||
value, err := strconv.ParseUint(counter, 16, 64) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -16,7 +16,7 @@ package procfs | |||
import ( | |||
"bytes" | |||
"fmt" | |||
"io/ioutil" | |||
"io" | |||
"os" | |||
"strconv" | |||
"strings" | |||
@@ -82,7 +82,7 @@ func (fs FS) Self() (Proc, error) { | |||
// NewProc returns a process for the given pid. | |||
// | |||
// Deprecated: use fs.Proc() instead | |||
// Deprecated: Use fs.Proc() instead. | |||
func (fs FS) NewProc(pid int) (Proc, error) { | |||
return fs.Proc(pid) | |||
} | |||
@@ -142,7 +142,7 @@ func (p Proc) Wchan() (string, error) { | |||
} | |||
defer f.Close() | |||
data, err := ioutil.ReadAll(f) | |||
data, err := io.ReadAll(f) | |||
if err != nil { | |||
return "", err | |||
} | |||
@@ -185,7 +185,7 @@ func (p Proc) Cwd() (string, error) { | |||
return wd, err | |||
} | |||
// RootDir returns the absolute path to the process's root directory (as set by chroot) | |||
// RootDir returns the absolute path to the process's root directory (as set by chroot). | |||
func (p Proc) RootDir() (string, error) { | |||
rdir, err := os.Readlink(p.path("root")) | |||
if os.IsNotExist(err) { | |||
@@ -311,7 +311,7 @@ func (p Proc) FileDescriptorsInfo() (ProcFDInfos, error) { | |||
// Schedstat returns task scheduling information for the process. | |||
func (p Proc) Schedstat() (ProcSchedstat, error) { | |||
contents, err := ioutil.ReadFile(p.path("schedstat")) | |||
contents, err := os.ReadFile(p.path("schedstat")) | |||
if err != nil { | |||
return ProcSchedstat{}, err | |||
} | |||
@@ -45,7 +45,7 @@ type Cgroup struct { | |||
} | |||
// parseCgroupString parses each line of the /proc/[pid]/cgroup file | |||
// Line format is hierarchyID:[controller1,controller2]:path | |||
// Line format is hierarchyID:[controller1,controller2]:path. | |||
func parseCgroupString(cgroupStr string) (*Cgroup, error) { | |||
var err error | |||
@@ -69,7 +69,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) { | |||
return cgroup, nil | |||
} | |||
// parseCgroups reads each line of the /proc/[pid]/cgroup file | |||
// parseCgroups reads each line of the /proc/[pid]/cgroup file. | |||
func parseCgroups(data []byte) ([]Cgroup, error) { | |||
var cgroups []Cgroup | |||
scanner := bufio.NewScanner(bytes.NewReader(data)) | |||
@@ -88,7 +88,7 @@ func parseCgroups(data []byte) ([]Cgroup, error) { | |||
// Cgroups reads from /proc/<pid>/cgroups and returns a []*Cgroup struct locating this PID in each process | |||
// control hierarchy running on this system. On every system (v1 and v2), all hierarchies contain all processes, | |||
// so the len of the returned struct is equal to the number of active hierarchies on this system | |||
// so the len of the returned struct is equal to the number of active hierarchies on this system. | |||
func (p Proc) Cgroups() ([]Cgroup, error) { | |||
data, err := util.ReadFileNoStat(p.path("cgroup")) | |||
if err != nil { | |||
@@ -0,0 +1,98 @@ | |||
// 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 procfs | |||
import ( | |||
"bufio" | |||
"bytes" | |||
"fmt" | |||
"strconv" | |||
"strings" | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// CgroupSummary models one line from /proc/cgroups. | |||
// This file contains information about the controllers that are compiled into the kernel. | |||
// | |||
// Also see http://man7.org/linux/man-pages/man7/cgroups.7.html | |||
type CgroupSummary struct { | |||
// The name of the controller. controller is also known as subsystem. | |||
SubsysName string | |||
// The unique ID of the cgroup hierarchy on which this controller is mounted. | |||
Hierarchy int | |||
// The number of control groups in this hierarchy using this controller. | |||
Cgroups int | |||
// This field contains the value 1 if this controller is enabled, or 0 if it has been disabled | |||
Enabled int | |||
} | |||
// parseCgroupSummary parses each line of the /proc/cgroup file | |||
// Line format is `subsys_name hierarchy num_cgroups enabled`. | |||
func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) { | |||
var err error | |||
fields := strings.Fields(CgroupSummaryStr) | |||
// require at least 4 fields | |||
if len(fields) < 4 { | |||
return nil, fmt.Errorf("at least 4 fields required, found %d fields in cgroup info string: %s", len(fields), CgroupSummaryStr) | |||
} | |||
CgroupSummary := &CgroupSummary{ | |||
SubsysName: fields[0], | |||
} | |||
CgroupSummary.Hierarchy, err = strconv.Atoi(fields[1]) | |||
if err != nil { | |||
return nil, fmt.Errorf("failed to parse hierarchy ID") | |||
} | |||
CgroupSummary.Cgroups, err = strconv.Atoi(fields[2]) | |||
if err != nil { | |||
return nil, fmt.Errorf("failed to parse Cgroup Num") | |||
} | |||
CgroupSummary.Enabled, err = strconv.Atoi(fields[3]) | |||
if err != nil { | |||
return nil, fmt.Errorf("failed to parse Enabled") | |||
} | |||
return CgroupSummary, nil | |||
} | |||
// parseCgroupSummary reads each line of the /proc/cgroup file. | |||
func parseCgroupSummary(data []byte) ([]CgroupSummary, error) { | |||
var CgroupSummarys []CgroupSummary | |||
scanner := bufio.NewScanner(bytes.NewReader(data)) | |||
for scanner.Scan() { | |||
CgroupSummaryString := scanner.Text() | |||
// ignore comment lines | |||
if strings.HasPrefix(CgroupSummaryString, "#") { | |||
continue | |||
} | |||
CgroupSummary, err := parseCgroupSummaryString(CgroupSummaryString) | |||
if err != nil { | |||
return nil, err | |||
} | |||
CgroupSummarys = append(CgroupSummarys, *CgroupSummary) | |||
} | |||
err := scanner.Err() | |||
return CgroupSummarys, err | |||
} | |||
// CgroupSummarys returns information about current /proc/cgroups. | |||
func (fs FS) CgroupSummarys() ([]CgroupSummary, error) { | |||
data, err := util.ReadFileNoStat(fs.proc.Path("cgroups")) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return parseCgroupSummary(data) | |||
} |
@@ -19,7 +19,7 @@ import ( | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// Environ reads process environments from /proc/<pid>/environ | |||
// Environ reads process environments from `/proc/<pid>/environ`. | |||
func (p Proc) Environ() ([]string, error) { | |||
environments := make([]string, 0) | |||
@@ -22,7 +22,6 @@ import ( | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// Regexp variables | |||
var ( | |||
rPos = regexp.MustCompile(`^pos:\s+(\d+)$`) | |||
rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`) | |||
@@ -122,7 +121,7 @@ func (p ProcFDInfos) Len() int { return len(p) } | |||
func (p ProcFDInfos) Swap(i, j int) { p[i], p[j] = p[j], p[i] } | |||
func (p ProcFDInfos) Less(i, j int) bool { return p[i].FD < p[j].FD } | |||
// InotifyWatchLen returns the total number of inotify watches | |||
// InotifyWatchLen returns the total number of inotify watches. | |||
func (p ProcFDInfos) InotifyWatchLen() (int, error) { | |||
length := 0 | |||
for _, f := range p { | |||
@@ -79,7 +79,7 @@ var ( | |||
// NewLimits returns the current soft limits of the process. | |||
// | |||
// Deprecated: use p.Limits() instead | |||
// Deprecated: Use p.Limits() instead. | |||
func (p Proc) NewLimits() (ProcLimits, error) { | |||
return p.Limits() | |||
} | |||
@@ -11,7 +11,9 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !js | |||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris | |||
// +build !js | |||
package procfs | |||
@@ -25,7 +27,7 @@ import ( | |||
"golang.org/x/sys/unix" | |||
) | |||
// ProcMapPermissions contains permission settings read from /proc/[pid]/maps | |||
// ProcMapPermissions contains permission settings read from `/proc/[pid]/maps`. | |||
type ProcMapPermissions struct { | |||
// mapping has the [R]ead flag set | |||
Read bool | |||
@@ -39,8 +41,8 @@ type ProcMapPermissions struct { | |||
Private bool | |||
} | |||
// ProcMap contains the process memory-mappings of the process, | |||
// read from /proc/[pid]/maps | |||
// ProcMap contains the process memory-mappings of the process | |||
// read from `/proc/[pid]/maps`. | |||
type ProcMap struct { | |||
// The start address of current mapping. | |||
StartAddr uintptr | |||
@@ -79,7 +81,7 @@ func parseDevice(s string) (uint64, error) { | |||
return unix.Mkdev(uint32(major), uint32(minor)), nil | |||
} | |||
// parseAddress just converts a hex-string to a uintptr | |||
// parseAddress converts a hex-string to a uintptr. | |||
func parseAddress(s string) (uintptr, error) { | |||
a, err := strconv.ParseUint(s, 16, 0) | |||
if err != nil { | |||
@@ -89,7 +91,7 @@ func parseAddress(s string) (uintptr, error) { | |||
return uintptr(a), nil | |||
} | |||
// parseAddresses parses the start-end address | |||
// parseAddresses parses the start-end address. | |||
func parseAddresses(s string) (uintptr, uintptr, error) { | |||
toks := strings.Split(s, "-") | |||
if len(toks) < 2 { | |||
@@ -0,0 +1,440 @@ | |||
// Copyright 2022 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" | |||
"io" | |||
"strconv" | |||
"strings" | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// ProcNetstat models the content of /proc/<pid>/net/netstat. | |||
type ProcNetstat struct { | |||
// The process ID. | |||
PID int | |||
TcpExt | |||
IpExt | |||
} | |||
type TcpExt struct { // nolint:revive | |||
SyncookiesSent float64 | |||
SyncookiesRecv float64 | |||
SyncookiesFailed float64 | |||
EmbryonicRsts float64 | |||
PruneCalled float64 | |||
RcvPruned float64 | |||
OfoPruned float64 | |||
OutOfWindowIcmps float64 | |||
LockDroppedIcmps float64 | |||
ArpFilter float64 | |||
TW float64 | |||
TWRecycled float64 | |||
TWKilled float64 | |||
PAWSActive float64 | |||
PAWSEstab float64 | |||
DelayedACKs float64 | |||
DelayedACKLocked float64 | |||
DelayedACKLost float64 | |||
ListenOverflows float64 | |||
ListenDrops float64 | |||
TCPHPHits float64 | |||
TCPPureAcks float64 | |||
TCPHPAcks float64 | |||
TCPRenoRecovery float64 | |||
TCPSackRecovery float64 | |||
TCPSACKReneging float64 | |||
TCPSACKReorder float64 | |||
TCPRenoReorder float64 | |||
TCPTSReorder float64 | |||
TCPFullUndo float64 | |||
TCPPartialUndo float64 | |||
TCPDSACKUndo float64 | |||
TCPLossUndo float64 | |||
TCPLostRetransmit float64 | |||
TCPRenoFailures float64 | |||
TCPSackFailures float64 | |||
TCPLossFailures float64 | |||
TCPFastRetrans float64 | |||
TCPSlowStartRetrans float64 | |||
TCPTimeouts float64 | |||
TCPLossProbes float64 | |||
TCPLossProbeRecovery float64 | |||
TCPRenoRecoveryFail float64 | |||
TCPSackRecoveryFail float64 | |||
TCPRcvCollapsed float64 | |||
TCPDSACKOldSent float64 | |||
TCPDSACKOfoSent float64 | |||
TCPDSACKRecv float64 | |||
TCPDSACKOfoRecv float64 | |||
TCPAbortOnData float64 | |||
TCPAbortOnClose float64 | |||
TCPAbortOnMemory float64 | |||
TCPAbortOnTimeout float64 | |||
TCPAbortOnLinger float64 | |||
TCPAbortFailed float64 | |||
TCPMemoryPressures float64 | |||
TCPMemoryPressuresChrono float64 | |||
TCPSACKDiscard float64 | |||
TCPDSACKIgnoredOld float64 | |||
TCPDSACKIgnoredNoUndo float64 | |||
TCPSpuriousRTOs float64 | |||
TCPMD5NotFound float64 | |||
TCPMD5Unexpected float64 | |||
TCPMD5Failure float64 | |||
TCPSackShifted float64 | |||
TCPSackMerged float64 | |||
TCPSackShiftFallback float64 | |||
TCPBacklogDrop float64 | |||
PFMemallocDrop float64 | |||
TCPMinTTLDrop float64 | |||
TCPDeferAcceptDrop float64 | |||
IPReversePathFilter float64 | |||
TCPTimeWaitOverflow float64 | |||
TCPReqQFullDoCookies float64 | |||
TCPReqQFullDrop float64 | |||
TCPRetransFail float64 | |||
TCPRcvCoalesce float64 | |||
TCPOFOQueue float64 | |||
TCPOFODrop float64 | |||
TCPOFOMerge float64 | |||
TCPChallengeACK float64 | |||
TCPSYNChallenge float64 | |||
TCPFastOpenActive float64 | |||
TCPFastOpenActiveFail float64 | |||
TCPFastOpenPassive float64 | |||
TCPFastOpenPassiveFail float64 | |||
TCPFastOpenListenOverflow float64 | |||
TCPFastOpenCookieReqd float64 | |||
TCPFastOpenBlackhole float64 | |||
TCPSpuriousRtxHostQueues float64 | |||
BusyPollRxPackets float64 | |||
TCPAutoCorking float64 | |||
TCPFromZeroWindowAdv float64 | |||
TCPToZeroWindowAdv float64 | |||
TCPWantZeroWindowAdv float64 | |||
TCPSynRetrans float64 | |||
TCPOrigDataSent float64 | |||
TCPHystartTrainDetect float64 | |||
TCPHystartTrainCwnd float64 | |||
TCPHystartDelayDetect float64 | |||
TCPHystartDelayCwnd float64 | |||
TCPACKSkippedSynRecv float64 | |||
TCPACKSkippedPAWS float64 | |||
TCPACKSkippedSeq float64 | |||
TCPACKSkippedFinWait2 float64 | |||
TCPACKSkippedTimeWait float64 | |||
TCPACKSkippedChallenge float64 | |||
TCPWinProbe float64 | |||
TCPKeepAlive float64 | |||
TCPMTUPFail float64 | |||
TCPMTUPSuccess float64 | |||
TCPWqueueTooBig float64 | |||
} | |||
type IpExt struct { // nolint:revive | |||
InNoRoutes float64 | |||
InTruncatedPkts float64 | |||
InMcastPkts float64 | |||
OutMcastPkts float64 | |||
InBcastPkts float64 | |||
OutBcastPkts float64 | |||
InOctets float64 | |||
OutOctets float64 | |||
InMcastOctets float64 | |||
OutMcastOctets float64 | |||
InBcastOctets float64 | |||
OutBcastOctets float64 | |||
InCsumErrors float64 | |||
InNoECTPkts float64 | |||
InECT1Pkts float64 | |||
InECT0Pkts float64 | |||
InCEPkts float64 | |||
ReasmOverlaps float64 | |||
} | |||
func (p Proc) Netstat() (ProcNetstat, error) { | |||
filename := p.path("net/netstat") | |||
data, err := util.ReadFileNoStat(filename) | |||
if err != nil { | |||
return ProcNetstat{PID: p.PID}, err | |||
} | |||
procNetstat, err := parseNetstat(bytes.NewReader(data), filename) | |||
procNetstat.PID = p.PID | |||
return procNetstat, err | |||
} | |||
// parseNetstat parses the metrics from proc/<pid>/net/netstat file | |||
// and returns a ProcNetstat structure. | |||
func parseNetstat(r io.Reader, fileName string) (ProcNetstat, error) { | |||
var ( | |||
scanner = bufio.NewScanner(r) | |||
procNetstat = ProcNetstat{} | |||
) | |||
for scanner.Scan() { | |||
nameParts := strings.Split(scanner.Text(), " ") | |||
scanner.Scan() | |||
valueParts := strings.Split(scanner.Text(), " ") | |||
// Remove trailing :. | |||
protocol := strings.TrimSuffix(nameParts[0], ":") | |||
if len(nameParts) != len(valueParts) { | |||
return procNetstat, fmt.Errorf("mismatch field count mismatch in %s: %s", | |||
fileName, protocol) | |||
} | |||
for i := 1; i < len(nameParts); i++ { | |||
value, err := strconv.ParseFloat(valueParts[i], 64) | |||
if err != nil { | |||
return procNetstat, err | |||
} | |||
key := nameParts[i] | |||
switch protocol { | |||
case "TcpExt": | |||
switch key { | |||
case "SyncookiesSent": | |||
procNetstat.TcpExt.SyncookiesSent = value | |||
case "SyncookiesRecv": | |||
procNetstat.TcpExt.SyncookiesRecv = value | |||
case "SyncookiesFailed": | |||
procNetstat.TcpExt.SyncookiesFailed = value | |||
case "EmbryonicRsts": | |||
procNetstat.TcpExt.EmbryonicRsts = value | |||
case "PruneCalled": | |||
procNetstat.TcpExt.PruneCalled = value | |||
case "RcvPruned": | |||
procNetstat.TcpExt.RcvPruned = value | |||
case "OfoPruned": | |||
procNetstat.TcpExt.OfoPruned = value | |||
case "OutOfWindowIcmps": | |||
procNetstat.TcpExt.OutOfWindowIcmps = value | |||
case "LockDroppedIcmps": | |||
procNetstat.TcpExt.LockDroppedIcmps = value | |||
case "ArpFilter": | |||
procNetstat.TcpExt.ArpFilter = value | |||
case "TW": | |||
procNetstat.TcpExt.TW = value | |||
case "TWRecycled": | |||
procNetstat.TcpExt.TWRecycled = value | |||
case "TWKilled": | |||
procNetstat.TcpExt.TWKilled = value | |||
case "PAWSActive": | |||
procNetstat.TcpExt.PAWSActive = value | |||
case "PAWSEstab": | |||
procNetstat.TcpExt.PAWSEstab = value | |||
case "DelayedACKs": | |||
procNetstat.TcpExt.DelayedACKs = value | |||
case "DelayedACKLocked": | |||
procNetstat.TcpExt.DelayedACKLocked = value | |||
case "DelayedACKLost": | |||
procNetstat.TcpExt.DelayedACKLost = value | |||
case "ListenOverflows": | |||
procNetstat.TcpExt.ListenOverflows = value | |||
case "ListenDrops": | |||
procNetstat.TcpExt.ListenDrops = value | |||
case "TCPHPHits": | |||
procNetstat.TcpExt.TCPHPHits = value | |||
case "TCPPureAcks": | |||
procNetstat.TcpExt.TCPPureAcks = value | |||
case "TCPHPAcks": | |||
procNetstat.TcpExt.TCPHPAcks = value | |||
case "TCPRenoRecovery": | |||
procNetstat.TcpExt.TCPRenoRecovery = value | |||
case "TCPSackRecovery": | |||
procNetstat.TcpExt.TCPSackRecovery = value | |||
case "TCPSACKReneging": | |||
procNetstat.TcpExt.TCPSACKReneging = value | |||
case "TCPSACKReorder": | |||
procNetstat.TcpExt.TCPSACKReorder = value | |||
case "TCPRenoReorder": | |||
procNetstat.TcpExt.TCPRenoReorder = value | |||
case "TCPTSReorder": | |||
procNetstat.TcpExt.TCPTSReorder = value | |||
case "TCPFullUndo": | |||
procNetstat.TcpExt.TCPFullUndo = value | |||
case "TCPPartialUndo": | |||
procNetstat.TcpExt.TCPPartialUndo = value | |||
case "TCPDSACKUndo": | |||
procNetstat.TcpExt.TCPDSACKUndo = value | |||
case "TCPLossUndo": | |||
procNetstat.TcpExt.TCPLossUndo = value | |||
case "TCPLostRetransmit": | |||
procNetstat.TcpExt.TCPLostRetransmit = value | |||
case "TCPRenoFailures": | |||
procNetstat.TcpExt.TCPRenoFailures = value | |||
case "TCPSackFailures": | |||
procNetstat.TcpExt.TCPSackFailures = value | |||
case "TCPLossFailures": | |||
procNetstat.TcpExt.TCPLossFailures = value | |||
case "TCPFastRetrans": | |||
procNetstat.TcpExt.TCPFastRetrans = value | |||
case "TCPSlowStartRetrans": | |||
procNetstat.TcpExt.TCPSlowStartRetrans = value | |||
case "TCPTimeouts": | |||
procNetstat.TcpExt.TCPTimeouts = value | |||
case "TCPLossProbes": | |||
procNetstat.TcpExt.TCPLossProbes = value | |||
case "TCPLossProbeRecovery": | |||
procNetstat.TcpExt.TCPLossProbeRecovery = value | |||
case "TCPRenoRecoveryFail": | |||
procNetstat.TcpExt.TCPRenoRecoveryFail = value | |||
case "TCPSackRecoveryFail": | |||
procNetstat.TcpExt.TCPSackRecoveryFail = value | |||
case "TCPRcvCollapsed": | |||
procNetstat.TcpExt.TCPRcvCollapsed = value | |||
case "TCPDSACKOldSent": | |||
procNetstat.TcpExt.TCPDSACKOldSent = value | |||
case "TCPDSACKOfoSent": | |||
procNetstat.TcpExt.TCPDSACKOfoSent = value | |||
case "TCPDSACKRecv": | |||
procNetstat.TcpExt.TCPDSACKRecv = value | |||
case "TCPDSACKOfoRecv": | |||
procNetstat.TcpExt.TCPDSACKOfoRecv = value | |||
case "TCPAbortOnData": | |||
procNetstat.TcpExt.TCPAbortOnData = value | |||
case "TCPAbortOnClose": | |||
procNetstat.TcpExt.TCPAbortOnClose = value | |||
case "TCPDeferAcceptDrop": | |||
procNetstat.TcpExt.TCPDeferAcceptDrop = value | |||
case "IPReversePathFilter": | |||
procNetstat.TcpExt.IPReversePathFilter = value | |||
case "TCPTimeWaitOverflow": | |||
procNetstat.TcpExt.TCPTimeWaitOverflow = value | |||
case "TCPReqQFullDoCookies": | |||
procNetstat.TcpExt.TCPReqQFullDoCookies = value | |||
case "TCPReqQFullDrop": | |||
procNetstat.TcpExt.TCPReqQFullDrop = value | |||
case "TCPRetransFail": | |||
procNetstat.TcpExt.TCPRetransFail = value | |||
case "TCPRcvCoalesce": | |||
procNetstat.TcpExt.TCPRcvCoalesce = value | |||
case "TCPOFOQueue": | |||
procNetstat.TcpExt.TCPOFOQueue = value | |||
case "TCPOFODrop": | |||
procNetstat.TcpExt.TCPOFODrop = value | |||
case "TCPOFOMerge": | |||
procNetstat.TcpExt.TCPOFOMerge = value | |||
case "TCPChallengeACK": | |||
procNetstat.TcpExt.TCPChallengeACK = value | |||
case "TCPSYNChallenge": | |||
procNetstat.TcpExt.TCPSYNChallenge = value | |||
case "TCPFastOpenActive": | |||
procNetstat.TcpExt.TCPFastOpenActive = value | |||
case "TCPFastOpenActiveFail": | |||
procNetstat.TcpExt.TCPFastOpenActiveFail = value | |||
case "TCPFastOpenPassive": | |||
procNetstat.TcpExt.TCPFastOpenPassive = value | |||
case "TCPFastOpenPassiveFail": | |||
procNetstat.TcpExt.TCPFastOpenPassiveFail = value | |||
case "TCPFastOpenListenOverflow": | |||
procNetstat.TcpExt.TCPFastOpenListenOverflow = value | |||
case "TCPFastOpenCookieReqd": | |||
procNetstat.TcpExt.TCPFastOpenCookieReqd = value | |||
case "TCPFastOpenBlackhole": | |||
procNetstat.TcpExt.TCPFastOpenBlackhole = value | |||
case "TCPSpuriousRtxHostQueues": | |||
procNetstat.TcpExt.TCPSpuriousRtxHostQueues = value | |||
case "BusyPollRxPackets": | |||
procNetstat.TcpExt.BusyPollRxPackets = value | |||
case "TCPAutoCorking": | |||
procNetstat.TcpExt.TCPAutoCorking = value | |||
case "TCPFromZeroWindowAdv": | |||
procNetstat.TcpExt.TCPFromZeroWindowAdv = value | |||
case "TCPToZeroWindowAdv": | |||
procNetstat.TcpExt.TCPToZeroWindowAdv = value | |||
case "TCPWantZeroWindowAdv": | |||
procNetstat.TcpExt.TCPWantZeroWindowAdv = value | |||
case "TCPSynRetrans": | |||
procNetstat.TcpExt.TCPSynRetrans = value | |||
case "TCPOrigDataSent": | |||
procNetstat.TcpExt.TCPOrigDataSent = value | |||
case "TCPHystartTrainDetect": | |||
procNetstat.TcpExt.TCPHystartTrainDetect = value | |||
case "TCPHystartTrainCwnd": | |||
procNetstat.TcpExt.TCPHystartTrainCwnd = value | |||
case "TCPHystartDelayDetect": | |||
procNetstat.TcpExt.TCPHystartDelayDetect = value | |||
case "TCPHystartDelayCwnd": | |||
procNetstat.TcpExt.TCPHystartDelayCwnd = value | |||
case "TCPACKSkippedSynRecv": | |||
procNetstat.TcpExt.TCPACKSkippedSynRecv = value | |||
case "TCPACKSkippedPAWS": | |||
procNetstat.TcpExt.TCPACKSkippedPAWS = value | |||
case "TCPACKSkippedSeq": | |||
procNetstat.TcpExt.TCPACKSkippedSeq = value | |||
case "TCPACKSkippedFinWait2": | |||
procNetstat.TcpExt.TCPACKSkippedFinWait2 = value | |||
case "TCPACKSkippedTimeWait": | |||
procNetstat.TcpExt.TCPACKSkippedTimeWait = value | |||
case "TCPACKSkippedChallenge": | |||
procNetstat.TcpExt.TCPACKSkippedChallenge = value | |||
case "TCPWinProbe": | |||
procNetstat.TcpExt.TCPWinProbe = value | |||
case "TCPKeepAlive": | |||
procNetstat.TcpExt.TCPKeepAlive = value | |||
case "TCPMTUPFail": | |||
procNetstat.TcpExt.TCPMTUPFail = value | |||
case "TCPMTUPSuccess": | |||
procNetstat.TcpExt.TCPMTUPSuccess = value | |||
case "TCPWqueueTooBig": | |||
procNetstat.TcpExt.TCPWqueueTooBig = value | |||
} | |||
case "IpExt": | |||
switch key { | |||
case "InNoRoutes": | |||
procNetstat.IpExt.InNoRoutes = value | |||
case "InTruncatedPkts": | |||
procNetstat.IpExt.InTruncatedPkts = value | |||
case "InMcastPkts": | |||
procNetstat.IpExt.InMcastPkts = value | |||
case "OutMcastPkts": | |||
procNetstat.IpExt.OutMcastPkts = value | |||
case "InBcastPkts": | |||
procNetstat.IpExt.InBcastPkts = value | |||
case "OutBcastPkts": | |||
procNetstat.IpExt.OutBcastPkts = value | |||
case "InOctets": | |||
procNetstat.IpExt.InOctets = value | |||
case "OutOctets": | |||
procNetstat.IpExt.OutOctets = value | |||
case "InMcastOctets": | |||
procNetstat.IpExt.InMcastOctets = value | |||
case "OutMcastOctets": | |||
procNetstat.IpExt.OutMcastOctets = value | |||
case "InBcastOctets": | |||
procNetstat.IpExt.InBcastOctets = value | |||
case "OutBcastOctets": | |||
procNetstat.IpExt.OutBcastOctets = value | |||
case "InCsumErrors": | |||
procNetstat.IpExt.InCsumErrors = value | |||
case "InNoECTPkts": | |||
procNetstat.IpExt.InNoECTPkts = value | |||
case "InECT1Pkts": | |||
procNetstat.IpExt.InECT1Pkts = value | |||
case "InECT0Pkts": | |||
procNetstat.IpExt.InECT0Pkts = value | |||
case "InCEPkts": | |||
procNetstat.IpExt.InCEPkts = value | |||
case "ReasmOverlaps": | |||
procNetstat.IpExt.ReasmOverlaps = value | |||
} | |||
} | |||
} | |||
} | |||
return procNetstat, scanner.Err() | |||
} |
@@ -35,9 +35,10 @@ import ( | |||
const lineFormat = "avg10=%f avg60=%f avg300=%f total=%d" | |||
// PSILine is a single line of values as returned by /proc/pressure/* | |||
// The Avg entries are averages over n seconds, as a percentage | |||
// The Total line is in microseconds | |||
// PSILine is a single line of values as returned by `/proc/pressure/*`. | |||
// | |||
// The Avg entries are averages over n seconds, as a percentage. | |||
// The Total line is in microseconds. | |||
type PSILine struct { | |||
Avg10 float64 | |||
Avg60 float64 | |||
@@ -46,8 +47,9 @@ type PSILine struct { | |||
} | |||
// PSIStats represent pressure stall information from /proc/pressure/* | |||
// Some indicates the share of time in which at least some tasks are stalled | |||
// Full indicates the share of time in which all non-idle tasks are stalled simultaneously | |||
// | |||
// "Some" indicates the share of time in which at least some tasks are stalled. | |||
// "Full" indicates the share of time in which all non-idle tasks are stalled simultaneously. | |||
type PSIStats struct { | |||
Some *PSILine | |||
Full *PSILine | |||
@@ -65,7 +67,7 @@ func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) { | |||
return parsePSIStats(resource, bytes.NewReader(data)) | |||
} | |||
// parsePSIStats parses the specified file for pressure stall information | |||
// parsePSIStats parses the specified file for pressure stall information. | |||
func parsePSIStats(resource string, r io.Reader) (PSIStats, error) { | |||
psiStats := PSIStats{} | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build !windows | |||
// +build !windows | |||
package procfs | |||
@@ -28,30 +29,30 @@ import ( | |||
) | |||
var ( | |||
// match the header line before each mapped zone in /proc/pid/smaps | |||
// match the header line before each mapped zone in `/proc/pid/smaps`. | |||
procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) | |||
) | |||
type ProcSMapsRollup struct { | |||
// Amount of the mapping that is currently resident in RAM | |||
// Amount of the mapping that is currently resident in RAM. | |||
Rss uint64 | |||
// Process's proportional share of this mapping | |||
// Process's proportional share of this mapping. | |||
Pss uint64 | |||
// Size in bytes of clean shared pages | |||
// Size in bytes of clean shared pages. | |||
SharedClean uint64 | |||
// Size in bytes of dirty shared pages | |||
// Size in bytes of dirty shared pages. | |||
SharedDirty uint64 | |||
// Size in bytes of clean private pages | |||
// Size in bytes of clean private pages. | |||
PrivateClean uint64 | |||
// Size in bytes of dirty private pages | |||
// Size in bytes of dirty private pages. | |||
PrivateDirty uint64 | |||
// Amount of memory currently marked as referenced or accessed | |||
// Amount of memory currently marked as referenced or accessed. | |||
Referenced uint64 | |||
// Amount of memory that does not belong to any file | |||
// Amount of memory that does not belong to any file. | |||
Anonymous uint64 | |||
// Amount would-be-anonymous memory currently on swap | |||
// Amount would-be-anonymous memory currently on swap. | |||
Swap uint64 | |||
// Process's proportional memory on swap | |||
// Process's proportional memory on swap. | |||
SwapPss uint64 | |||
} | |||
@@ -0,0 +1,353 @@ | |||
// Copyright 2022 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" | |||
"io" | |||
"strconv" | |||
"strings" | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// ProcSnmp models the content of /proc/<pid>/net/snmp. | |||
type ProcSnmp struct { | |||
// The process ID. | |||
PID int | |||
Ip | |||
Icmp | |||
IcmpMsg | |||
Tcp | |||
Udp | |||
UdpLite | |||
} | |||
type Ip struct { // nolint:revive | |||
Forwarding float64 | |||
DefaultTTL float64 | |||
InReceives float64 | |||
InHdrErrors float64 | |||
InAddrErrors float64 | |||
ForwDatagrams float64 | |||
InUnknownProtos float64 | |||
InDiscards float64 | |||
InDelivers float64 | |||
OutRequests float64 | |||
OutDiscards float64 | |||
OutNoRoutes float64 | |||
ReasmTimeout float64 | |||
ReasmReqds float64 | |||
ReasmOKs float64 | |||
ReasmFails float64 | |||
FragOKs float64 | |||
FragFails float64 | |||
FragCreates float64 | |||
} | |||
type Icmp struct { | |||
InMsgs float64 | |||
InErrors float64 | |||
InCsumErrors float64 | |||
InDestUnreachs float64 | |||
InTimeExcds float64 | |||
InParmProbs float64 | |||
InSrcQuenchs float64 | |||
InRedirects float64 | |||
InEchos float64 | |||
InEchoReps float64 | |||
InTimestamps float64 | |||
InTimestampReps float64 | |||
InAddrMasks float64 | |||
InAddrMaskReps float64 | |||
OutMsgs float64 | |||
OutErrors float64 | |||
OutDestUnreachs float64 | |||
OutTimeExcds float64 | |||
OutParmProbs float64 | |||
OutSrcQuenchs float64 | |||
OutRedirects float64 | |||
OutEchos float64 | |||
OutEchoReps float64 | |||
OutTimestamps float64 | |||
OutTimestampReps float64 | |||
OutAddrMasks float64 | |||
OutAddrMaskReps float64 | |||
} | |||
type IcmpMsg struct { | |||
InType3 float64 | |||
OutType3 float64 | |||
} | |||
type Tcp struct { // nolint:revive | |||
RtoAlgorithm float64 | |||
RtoMin float64 | |||
RtoMax float64 | |||
MaxConn float64 | |||
ActiveOpens float64 | |||
PassiveOpens float64 | |||
AttemptFails float64 | |||
EstabResets float64 | |||
CurrEstab float64 | |||
InSegs float64 | |||
OutSegs float64 | |||
RetransSegs float64 | |||
InErrs float64 | |||
OutRsts float64 | |||
InCsumErrors float64 | |||
} | |||
type Udp struct { // nolint:revive | |||
InDatagrams float64 | |||
NoPorts float64 | |||
InErrors float64 | |||
OutDatagrams float64 | |||
RcvbufErrors float64 | |||
SndbufErrors float64 | |||
InCsumErrors float64 | |||
IgnoredMulti float64 | |||
} | |||
type UdpLite struct { // nolint:revive | |||
InDatagrams float64 | |||
NoPorts float64 | |||
InErrors float64 | |||
OutDatagrams float64 | |||
RcvbufErrors float64 | |||
SndbufErrors float64 | |||
InCsumErrors float64 | |||
IgnoredMulti float64 | |||
} | |||
func (p Proc) Snmp() (ProcSnmp, error) { | |||
filename := p.path("net/snmp") | |||
data, err := util.ReadFileNoStat(filename) | |||
if err != nil { | |||
return ProcSnmp{PID: p.PID}, err | |||
} | |||
procSnmp, err := parseSnmp(bytes.NewReader(data), filename) | |||
procSnmp.PID = p.PID | |||
return procSnmp, err | |||
} | |||
// parseSnmp parses the metrics from proc/<pid>/net/snmp file | |||
// and returns a map contains those metrics (e.g. {"Ip": {"Forwarding": 2}}). | |||
func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) { | |||
var ( | |||
scanner = bufio.NewScanner(r) | |||
procSnmp = ProcSnmp{} | |||
) | |||
for scanner.Scan() { | |||
nameParts := strings.Split(scanner.Text(), " ") | |||
scanner.Scan() | |||
valueParts := strings.Split(scanner.Text(), " ") | |||
// Remove trailing :. | |||
protocol := strings.TrimSuffix(nameParts[0], ":") | |||
if len(nameParts) != len(valueParts) { | |||
return procSnmp, fmt.Errorf("mismatch field count mismatch in %s: %s", | |||
fileName, protocol) | |||
} | |||
for i := 1; i < len(nameParts); i++ { | |||
value, err := strconv.ParseFloat(valueParts[i], 64) | |||
if err != nil { | |||
return procSnmp, err | |||
} | |||
key := nameParts[i] | |||
switch protocol { | |||
case "Ip": | |||
switch key { | |||
case "Forwarding": | |||
procSnmp.Ip.Forwarding = value | |||
case "DefaultTTL": | |||
procSnmp.Ip.DefaultTTL = value | |||
case "InReceives": | |||
procSnmp.Ip.InReceives = value | |||
case "InHdrErrors": | |||
procSnmp.Ip.InHdrErrors = value | |||
case "InAddrErrors": | |||
procSnmp.Ip.InAddrErrors = value | |||
case "ForwDatagrams": | |||
procSnmp.Ip.ForwDatagrams = value | |||
case "InUnknownProtos": | |||
procSnmp.Ip.InUnknownProtos = value | |||
case "InDiscards": | |||
procSnmp.Ip.InDiscards = value | |||
case "InDelivers": | |||
procSnmp.Ip.InDelivers = value | |||
case "OutRequests": | |||
procSnmp.Ip.OutRequests = value | |||
case "OutDiscards": | |||
procSnmp.Ip.OutDiscards = value | |||
case "OutNoRoutes": | |||
procSnmp.Ip.OutNoRoutes = value | |||
case "ReasmTimeout": | |||
procSnmp.Ip.ReasmTimeout = value | |||
case "ReasmReqds": | |||
procSnmp.Ip.ReasmReqds = value | |||
case "ReasmOKs": | |||
procSnmp.Ip.ReasmOKs = value | |||
case "ReasmFails": | |||
procSnmp.Ip.ReasmFails = value | |||
case "FragOKs": | |||
procSnmp.Ip.FragOKs = value | |||
case "FragFails": | |||
procSnmp.Ip.FragFails = value | |||
case "FragCreates": | |||
procSnmp.Ip.FragCreates = value | |||
} | |||
case "Icmp": | |||
switch key { | |||
case "InMsgs": | |||
procSnmp.Icmp.InMsgs = value | |||
case "InErrors": | |||
procSnmp.Icmp.InErrors = value | |||
case "InCsumErrors": | |||
procSnmp.Icmp.InCsumErrors = value | |||
case "InDestUnreachs": | |||
procSnmp.Icmp.InDestUnreachs = value | |||
case "InTimeExcds": | |||
procSnmp.Icmp.InTimeExcds = value | |||
case "InParmProbs": | |||
procSnmp.Icmp.InParmProbs = value | |||
case "InSrcQuenchs": | |||
procSnmp.Icmp.InSrcQuenchs = value | |||
case "InRedirects": | |||
procSnmp.Icmp.InRedirects = value | |||
case "InEchos": | |||
procSnmp.Icmp.InEchos = value | |||
case "InEchoReps": | |||
procSnmp.Icmp.InEchoReps = value | |||
case "InTimestamps": | |||
procSnmp.Icmp.InTimestamps = value | |||
case "InTimestampReps": | |||
procSnmp.Icmp.InTimestampReps = value | |||
case "InAddrMasks": | |||
procSnmp.Icmp.InAddrMasks = value | |||
case "InAddrMaskReps": | |||
procSnmp.Icmp.InAddrMaskReps = value | |||
case "OutMsgs": | |||
procSnmp.Icmp.OutMsgs = value | |||
case "OutErrors": | |||
procSnmp.Icmp.OutErrors = value | |||
case "OutDestUnreachs": | |||
procSnmp.Icmp.OutDestUnreachs = value | |||
case "OutTimeExcds": | |||
procSnmp.Icmp.OutTimeExcds = value | |||
case "OutParmProbs": | |||
procSnmp.Icmp.OutParmProbs = value | |||
case "OutSrcQuenchs": | |||
procSnmp.Icmp.OutSrcQuenchs = value | |||
case "OutRedirects": | |||
procSnmp.Icmp.OutRedirects = value | |||
case "OutEchos": | |||
procSnmp.Icmp.OutEchos = value | |||
case "OutEchoReps": | |||
procSnmp.Icmp.OutEchoReps = value | |||
case "OutTimestamps": | |||
procSnmp.Icmp.OutTimestamps = value | |||
case "OutTimestampReps": | |||
procSnmp.Icmp.OutTimestampReps = value | |||
case "OutAddrMasks": | |||
procSnmp.Icmp.OutAddrMasks = value | |||
case "OutAddrMaskReps": | |||
procSnmp.Icmp.OutAddrMaskReps = value | |||
} | |||
case "IcmpMsg": | |||
switch key { | |||
case "InType3": | |||
procSnmp.IcmpMsg.InType3 = value | |||
case "OutType3": | |||
procSnmp.IcmpMsg.OutType3 = value | |||
} | |||
case "Tcp": | |||
switch key { | |||
case "RtoAlgorithm": | |||
procSnmp.Tcp.RtoAlgorithm = value | |||
case "RtoMin": | |||
procSnmp.Tcp.RtoMin = value | |||
case "RtoMax": | |||
procSnmp.Tcp.RtoMax = value | |||
case "MaxConn": | |||
procSnmp.Tcp.MaxConn = value | |||
case "ActiveOpens": | |||
procSnmp.Tcp.ActiveOpens = value | |||
case "PassiveOpens": | |||
procSnmp.Tcp.PassiveOpens = value | |||
case "AttemptFails": | |||
procSnmp.Tcp.AttemptFails = value | |||
case "EstabResets": | |||
procSnmp.Tcp.EstabResets = value | |||
case "CurrEstab": | |||
procSnmp.Tcp.CurrEstab = value | |||
case "InSegs": | |||
procSnmp.Tcp.InSegs = value | |||
case "OutSegs": | |||
procSnmp.Tcp.OutSegs = value | |||
case "RetransSegs": | |||
procSnmp.Tcp.RetransSegs = value | |||
case "InErrs": | |||
procSnmp.Tcp.InErrs = value | |||
case "OutRsts": | |||
procSnmp.Tcp.OutRsts = value | |||
case "InCsumErrors": | |||
procSnmp.Tcp.InCsumErrors = value | |||
} | |||
case "Udp": | |||
switch key { | |||
case "InDatagrams": | |||
procSnmp.Udp.InDatagrams = value | |||
case "NoPorts": | |||
procSnmp.Udp.NoPorts = value | |||
case "InErrors": | |||
procSnmp.Udp.InErrors = value | |||
case "OutDatagrams": | |||
procSnmp.Udp.OutDatagrams = value | |||
case "RcvbufErrors": | |||
procSnmp.Udp.RcvbufErrors = value | |||
case "SndbufErrors": | |||
procSnmp.Udp.SndbufErrors = value | |||
case "InCsumErrors": | |||
procSnmp.Udp.InCsumErrors = value | |||
case "IgnoredMulti": | |||
procSnmp.Udp.IgnoredMulti = value | |||
} | |||
case "UdpLite": | |||
switch key { | |||
case "InDatagrams": | |||
procSnmp.UdpLite.InDatagrams = value | |||
case "NoPorts": | |||
procSnmp.UdpLite.NoPorts = value | |||
case "InErrors": | |||
procSnmp.UdpLite.InErrors = value | |||
case "OutDatagrams": | |||
procSnmp.UdpLite.OutDatagrams = value | |||
case "RcvbufErrors": | |||
procSnmp.UdpLite.RcvbufErrors = value | |||
case "SndbufErrors": | |||
procSnmp.UdpLite.SndbufErrors = value | |||
case "InCsumErrors": | |||
procSnmp.UdpLite.InCsumErrors = value | |||
case "IgnoredMulti": | |||
procSnmp.UdpLite.IgnoredMulti = value | |||
} | |||
} | |||
} | |||
} | |||
return procSnmp, scanner.Err() | |||
} |
@@ -0,0 +1,381 @@ | |||
// Copyright 2022 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" | |||
"errors" | |||
"io" | |||
"os" | |||
"strconv" | |||
"strings" | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// ProcSnmp6 models the content of /proc/<pid>/net/snmp6. | |||
type ProcSnmp6 struct { | |||
// The process ID. | |||
PID int | |||
Ip6 | |||
Icmp6 | |||
Udp6 | |||
UdpLite6 | |||
} | |||
type Ip6 struct { // nolint:revive | |||
InReceives float64 | |||
InHdrErrors float64 | |||
InTooBigErrors float64 | |||
InNoRoutes float64 | |||
InAddrErrors float64 | |||
InUnknownProtos float64 | |||
InTruncatedPkts float64 | |||
InDiscards float64 | |||
InDelivers float64 | |||
OutForwDatagrams float64 | |||
OutRequests float64 | |||
OutDiscards float64 | |||
OutNoRoutes float64 | |||
ReasmTimeout float64 | |||
ReasmReqds float64 | |||
ReasmOKs float64 | |||
ReasmFails float64 | |||
FragOKs float64 | |||
FragFails float64 | |||
FragCreates float64 | |||
InMcastPkts float64 | |||
OutMcastPkts float64 | |||
InOctets float64 | |||
OutOctets float64 | |||
InMcastOctets float64 | |||
OutMcastOctets float64 | |||
InBcastOctets float64 | |||
OutBcastOctets float64 | |||
InNoECTPkts float64 | |||
InECT1Pkts float64 | |||
InECT0Pkts float64 | |||
InCEPkts float64 | |||
} | |||
type Icmp6 struct { | |||
InMsgs float64 | |||
InErrors float64 | |||
OutMsgs float64 | |||
OutErrors float64 | |||
InCsumErrors float64 | |||
InDestUnreachs float64 | |||
InPktTooBigs float64 | |||
InTimeExcds float64 | |||
InParmProblems float64 | |||
InEchos float64 | |||
InEchoReplies float64 | |||
InGroupMembQueries float64 | |||
InGroupMembResponses float64 | |||
InGroupMembReductions float64 | |||
InRouterSolicits float64 | |||
InRouterAdvertisements float64 | |||
InNeighborSolicits float64 | |||
InNeighborAdvertisements float64 | |||
InRedirects float64 | |||
InMLDv2Reports float64 | |||
OutDestUnreachs float64 | |||
OutPktTooBigs float64 | |||
OutTimeExcds float64 | |||
OutParmProblems float64 | |||
OutEchos float64 | |||
OutEchoReplies float64 | |||
OutGroupMembQueries float64 | |||
OutGroupMembResponses float64 | |||
OutGroupMembReductions float64 | |||
OutRouterSolicits float64 | |||
OutRouterAdvertisements float64 | |||
OutNeighborSolicits float64 | |||
OutNeighborAdvertisements float64 | |||
OutRedirects float64 | |||
OutMLDv2Reports float64 | |||
InType1 float64 | |||
InType134 float64 | |||
InType135 float64 | |||
InType136 float64 | |||
InType143 float64 | |||
OutType133 float64 | |||
OutType135 float64 | |||
OutType136 float64 | |||
OutType143 float64 | |||
} | |||
type Udp6 struct { // nolint:revive | |||
InDatagrams float64 | |||
NoPorts float64 | |||
InErrors float64 | |||
OutDatagrams float64 | |||
RcvbufErrors float64 | |||
SndbufErrors float64 | |||
InCsumErrors float64 | |||
IgnoredMulti float64 | |||
} | |||
type UdpLite6 struct { // nolint:revive | |||
InDatagrams float64 | |||
NoPorts float64 | |||
InErrors float64 | |||
OutDatagrams float64 | |||
RcvbufErrors float64 | |||
SndbufErrors float64 | |||
InCsumErrors float64 | |||
} | |||
func (p Proc) Snmp6() (ProcSnmp6, error) { | |||
filename := p.path("net/snmp6") | |||
data, err := util.ReadFileNoStat(filename) | |||
if err != nil { | |||
// On systems with IPv6 disabled, this file won't exist. | |||
// Do nothing. | |||
if errors.Is(err, os.ErrNotExist) { | |||
return ProcSnmp6{PID: p.PID}, nil | |||
} | |||
return ProcSnmp6{PID: p.PID}, err | |||
} | |||
procSnmp6, err := parseSNMP6Stats(bytes.NewReader(data)) | |||
procSnmp6.PID = p.PID | |||
return procSnmp6, err | |||
} | |||
// parseSnmp6 parses the metrics from proc/<pid>/net/snmp6 file | |||
// and returns a map contains those metrics. | |||
func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) { | |||
var ( | |||
scanner = bufio.NewScanner(r) | |||
procSnmp6 = ProcSnmp6{} | |||
) | |||
for scanner.Scan() { | |||
stat := strings.Fields(scanner.Text()) | |||
if len(stat) < 2 { | |||
continue | |||
} | |||
// Expect to have "6" in metric name, skip line otherwise | |||
if sixIndex := strings.Index(stat[0], "6"); sixIndex != -1 { | |||
protocol := stat[0][:sixIndex+1] | |||
key := stat[0][sixIndex+1:] | |||
value, err := strconv.ParseFloat(stat[1], 64) | |||
if err != nil { | |||
return procSnmp6, err | |||
} | |||
switch protocol { | |||
case "Ip6": | |||
switch key { | |||
case "InReceives": | |||
procSnmp6.Ip6.InReceives = value | |||
case "InHdrErrors": | |||
procSnmp6.Ip6.InHdrErrors = value | |||
case "InTooBigErrors": | |||
procSnmp6.Ip6.InTooBigErrors = value | |||
case "InNoRoutes": | |||
procSnmp6.Ip6.InNoRoutes = value | |||
case "InAddrErrors": | |||
procSnmp6.Ip6.InAddrErrors = value | |||
case "InUnknownProtos": | |||
procSnmp6.Ip6.InUnknownProtos = value | |||
case "InTruncatedPkts": | |||
procSnmp6.Ip6.InTruncatedPkts = value | |||
case "InDiscards": | |||
procSnmp6.Ip6.InDiscards = value | |||
case "InDelivers": | |||
procSnmp6.Ip6.InDelivers = value | |||
case "OutForwDatagrams": | |||
procSnmp6.Ip6.OutForwDatagrams = value | |||
case "OutRequests": | |||
procSnmp6.Ip6.OutRequests = value | |||
case "OutDiscards": | |||
procSnmp6.Ip6.OutDiscards = value | |||
case "OutNoRoutes": | |||
procSnmp6.Ip6.OutNoRoutes = value | |||
case "ReasmTimeout": | |||
procSnmp6.Ip6.ReasmTimeout = value | |||
case "ReasmReqds": | |||
procSnmp6.Ip6.ReasmReqds = value | |||
case "ReasmOKs": | |||
procSnmp6.Ip6.ReasmOKs = value | |||
case "ReasmFails": | |||
procSnmp6.Ip6.ReasmFails = value | |||
case "FragOKs": | |||
procSnmp6.Ip6.FragOKs = value | |||
case "FragFails": | |||
procSnmp6.Ip6.FragFails = value | |||
case "FragCreates": | |||
procSnmp6.Ip6.FragCreates = value | |||
case "InMcastPkts": | |||
procSnmp6.Ip6.InMcastPkts = value | |||
case "OutMcastPkts": | |||
procSnmp6.Ip6.OutMcastPkts = value | |||
case "InOctets": | |||
procSnmp6.Ip6.InOctets = value | |||
case "OutOctets": | |||
procSnmp6.Ip6.OutOctets = value | |||
case "InMcastOctets": | |||
procSnmp6.Ip6.InMcastOctets = value | |||
case "OutMcastOctets": | |||
procSnmp6.Ip6.OutMcastOctets = value | |||
case "InBcastOctets": | |||
procSnmp6.Ip6.InBcastOctets = value | |||
case "OutBcastOctets": | |||
procSnmp6.Ip6.OutBcastOctets = value | |||
case "InNoECTPkts": | |||
procSnmp6.Ip6.InNoECTPkts = value | |||
case "InECT1Pkts": | |||
procSnmp6.Ip6.InECT1Pkts = value | |||
case "InECT0Pkts": | |||
procSnmp6.Ip6.InECT0Pkts = value | |||
case "InCEPkts": | |||
procSnmp6.Ip6.InCEPkts = value | |||
} | |||
case "Icmp6": | |||
switch key { | |||
case "InMsgs": | |||
procSnmp6.Icmp6.InMsgs = value | |||
case "InErrors": | |||
procSnmp6.Icmp6.InErrors = value | |||
case "OutMsgs": | |||
procSnmp6.Icmp6.OutMsgs = value | |||
case "OutErrors": | |||
procSnmp6.Icmp6.OutErrors = value | |||
case "InCsumErrors": | |||
procSnmp6.Icmp6.InCsumErrors = value | |||
case "InDestUnreachs": | |||
procSnmp6.Icmp6.InDestUnreachs = value | |||
case "InPktTooBigs": | |||
procSnmp6.Icmp6.InPktTooBigs = value | |||
case "InTimeExcds": | |||
procSnmp6.Icmp6.InTimeExcds = value | |||
case "InParmProblems": | |||
procSnmp6.Icmp6.InParmProblems = value | |||
case "InEchos": | |||
procSnmp6.Icmp6.InEchos = value | |||
case "InEchoReplies": | |||
procSnmp6.Icmp6.InEchoReplies = value | |||
case "InGroupMembQueries": | |||
procSnmp6.Icmp6.InGroupMembQueries = value | |||
case "InGroupMembResponses": | |||
procSnmp6.Icmp6.InGroupMembResponses = value | |||
case "InGroupMembReductions": | |||
procSnmp6.Icmp6.InGroupMembReductions = value | |||
case "InRouterSolicits": | |||
procSnmp6.Icmp6.InRouterSolicits = value | |||
case "InRouterAdvertisements": | |||
procSnmp6.Icmp6.InRouterAdvertisements = value | |||
case "InNeighborSolicits": | |||
procSnmp6.Icmp6.InNeighborSolicits = value | |||
case "InNeighborAdvertisements": | |||
procSnmp6.Icmp6.InNeighborAdvertisements = value | |||
case "InRedirects": | |||
procSnmp6.Icmp6.InRedirects = value | |||
case "InMLDv2Reports": | |||
procSnmp6.Icmp6.InMLDv2Reports = value | |||
case "OutDestUnreachs": | |||
procSnmp6.Icmp6.OutDestUnreachs = value | |||
case "OutPktTooBigs": | |||
procSnmp6.Icmp6.OutPktTooBigs = value | |||
case "OutTimeExcds": | |||
procSnmp6.Icmp6.OutTimeExcds = value | |||
case "OutParmProblems": | |||
procSnmp6.Icmp6.OutParmProblems = value | |||
case "OutEchos": | |||
procSnmp6.Icmp6.OutEchos = value | |||
case "OutEchoReplies": | |||
procSnmp6.Icmp6.OutEchoReplies = value | |||
case "OutGroupMembQueries": | |||
procSnmp6.Icmp6.OutGroupMembQueries = value | |||
case "OutGroupMembResponses": | |||
procSnmp6.Icmp6.OutGroupMembResponses = value | |||
case "OutGroupMembReductions": | |||
procSnmp6.Icmp6.OutGroupMembReductions = value | |||
case "OutRouterSolicits": | |||
procSnmp6.Icmp6.OutRouterSolicits = value | |||
case "OutRouterAdvertisements": | |||
procSnmp6.Icmp6.OutRouterAdvertisements = value | |||
case "OutNeighborSolicits": | |||
procSnmp6.Icmp6.OutNeighborSolicits = value | |||
case "OutNeighborAdvertisements": | |||
procSnmp6.Icmp6.OutNeighborAdvertisements = value | |||
case "OutRedirects": | |||
procSnmp6.Icmp6.OutRedirects = value | |||
case "OutMLDv2Reports": | |||
procSnmp6.Icmp6.OutMLDv2Reports = value | |||
case "InType1": | |||
procSnmp6.Icmp6.InType1 = value | |||
case "InType134": | |||
procSnmp6.Icmp6.InType134 = value | |||
case "InType135": | |||
procSnmp6.Icmp6.InType135 = value | |||
case "InType136": | |||
procSnmp6.Icmp6.InType136 = value | |||
case "InType143": | |||
procSnmp6.Icmp6.InType143 = value | |||
case "OutType133": | |||
procSnmp6.Icmp6.OutType133 = value | |||
case "OutType135": | |||
procSnmp6.Icmp6.OutType135 = value | |||
case "OutType136": | |||
procSnmp6.Icmp6.OutType136 = value | |||
case "OutType143": | |||
procSnmp6.Icmp6.OutType143 = value | |||
} | |||
case "Udp6": | |||
switch key { | |||
case "InDatagrams": | |||
procSnmp6.Udp6.InDatagrams = value | |||
case "NoPorts": | |||
procSnmp6.Udp6.NoPorts = value | |||
case "InErrors": | |||
procSnmp6.Udp6.InErrors = value | |||
case "OutDatagrams": | |||
procSnmp6.Udp6.OutDatagrams = value | |||
case "RcvbufErrors": | |||
procSnmp6.Udp6.RcvbufErrors = value | |||
case "SndbufErrors": | |||
procSnmp6.Udp6.SndbufErrors = value | |||
case "InCsumErrors": | |||
procSnmp6.Udp6.InCsumErrors = value | |||
case "IgnoredMulti": | |||
procSnmp6.Udp6.IgnoredMulti = value | |||
} | |||
case "UdpLite6": | |||
switch key { | |||
case "InDatagrams": | |||
procSnmp6.UdpLite6.InDatagrams = value | |||
case "NoPorts": | |||
procSnmp6.UdpLite6.NoPorts = value | |||
case "InErrors": | |||
procSnmp6.UdpLite6.InErrors = value | |||
case "OutDatagrams": | |||
procSnmp6.UdpLite6.OutDatagrams = value | |||
case "RcvbufErrors": | |||
procSnmp6.UdpLite6.RcvbufErrors = value | |||
case "SndbufErrors": | |||
procSnmp6.UdpLite6.SndbufErrors = value | |||
case "InCsumErrors": | |||
procSnmp6.UdpLite6.InCsumErrors = value | |||
} | |||
} | |||
} | |||
} | |||
return procSnmp6, scanner.Err() | |||
} |
@@ -81,10 +81,10 @@ type ProcStat struct { | |||
STime uint | |||
// Amount of time that this process's waited-for children have been | |||
// scheduled in user mode, measured in clock ticks. | |||
CUTime uint | |||
CUTime int | |||
// Amount of time that this process's waited-for children have been | |||
// scheduled in kernel mode, measured in clock ticks. | |||
CSTime uint | |||
CSTime int | |||
// For processes running a real-time scheduling policy, this is the negated | |||
// scheduling priority, minus one. | |||
Priority int | |||
@@ -115,7 +115,7 @@ type ProcStat struct { | |||
// NewStat returns the current status information of the process. | |||
// | |||
// Deprecated: use p.Stat() instead | |||
// Deprecated: Use p.Stat() instead. | |||
func (p Proc) NewStat() (ProcStat, error) { | |||
return p.Stat() | |||
} | |||
@@ -141,6 +141,11 @@ func (p Proc) Stat() (ProcStat, error) { | |||
} | |||
s.Comm = string(data[l+1 : r]) | |||
// Check the following resources for the details about the particular stat | |||
// fields and their data types: | |||
// * https://man7.org/linux/man-pages/man5/proc.5.html | |||
// * https://man7.org/linux/man-pages/man3/scanf.3.html | |||
_, err = fmt.Fscan( | |||
bytes.NewBuffer(data[r+2:]), | |||
&s.State, | |||
@@ -33,37 +33,37 @@ type ProcStatus struct { | |||
TGID int | |||
// Peak virtual memory size. | |||
VmPeak uint64 // nolint:golint | |||
VmPeak uint64 // nolint:revive | |||
// Virtual memory size. | |||
VmSize uint64 // nolint:golint | |||
VmSize uint64 // nolint:revive | |||
// Locked memory size. | |||
VmLck uint64 // nolint:golint | |||
VmLck uint64 // nolint:revive | |||
// Pinned memory size. | |||
VmPin uint64 // nolint:golint | |||
VmPin uint64 // nolint:revive | |||
// Peak resident set size. | |||
VmHWM uint64 // nolint:golint | |||
VmHWM uint64 // nolint:revive | |||
// Resident set size (sum of RssAnnon RssFile and RssShmem). | |||
VmRSS uint64 // nolint:golint | |||
VmRSS uint64 // nolint:revive | |||
// Size of resident anonymous memory. | |||
RssAnon uint64 // nolint:golint | |||
RssAnon uint64 // nolint:revive | |||
// Size of resident file mappings. | |||
RssFile uint64 // nolint:golint | |||
RssFile uint64 // nolint:revive | |||
// Size of resident shared memory. | |||
RssShmem uint64 // nolint:golint | |||
RssShmem uint64 // nolint:revive | |||
// Size of data segments. | |||
VmData uint64 // nolint:golint | |||
VmData uint64 // nolint:revive | |||
// Size of stack segments. | |||
VmStk uint64 // nolint:golint | |||
VmStk uint64 // nolint:revive | |||
// Size of text segments. | |||
VmExe uint64 // nolint:golint | |||
VmExe uint64 // nolint:revive | |||
// Shared library code size. | |||
VmLib uint64 // nolint:golint | |||
VmLib uint64 // nolint:revive | |||
// Page table entries size. | |||
VmPTE uint64 // nolint:golint | |||
VmPTE uint64 // nolint:revive | |||
// Size of second-level page tables. | |||
VmPMD uint64 // nolint:golint | |||
VmPMD uint64 // nolint:revive | |||
// Swapped-out virtual memory size by anonymous private. | |||
VmSwap uint64 // nolint:golint | |||
VmSwap uint64 // nolint:revive | |||
// Size of hugetlb memory portions | |||
HugetlbPages uint64 | |||
@@ -0,0 +1,51 @@ | |||
// Copyright 2022 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 ( | |||
"fmt" | |||
"strings" | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
func sysctlToPath(sysctl string) string { | |||
return strings.Replace(sysctl, ".", "/", -1) | |||
} | |||
func (fs FS) SysctlStrings(sysctl string) ([]string, error) { | |||
value, err := util.SysReadFile(fs.proc.Path("sys", sysctlToPath(sysctl))) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return strings.Fields(value), nil | |||
} | |||
func (fs FS) SysctlInts(sysctl string) ([]int, error) { | |||
fields, err := fs.SysctlStrings(sysctl) | |||
if err != nil { | |||
return nil, err | |||
} | |||
values := make([]int, len(fields)) | |||
for i, f := range fields { | |||
vp := util.NewValueParser(f) | |||
values[i] = vp.Int() | |||
if err := vp.Err(); err != nil { | |||
return nil, fmt.Errorf("field %d in sysctl %s is not a valid int: %w", i, sysctl, err) | |||
} | |||
} | |||
return values, nil | |||
} |
@@ -40,7 +40,7 @@ type Schedstat struct { | |||
CPUs []*SchedstatCPU | |||
} | |||
// SchedstatCPU contains the values from one "cpu<N>" line | |||
// SchedstatCPU contains the values from one "cpu<N>" line. | |||
type SchedstatCPU struct { | |||
CPUNum string | |||
@@ -49,14 +49,14 @@ type SchedstatCPU struct { | |||
RunTimeslices uint64 | |||
} | |||
// ProcSchedstat contains the values from /proc/<pid>/schedstat | |||
// ProcSchedstat contains the values from `/proc/<pid>/schedstat`. | |||
type ProcSchedstat struct { | |||
RunningNanoseconds uint64 | |||
WaitingNanoseconds uint64 | |||
RunTimeslices uint64 | |||
} | |||
// Schedstat reads data from /proc/schedstat | |||
// Schedstat reads data from `/proc/schedstat`. | |||
func (fs FS) Schedstat() (*Schedstat, error) { | |||
file, err := os.Open(fs.proc.Path("schedstat")) | |||
if err != nil { | |||
@@ -137,7 +137,7 @@ func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) { | |||
return s, nil | |||
} | |||
// SlabInfo reads data from /proc/slabinfo | |||
// 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 | |||
@@ -0,0 +1,160 @@ | |||
// Copyright 2022 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" | |||
"io" | |||
"strconv" | |||
"strings" | |||
"github.com/prometheus/procfs/internal/util" | |||
) | |||
// Softirqs represents the softirq statistics. | |||
type Softirqs struct { | |||
Hi []uint64 | |||
Timer []uint64 | |||
NetTx []uint64 | |||
NetRx []uint64 | |||
Block []uint64 | |||
IRQPoll []uint64 | |||
Tasklet []uint64 | |||
Sched []uint64 | |||
HRTimer []uint64 | |||
RCU []uint64 | |||
} | |||
func (fs FS) Softirqs() (Softirqs, error) { | |||
fileName := fs.proc.Path("softirqs") | |||
data, err := util.ReadFileNoStat(fileName) | |||
if err != nil { | |||
return Softirqs{}, err | |||
} | |||
reader := bytes.NewReader(data) | |||
return parseSoftirqs(reader) | |||
} | |||
func parseSoftirqs(r io.Reader) (Softirqs, error) { | |||
var ( | |||
softirqs = Softirqs{} | |||
scanner = bufio.NewScanner(r) | |||
) | |||
if !scanner.Scan() { | |||
return Softirqs{}, fmt.Errorf("softirqs empty") | |||
} | |||
for scanner.Scan() { | |||
parts := strings.Fields(scanner.Text()) | |||
var err error | |||
// require at least one cpu | |||
if len(parts) < 2 { | |||
continue | |||
} | |||
switch { | |||
case parts[0] == "HI:": | |||
perCPU := parts[1:] | |||
softirqs.Hi = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (HI%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "TIMER:": | |||
perCPU := parts[1:] | |||
softirqs.Timer = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (TIMER%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "NET_TX:": | |||
perCPU := parts[1:] | |||
softirqs.NetTx = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (NET_TX%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "NET_RX:": | |||
perCPU := parts[1:] | |||
softirqs.NetRx = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (NET_RX%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "BLOCK:": | |||
perCPU := parts[1:] | |||
softirqs.Block = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (BLOCK%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "IRQ_POLL:": | |||
perCPU := parts[1:] | |||
softirqs.IRQPoll = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (IRQ_POLL%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "TASKLET:": | |||
perCPU := parts[1:] | |||
softirqs.Tasklet = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (TASKLET%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "SCHED:": | |||
perCPU := parts[1:] | |||
softirqs.Sched = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (SCHED%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "HRTIMER:": | |||
perCPU := parts[1:] | |||
softirqs.HRTimer = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (HRTIMER%d): %w", count, i, err) | |||
} | |||
} | |||
case parts[0] == "RCU:": | |||
perCPU := parts[1:] | |||
softirqs.RCU = make([]uint64, len(perCPU)) | |||
for i, count := range perCPU { | |||
if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse %q (RCU%d): %w", count, i, err) | |||
} | |||
} | |||
} | |||
} | |||
if err := scanner.Err(); err != nil { | |||
return Softirqs{}, fmt.Errorf("couldn't parse softirqs: %w", err) | |||
} | |||
return softirqs, scanner.Err() | |||
} |
@@ -41,7 +41,7 @@ type CPUStat struct { | |||
// SoftIRQStat represent the softirq statistics as exported in the procfs stat file. | |||
// A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html | |||
// It is possible to get per-cpu stats by reading /proc/softirqs | |||
// It is possible to get per-cpu stats by reading `/proc/softirqs`. | |||
type SoftIRQStat struct { | |||
Hi uint64 | |||
Timer uint64 | |||
@@ -145,7 +145,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { | |||
// NewStat returns information about current cpu/process statistics. | |||
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt | |||
// | |||
// Deprecated: use fs.Stat() instead | |||
// Deprecated: Use fs.Stat() instead. | |||
func NewStat() (Stat, error) { | |||
fs, err := NewFS(fs.DefaultProcMountPoint) | |||
if err != nil { | |||
@@ -155,15 +155,15 @@ func NewStat() (Stat, error) { | |||
} | |||
// NewStat returns information about current cpu/process statistics. | |||
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt | |||
// See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt | |||
// | |||
// Deprecated: use fs.Stat() instead | |||
// Deprecated: Use fs.Stat() instead. | |||
func (fs FS) NewStat() (Stat, error) { | |||
return fs.Stat() | |||
} | |||
// Stat returns information about current cpu/process statistics. | |||
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt | |||
// See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt | |||
func (fs FS) Stat() (Stat, error) { | |||
fileName := fs.proc.Path("stat") | |||
data, err := util.ReadFileNoStat(fileName) | |||
@@ -11,13 +11,13 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build !windows | |||
// +build !windows | |||
package procfs | |||
import ( | |||
"fmt" | |||
"io/ioutil" | |||
"os" | |||
"path/filepath" | |||
"strings" | |||
@@ -29,7 +29,7 @@ import ( | |||
// https://www.kernel.org/doc/Documentation/sysctl/vm.txt | |||
// Each setting is exposed as a single file. | |||
// Each file contains one line with a single numerical value, except lowmem_reserve_ratio which holds an array | |||
// and numa_zonelist_order (deprecated) which is a string | |||
// and numa_zonelist_order (deprecated) which is a string. | |||
type VM struct { | |||
AdminReserveKbytes *int64 // /proc/sys/vm/admin_reserve_kbytes | |||
BlockDump *int64 // /proc/sys/vm/block_dump | |||
@@ -87,7 +87,7 @@ func (fs FS) VM() (*VM, error) { | |||
return nil, fmt.Errorf("%s is not a directory", path) | |||
} | |||
files, err := ioutil.ReadDir(path) | |||
files, err := os.ReadDir(path) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -11,6 +11,7 @@ | |||
// See the License for the specific language governing permissions and | |||
// limitations under the License. | |||
//go:build !windows | |||
// +build !windows | |||
package procfs | |||
@@ -18,7 +19,7 @@ package procfs | |||
import ( | |||
"bytes" | |||
"fmt" | |||
"io/ioutil" | |||
"os" | |||
"regexp" | |||
"strings" | |||
@@ -72,7 +73,7 @@ var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`) | |||
// structs containing the relevant info. More information available here: | |||
// https://www.kernel.org/doc/Documentation/sysctl/vm.txt | |||
func (fs FS) Zoneinfo() ([]Zoneinfo, error) { | |||
data, err := ioutil.ReadFile(fs.proc.Path("zoneinfo")) | |||
data, err := os.ReadFile(fs.proc.Path("zoneinfo")) | |||
if err != nil { | |||
return nil, fmt.Errorf("error reading zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err) | |||
} | |||
@@ -1,3 +0,0 @@ | |||
# This source code refers to The Go Authors for copyright purposes. | |||
# The master list of authors is in the main Go distribution, | |||
# visible at http://tip.golang.org/AUTHORS. |
@@ -1,3 +0,0 @@ | |||
# This source code was written by the Go contributors. | |||
# The master list of contributors is in the main Go distribution, | |||
# visible at http://tip.golang.org/CONTRIBUTORS. |
@@ -0,0 +1,29 @@ | |||
// Copyright 2021 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. | |||
//go:build (darwin || freebsd || netbsd || openbsd) && gc | |||
// +build darwin freebsd netbsd openbsd | |||
// +build gc | |||
#include "textflag.h" | |||
// System call support for RISCV64 BSD | |||
// Just jump to package syscall's implementation for all these functions. | |||
// The runtime may know about them. | |||
TEXT ·Syscall(SB),NOSPLIT,$0-56 | |||
JMP syscall·Syscall(SB) | |||
TEXT ·Syscall6(SB),NOSPLIT,$0-80 | |||
JMP syscall·Syscall6(SB) | |||
TEXT ·Syscall9(SB),NOSPLIT,$0-104 | |||
JMP syscall·Syscall9(SB) | |||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56 | |||
JMP syscall·RawSyscall(SB) | |||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 | |||
JMP syscall·RawSyscall6(SB) |
@@ -0,0 +1,54 @@ | |||
// Copyright 2022 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. | |||
//go:build linux && loong64 && gc | |||
// +build linux | |||
// +build loong64 | |||
// +build gc | |||
#include "textflag.h" | |||
// Just jump to package syscall's implementation for all these functions. | |||
// The runtime may know about them. | |||
TEXT ·Syscall(SB),NOSPLIT,$0-56 | |||
JMP syscall·Syscall(SB) | |||
TEXT ·Syscall6(SB),NOSPLIT,$0-80 | |||
JMP syscall·Syscall6(SB) | |||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48 | |||
JAL runtime·entersyscall(SB) | |||
MOVV a1+8(FP), R4 | |||
MOVV a2+16(FP), R5 | |||
MOVV a3+24(FP), R6 | |||
MOVV R0, R7 | |||
MOVV R0, R8 | |||
MOVV R0, R9 | |||
MOVV trap+0(FP), R11 // syscall entry | |||
SYSCALL | |||
MOVV R4, r1+32(FP) | |||
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 | |||
JAL runtime·exitsyscall(SB) | |||
RET | |||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56 | |||
JMP syscall·RawSyscall(SB) | |||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 | |||
JMP syscall·RawSyscall6(SB) | |||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48 | |||
MOVV a1+8(FP), R4 | |||
MOVV a2+16(FP), R5 | |||
MOVV a3+24(FP), R6 | |||
MOVV R0, R7 | |||
MOVV R0, R8 | |||
MOVV R0, R9 | |||
MOVV trap+0(FP), R11 // syscall entry | |||
SYSCALL | |||
MOVV R4, r1+32(FP) | |||
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 | |||
RET |
@@ -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 386 || amd64 || amd64p32 || alpha || arm || arm64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh | |||
// +build 386 amd64 amd64p32 alpha arm arm64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh | |||
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh | |||
// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh | |||
package unix | |||
@@ -1,233 +0,0 @@ | |||
// Copyright 2017 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. | |||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep | |||
// them here for backwards compatibility. | |||
package unix | |||
const ( | |||
DLT_HHDLC = 0x79 | |||
IFF_SMART = 0x20 | |||
IFT_1822 = 0x2 | |||
IFT_A12MPPSWITCH = 0x82 | |||
IFT_AAL2 = 0xbb | |||
IFT_AAL5 = 0x31 | |||
IFT_ADSL = 0x5e | |||
IFT_AFLANE8023 = 0x3b | |||
IFT_AFLANE8025 = 0x3c | |||
IFT_ARAP = 0x58 | |||
IFT_ARCNET = 0x23 | |||
IFT_ARCNETPLUS = 0x24 | |||
IFT_ASYNC = 0x54 | |||
IFT_ATM = 0x25 | |||
IFT_ATMDXI = 0x69 | |||
IFT_ATMFUNI = 0x6a | |||
IFT_ATMIMA = 0x6b | |||
IFT_ATMLOGICAL = 0x50 | |||
IFT_ATMRADIO = 0xbd | |||
IFT_ATMSUBINTERFACE = 0x86 | |||
IFT_ATMVCIENDPT = 0xc2 | |||
IFT_ATMVIRTUAL = 0x95 | |||
IFT_BGPPOLICYACCOUNTING = 0xa2 | |||
IFT_BSC = 0x53 | |||
IFT_CCTEMUL = 0x3d | |||
IFT_CEPT = 0x13 | |||
IFT_CES = 0x85 | |||
IFT_CHANNEL = 0x46 | |||
IFT_CNR = 0x55 | |||
IFT_COFFEE = 0x84 | |||
IFT_COMPOSITELINK = 0x9b | |||
IFT_DCN = 0x8d | |||
IFT_DIGITALPOWERLINE = 0x8a | |||
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba | |||
IFT_DLSW = 0x4a | |||
IFT_DOCSCABLEDOWNSTREAM = 0x80 | |||
IFT_DOCSCABLEMACLAYER = 0x7f | |||
IFT_DOCSCABLEUPSTREAM = 0x81 | |||
IFT_DS0 = 0x51 | |||
IFT_DS0BUNDLE = 0x52 | |||
IFT_DS1FDL = 0xaa | |||
IFT_DS3 = 0x1e | |||
IFT_DTM = 0x8c | |||
IFT_DVBASILN = 0xac | |||
IFT_DVBASIOUT = 0xad | |||
IFT_DVBRCCDOWNSTREAM = 0x93 | |||
IFT_DVBRCCMACLAYER = 0x92 | |||
IFT_DVBRCCUPSTREAM = 0x94 | |||
IFT_ENC = 0xf4 | |||
IFT_EON = 0x19 | |||
IFT_EPLRS = 0x57 | |||
IFT_ESCON = 0x49 | |||
IFT_ETHER = 0x6 | |||
IFT_FAITH = 0xf2 | |||
IFT_FAST = 0x7d | |||
IFT_FASTETHER = 0x3e | |||
IFT_FASTETHERFX = 0x45 | |||
IFT_FDDI = 0xf | |||
IFT_FIBRECHANNEL = 0x38 | |||
IFT_FRAMERELAYINTERCONNECT = 0x3a | |||
IFT_FRAMERELAYMPI = 0x5c | |||
IFT_FRDLCIENDPT = 0xc1 | |||
IFT_FRELAY = 0x20 | |||
IFT_FRELAYDCE = 0x2c | |||
IFT_FRF16MFRBUNDLE = 0xa3 | |||
IFT_FRFORWARD = 0x9e | |||
IFT_G703AT2MB = 0x43 | |||
IFT_G703AT64K = 0x42 | |||
IFT_GIF = 0xf0 | |||
IFT_GIGABITETHERNET = 0x75 | |||
IFT_GR303IDT = 0xb2 | |||
IFT_GR303RDT = 0xb1 | |||
IFT_H323GATEKEEPER = 0xa4 | |||
IFT_H323PROXY = 0xa5 | |||
IFT_HDH1822 = 0x3 | |||
IFT_HDLC = 0x76 | |||
IFT_HDSL2 = 0xa8 | |||
IFT_HIPERLAN2 = 0xb7 | |||
IFT_HIPPI = 0x2f | |||
IFT_HIPPIINTERFACE = 0x39 | |||
IFT_HOSTPAD = 0x5a | |||
IFT_HSSI = 0x2e | |||
IFT_HY = 0xe | |||
IFT_IBM370PARCHAN = 0x48 | |||
IFT_IDSL = 0x9a | |||
IFT_IEEE80211 = 0x47 | |||
IFT_IEEE80212 = 0x37 | |||
IFT_IEEE8023ADLAG = 0xa1 | |||
IFT_IFGSN = 0x91 | |||
IFT_IMT = 0xbe | |||
IFT_INTERLEAVE = 0x7c | |||
IFT_IP = 0x7e | |||
IFT_IPFORWARD = 0x8e | |||
IFT_IPOVERATM = 0x72 | |||
IFT_IPOVERCDLC = 0x6d | |||
IFT_IPOVERCLAW = 0x6e | |||
IFT_IPSWITCH = 0x4e | |||
IFT_IPXIP = 0xf9 | |||
IFT_ISDN = 0x3f | |||
IFT_ISDNBASIC = 0x14 | |||
IFT_ISDNPRIMARY = 0x15 | |||
IFT_ISDNS = 0x4b | |||
IFT_ISDNU = 0x4c | |||
IFT_ISO88022LLC = 0x29 | |||
IFT_ISO88023 = 0x7 | |||
IFT_ISO88024 = 0x8 | |||
IFT_ISO88025 = 0x9 | |||
IFT_ISO88025CRFPINT = 0x62 | |||
IFT_ISO88025DTR = 0x56 | |||
IFT_ISO88025FIBER = 0x73 | |||
IFT_ISO88026 = 0xa | |||
IFT_ISUP = 0xb3 | |||
IFT_L3IPXVLAN = 0x89 | |||
IFT_LAPB = 0x10 | |||
IFT_LAPD = 0x4d | |||
IFT_LAPF = 0x77 | |||
IFT_LOCALTALK = 0x2a | |||
IFT_LOOP = 0x18 | |||
IFT_MEDIAMAILOVERIP = 0x8b | |||
IFT_MFSIGLINK = 0xa7 | |||
IFT_MIOX25 = 0x26 | |||
IFT_MODEM = 0x30 | |||
IFT_MPC = 0x71 | |||
IFT_MPLS = 0xa6 | |||
IFT_MPLSTUNNEL = 0x96 | |||
IFT_MSDSL = 0x8f | |||
IFT_MVL = 0xbf | |||
IFT_MYRINET = 0x63 | |||
IFT_NFAS = 0xaf | |||
IFT_NSIP = 0x1b | |||
IFT_OPTICALCHANNEL = 0xc3 | |||
IFT_OPTICALTRANSPORT = 0xc4 | |||
IFT_OTHER = 0x1 | |||
IFT_P10 = 0xc | |||
IFT_P80 = 0xd | |||
IFT_PARA = 0x22 | |||
IFT_PFLOG = 0xf6 | |||
IFT_PFSYNC = 0xf7 | |||
IFT_PLC = 0xae | |||
IFT_POS = 0xab | |||
IFT_PPPMULTILINKBUNDLE = 0x6c | |||
IFT_PROPBWAP2MP = 0xb8 | |||
IFT_PROPCNLS = 0x59 | |||
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 | |||
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 | |||
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 | |||
IFT_PROPMUX = 0x36 | |||
IFT_PROPWIRELESSP2P = 0x9d | |||
IFT_PTPSERIAL = 0x16 | |||
IFT_PVC = 0xf1 | |||
IFT_QLLC = 0x44 | |||
IFT_RADIOMAC = 0xbc | |||
IFT_RADSL = 0x5f | |||
IFT_REACHDSL = 0xc0 | |||
IFT_RFC1483 = 0x9f | |||
IFT_RS232 = 0x21 | |||
IFT_RSRB = 0x4f | |||
IFT_SDLC = 0x11 | |||
IFT_SDSL = 0x60 | |||
IFT_SHDSL = 0xa9 | |||
IFT_SIP = 0x1f | |||
IFT_SLIP = 0x1c | |||
IFT_SMDSDXI = 0x2b | |||
IFT_SMDSICIP = 0x34 | |||
IFT_SONET = 0x27 | |||
IFT_SONETOVERHEADCHANNEL = 0xb9 | |||
IFT_SONETPATH = 0x32 | |||
IFT_SONETVT = 0x33 | |||
IFT_SRP = 0x97 | |||
IFT_SS7SIGLINK = 0x9c | |||
IFT_STACKTOSTACK = 0x6f | |||
IFT_STARLAN = 0xb | |||
IFT_STF = 0xd7 | |||
IFT_T1 = 0x12 | |||
IFT_TDLC = 0x74 | |||
IFT_TERMPAD = 0x5b | |||
IFT_TR008 = 0xb0 | |||
IFT_TRANSPHDLC = 0x7b | |||
IFT_TUNNEL = 0x83 | |||
IFT_ULTRA = 0x1d | |||
IFT_USB = 0xa0 | |||
IFT_V11 = 0x40 | |||
IFT_V35 = 0x2d | |||
IFT_V36 = 0x41 | |||
IFT_V37 = 0x78 | |||
IFT_VDSL = 0x61 | |||
IFT_VIRTUALIPADDRESS = 0x70 | |||
IFT_VOICEEM = 0x64 | |||
IFT_VOICEENCAP = 0x67 | |||
IFT_VOICEFXO = 0x65 | |||
IFT_VOICEFXS = 0x66 | |||
IFT_VOICEOVERATM = 0x98 | |||
IFT_VOICEOVERFRAMERELAY = 0x99 | |||
IFT_VOICEOVERIP = 0x68 | |||
IFT_X213 = 0x5d | |||
IFT_X25 = 0x5 | |||
IFT_X25DDN = 0x4 | |||
IFT_X25HUNTGROUP = 0x7a | |||
IFT_X25MLP = 0x79 | |||
IFT_X25PLE = 0x28 | |||
IFT_XETHER = 0x1a | |||
IPPROTO_MAXID = 0x34 | |||
IPV6_FAITH = 0x1d | |||
IPV6_MIN_MEMBERSHIPS = 0x1f | |||
IP_FAITH = 0x16 | |||
IP_MAX_SOURCE_FILTER = 0x400 | |||
IP_MIN_MEMBERSHIPS = 0x1f | |||
MAP_NORESERVE = 0x40 | |||
MAP_RENAME = 0x20 | |||
NET_RT_MAXID = 0x6 | |||
RTF_PRCLONING = 0x10000 | |||
RTM_OLDADD = 0x9 | |||
RTM_OLDDEL = 0xa | |||
RT_CACHING_CONTEXT = 0x1 | |||
RT_NORTREF = 0x2 | |||
SIOCADDRT = 0x8030720a | |||
SIOCALIFADDR = 0x8118691b | |||
SIOCDELRT = 0x8030720b | |||
SIOCDLIFADDR = 0x8118691d | |||
SIOCGLIFADDR = 0xc118691c | |||
SIOCGLIFPHYADDR = 0xc118694b | |||
SIOCSLIFPHYADDR = 0x8118694a | |||
) |
@@ -1,233 +0,0 @@ | |||
// Copyright 2017 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. | |||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep | |||
// them here for backwards compatibility. | |||
package unix | |||
const ( | |||
DLT_HHDLC = 0x79 | |||
IFF_SMART = 0x20 | |||
IFT_1822 = 0x2 | |||
IFT_A12MPPSWITCH = 0x82 | |||
IFT_AAL2 = 0xbb | |||
IFT_AAL5 = 0x31 | |||
IFT_ADSL = 0x5e | |||
IFT_AFLANE8023 = 0x3b | |||
IFT_AFLANE8025 = 0x3c | |||
IFT_ARAP = 0x58 | |||
IFT_ARCNET = 0x23 | |||
IFT_ARCNETPLUS = 0x24 | |||
IFT_ASYNC = 0x54 | |||
IFT_ATM = 0x25 | |||
IFT_ATMDXI = 0x69 | |||
IFT_ATMFUNI = 0x6a | |||
IFT_ATMIMA = 0x6b | |||
IFT_ATMLOGICAL = 0x50 | |||
IFT_ATMRADIO = 0xbd | |||
IFT_ATMSUBINTERFACE = 0x86 | |||
IFT_ATMVCIENDPT = 0xc2 | |||
IFT_ATMVIRTUAL = 0x95 | |||
IFT_BGPPOLICYACCOUNTING = 0xa2 | |||
IFT_BSC = 0x53 | |||
IFT_CCTEMUL = 0x3d | |||
IFT_CEPT = 0x13 | |||
IFT_CES = 0x85 | |||
IFT_CHANNEL = 0x46 | |||
IFT_CNR = 0x55 | |||
IFT_COFFEE = 0x84 | |||
IFT_COMPOSITELINK = 0x9b | |||
IFT_DCN = 0x8d | |||
IFT_DIGITALPOWERLINE = 0x8a | |||
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba | |||
IFT_DLSW = 0x4a | |||
IFT_DOCSCABLEDOWNSTREAM = 0x80 | |||
IFT_DOCSCABLEMACLAYER = 0x7f | |||
IFT_DOCSCABLEUPSTREAM = 0x81 | |||
IFT_DS0 = 0x51 | |||
IFT_DS0BUNDLE = 0x52 | |||
IFT_DS1FDL = 0xaa | |||
IFT_DS3 = 0x1e | |||
IFT_DTM = 0x8c | |||
IFT_DVBASILN = 0xac | |||
IFT_DVBASIOUT = 0xad | |||
IFT_DVBRCCDOWNSTREAM = 0x93 | |||
IFT_DVBRCCMACLAYER = 0x92 | |||
IFT_DVBRCCUPSTREAM = 0x94 | |||
IFT_ENC = 0xf4 | |||
IFT_EON = 0x19 | |||
IFT_EPLRS = 0x57 | |||
IFT_ESCON = 0x49 | |||
IFT_ETHER = 0x6 | |||
IFT_FAITH = 0xf2 | |||
IFT_FAST = 0x7d | |||
IFT_FASTETHER = 0x3e | |||
IFT_FASTETHERFX = 0x45 | |||
IFT_FDDI = 0xf | |||
IFT_FIBRECHANNEL = 0x38 | |||
IFT_FRAMERELAYINTERCONNECT = 0x3a | |||
IFT_FRAMERELAYMPI = 0x5c | |||
IFT_FRDLCIENDPT = 0xc1 | |||
IFT_FRELAY = 0x20 | |||
IFT_FRELAYDCE = 0x2c | |||
IFT_FRF16MFRBUNDLE = 0xa3 | |||
IFT_FRFORWARD = 0x9e | |||
IFT_G703AT2MB = 0x43 | |||
IFT_G703AT64K = 0x42 | |||
IFT_GIF = 0xf0 | |||
IFT_GIGABITETHERNET = 0x75 | |||
IFT_GR303IDT = 0xb2 | |||
IFT_GR303RDT = 0xb1 | |||
IFT_H323GATEKEEPER = 0xa4 | |||
IFT_H323PROXY = 0xa5 | |||
IFT_HDH1822 = 0x3 | |||
IFT_HDLC = 0x76 | |||
IFT_HDSL2 = 0xa8 | |||
IFT_HIPERLAN2 = 0xb7 | |||
IFT_HIPPI = 0x2f | |||
IFT_HIPPIINTERFACE = 0x39 | |||
IFT_HOSTPAD = 0x5a | |||
IFT_HSSI = 0x2e | |||
IFT_HY = 0xe | |||
IFT_IBM370PARCHAN = 0x48 | |||
IFT_IDSL = 0x9a | |||
IFT_IEEE80211 = 0x47 | |||
IFT_IEEE80212 = 0x37 | |||
IFT_IEEE8023ADLAG = 0xa1 | |||
IFT_IFGSN = 0x91 | |||
IFT_IMT = 0xbe | |||
IFT_INTERLEAVE = 0x7c | |||
IFT_IP = 0x7e | |||
IFT_IPFORWARD = 0x8e | |||
IFT_IPOVERATM = 0x72 | |||
IFT_IPOVERCDLC = 0x6d | |||
IFT_IPOVERCLAW = 0x6e | |||
IFT_IPSWITCH = 0x4e | |||
IFT_IPXIP = 0xf9 | |||
IFT_ISDN = 0x3f | |||
IFT_ISDNBASIC = 0x14 | |||
IFT_ISDNPRIMARY = 0x15 | |||
IFT_ISDNS = 0x4b | |||
IFT_ISDNU = 0x4c | |||
IFT_ISO88022LLC = 0x29 | |||
IFT_ISO88023 = 0x7 | |||
IFT_ISO88024 = 0x8 | |||
IFT_ISO88025 = 0x9 | |||
IFT_ISO88025CRFPINT = 0x62 | |||
IFT_ISO88025DTR = 0x56 | |||
IFT_ISO88025FIBER = 0x73 | |||
IFT_ISO88026 = 0xa | |||
IFT_ISUP = 0xb3 | |||
IFT_L3IPXVLAN = 0x89 | |||
IFT_LAPB = 0x10 | |||
IFT_LAPD = 0x4d | |||
IFT_LAPF = 0x77 | |||
IFT_LOCALTALK = 0x2a | |||
IFT_LOOP = 0x18 | |||
IFT_MEDIAMAILOVERIP = 0x8b | |||
IFT_MFSIGLINK = 0xa7 | |||
IFT_MIOX25 = 0x26 | |||
IFT_MODEM = 0x30 | |||
IFT_MPC = 0x71 | |||
IFT_MPLS = 0xa6 | |||
IFT_MPLSTUNNEL = 0x96 | |||
IFT_MSDSL = 0x8f | |||
IFT_MVL = 0xbf | |||
IFT_MYRINET = 0x63 | |||
IFT_NFAS = 0xaf | |||
IFT_NSIP = 0x1b | |||
IFT_OPTICALCHANNEL = 0xc3 | |||
IFT_OPTICALTRANSPORT = 0xc4 | |||
IFT_OTHER = 0x1 | |||
IFT_P10 = 0xc | |||
IFT_P80 = 0xd | |||
IFT_PARA = 0x22 | |||
IFT_PFLOG = 0xf6 | |||
IFT_PFSYNC = 0xf7 | |||
IFT_PLC = 0xae | |||
IFT_POS = 0xab | |||
IFT_PPPMULTILINKBUNDLE = 0x6c | |||
IFT_PROPBWAP2MP = 0xb8 | |||
IFT_PROPCNLS = 0x59 | |||
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 | |||
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 | |||
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 | |||
IFT_PROPMUX = 0x36 | |||
IFT_PROPWIRELESSP2P = 0x9d | |||
IFT_PTPSERIAL = 0x16 | |||
IFT_PVC = 0xf1 | |||
IFT_QLLC = 0x44 | |||
IFT_RADIOMAC = 0xbc | |||
IFT_RADSL = 0x5f | |||
IFT_REACHDSL = 0xc0 | |||
IFT_RFC1483 = 0x9f | |||
IFT_RS232 = 0x21 | |||
IFT_RSRB = 0x4f | |||
IFT_SDLC = 0x11 | |||
IFT_SDSL = 0x60 | |||
IFT_SHDSL = 0xa9 | |||
IFT_SIP = 0x1f | |||
IFT_SLIP = 0x1c | |||
IFT_SMDSDXI = 0x2b | |||
IFT_SMDSICIP = 0x34 | |||
IFT_SONET = 0x27 | |||
IFT_SONETOVERHEADCHANNEL = 0xb9 | |||
IFT_SONETPATH = 0x32 | |||
IFT_SONETVT = 0x33 | |||
IFT_SRP = 0x97 | |||
IFT_SS7SIGLINK = 0x9c | |||
IFT_STACKTOSTACK = 0x6f | |||
IFT_STARLAN = 0xb | |||
IFT_STF = 0xd7 | |||
IFT_T1 = 0x12 | |||
IFT_TDLC = 0x74 | |||
IFT_TERMPAD = 0x5b | |||
IFT_TR008 = 0xb0 | |||
IFT_TRANSPHDLC = 0x7b | |||
IFT_TUNNEL = 0x83 | |||
IFT_ULTRA = 0x1d | |||
IFT_USB = 0xa0 | |||
IFT_V11 = 0x40 | |||
IFT_V35 = 0x2d | |||
IFT_V36 = 0x41 | |||
IFT_V37 = 0x78 | |||
IFT_VDSL = 0x61 | |||
IFT_VIRTUALIPADDRESS = 0x70 | |||
IFT_VOICEEM = 0x64 | |||
IFT_VOICEENCAP = 0x67 | |||
IFT_VOICEFXO = 0x65 | |||
IFT_VOICEFXS = 0x66 | |||
IFT_VOICEOVERATM = 0x98 | |||
IFT_VOICEOVERFRAMERELAY = 0x99 | |||
IFT_VOICEOVERIP = 0x68 | |||
IFT_X213 = 0x5d | |||
IFT_X25 = 0x5 | |||
IFT_X25DDN = 0x4 | |||
IFT_X25HUNTGROUP = 0x7a | |||
IFT_X25MLP = 0x79 | |||
IFT_X25PLE = 0x28 | |||
IFT_XETHER = 0x1a | |||
IPPROTO_MAXID = 0x34 | |||
IPV6_FAITH = 0x1d | |||
IPV6_MIN_MEMBERSHIPS = 0x1f | |||
IP_FAITH = 0x16 | |||
IP_MAX_SOURCE_FILTER = 0x400 | |||
IP_MIN_MEMBERSHIPS = 0x1f | |||
MAP_NORESERVE = 0x40 | |||
MAP_RENAME = 0x20 | |||
NET_RT_MAXID = 0x6 | |||
RTF_PRCLONING = 0x10000 | |||
RTM_OLDADD = 0x9 | |||
RTM_OLDDEL = 0xa | |||
RT_CACHING_CONTEXT = 0x1 | |||
RT_NORTREF = 0x2 | |||
SIOCADDRT = 0x8040720a | |||
SIOCALIFADDR = 0x8118691b | |||
SIOCDELRT = 0x8040720b | |||
SIOCDLIFADDR = 0x8118691d | |||
SIOCGLIFADDR = 0xc118691c | |||
SIOCGLIFPHYADDR = 0xc118694b | |||
SIOCSLIFPHYADDR = 0x8118694a | |||
) |
@@ -1,226 +0,0 @@ | |||
// Copyright 2017 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. | |||
package unix | |||
const ( | |||
IFT_1822 = 0x2 | |||
IFT_A12MPPSWITCH = 0x82 | |||
IFT_AAL2 = 0xbb | |||
IFT_AAL5 = 0x31 | |||
IFT_ADSL = 0x5e | |||
IFT_AFLANE8023 = 0x3b | |||
IFT_AFLANE8025 = 0x3c | |||
IFT_ARAP = 0x58 | |||
IFT_ARCNET = 0x23 | |||
IFT_ARCNETPLUS = 0x24 | |||
IFT_ASYNC = 0x54 | |||
IFT_ATM = 0x25 | |||
IFT_ATMDXI = 0x69 | |||
IFT_ATMFUNI = 0x6a | |||
IFT_ATMIMA = 0x6b | |||
IFT_ATMLOGICAL = 0x50 | |||
IFT_ATMRADIO = 0xbd | |||
IFT_ATMSUBINTERFACE = 0x86 | |||
IFT_ATMVCIENDPT = 0xc2 | |||
IFT_ATMVIRTUAL = 0x95 | |||
IFT_BGPPOLICYACCOUNTING = 0xa2 | |||
IFT_BSC = 0x53 | |||
IFT_CCTEMUL = 0x3d | |||
IFT_CEPT = 0x13 | |||
IFT_CES = 0x85 | |||
IFT_CHANNEL = 0x46 | |||
IFT_CNR = 0x55 | |||
IFT_COFFEE = 0x84 | |||
IFT_COMPOSITELINK = 0x9b | |||
IFT_DCN = 0x8d | |||
IFT_DIGITALPOWERLINE = 0x8a | |||
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba | |||
IFT_DLSW = 0x4a | |||
IFT_DOCSCABLEDOWNSTREAM = 0x80 | |||
IFT_DOCSCABLEMACLAYER = 0x7f | |||
IFT_DOCSCABLEUPSTREAM = 0x81 | |||
IFT_DS0 = 0x51 | |||
IFT_DS0BUNDLE = 0x52 | |||
IFT_DS1FDL = 0xaa | |||
IFT_DS3 = 0x1e | |||
IFT_DTM = 0x8c | |||
IFT_DVBASILN = 0xac | |||
IFT_DVBASIOUT = 0xad | |||
IFT_DVBRCCDOWNSTREAM = 0x93 | |||
IFT_DVBRCCMACLAYER = 0x92 | |||
IFT_DVBRCCUPSTREAM = 0x94 | |||
IFT_ENC = 0xf4 | |||
IFT_EON = 0x19 | |||
IFT_EPLRS = 0x57 | |||
IFT_ESCON = 0x49 | |||
IFT_ETHER = 0x6 | |||
IFT_FAST = 0x7d | |||
IFT_FASTETHER = 0x3e | |||
IFT_FASTETHERFX = 0x45 | |||
IFT_FDDI = 0xf | |||
IFT_FIBRECHANNEL = 0x38 | |||
IFT_FRAMERELAYINTERCONNECT = 0x3a | |||
IFT_FRAMERELAYMPI = 0x5c | |||
IFT_FRDLCIENDPT = 0xc1 | |||
IFT_FRELAY = 0x20 | |||
IFT_FRELAYDCE = 0x2c | |||
IFT_FRF16MFRBUNDLE = 0xa3 | |||
IFT_FRFORWARD = 0x9e | |||
IFT_G703AT2MB = 0x43 | |||
IFT_G703AT64K = 0x42 | |||
IFT_GIF = 0xf0 | |||
IFT_GIGABITETHERNET = 0x75 | |||
IFT_GR303IDT = 0xb2 | |||
IFT_GR303RDT = 0xb1 | |||
IFT_H323GATEKEEPER = 0xa4 | |||
IFT_H323PROXY = 0xa5 | |||
IFT_HDH1822 = 0x3 | |||
IFT_HDLC = 0x76 | |||
IFT_HDSL2 = 0xa8 | |||
IFT_HIPERLAN2 = 0xb7 | |||
IFT_HIPPI = 0x2f | |||
IFT_HIPPIINTERFACE = 0x39 | |||
IFT_HOSTPAD = 0x5a | |||
IFT_HSSI = 0x2e | |||
IFT_HY = 0xe | |||
IFT_IBM370PARCHAN = 0x48 | |||
IFT_IDSL = 0x9a | |||
IFT_IEEE80211 = 0x47 | |||
IFT_IEEE80212 = 0x37 | |||
IFT_IEEE8023ADLAG = 0xa1 | |||
IFT_IFGSN = 0x91 | |||
IFT_IMT = 0xbe | |||
IFT_INTERLEAVE = 0x7c | |||
IFT_IP = 0x7e | |||
IFT_IPFORWARD = 0x8e | |||
IFT_IPOVERATM = 0x72 | |||
IFT_IPOVERCDLC = 0x6d | |||
IFT_IPOVERCLAW = 0x6e | |||
IFT_IPSWITCH = 0x4e | |||
IFT_ISDN = 0x3f | |||
IFT_ISDNBASIC = 0x14 | |||
IFT_ISDNPRIMARY = 0x15 | |||
IFT_ISDNS = 0x4b | |||
IFT_ISDNU = 0x4c | |||
IFT_ISO88022LLC = 0x29 | |||
IFT_ISO88023 = 0x7 | |||
IFT_ISO88024 = 0x8 | |||
IFT_ISO88025 = 0x9 | |||
IFT_ISO88025CRFPINT = 0x62 | |||
IFT_ISO88025DTR = 0x56 | |||
IFT_ISO88025FIBER = 0x73 | |||
IFT_ISO88026 = 0xa | |||
IFT_ISUP = 0xb3 | |||
IFT_L3IPXVLAN = 0x89 | |||
IFT_LAPB = 0x10 | |||
IFT_LAPD = 0x4d | |||
IFT_LAPF = 0x77 | |||
IFT_LOCALTALK = 0x2a | |||
IFT_LOOP = 0x18 | |||
IFT_MEDIAMAILOVERIP = 0x8b | |||
IFT_MFSIGLINK = 0xa7 | |||
IFT_MIOX25 = 0x26 | |||
IFT_MODEM = 0x30 | |||
IFT_MPC = 0x71 | |||
IFT_MPLS = 0xa6 | |||
IFT_MPLSTUNNEL = 0x96 | |||
IFT_MSDSL = 0x8f | |||
IFT_MVL = 0xbf | |||
IFT_MYRINET = 0x63 | |||
IFT_NFAS = 0xaf | |||
IFT_NSIP = 0x1b | |||
IFT_OPTICALCHANNEL = 0xc3 | |||
IFT_OPTICALTRANSPORT = 0xc4 | |||
IFT_OTHER = 0x1 | |||
IFT_P10 = 0xc | |||
IFT_P80 = 0xd | |||
IFT_PARA = 0x22 | |||
IFT_PFLOG = 0xf6 | |||
IFT_PFSYNC = 0xf7 | |||
IFT_PLC = 0xae | |||
IFT_POS = 0xab | |||
IFT_PPPMULTILINKBUNDLE = 0x6c | |||
IFT_PROPBWAP2MP = 0xb8 | |||
IFT_PROPCNLS = 0x59 | |||
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 | |||
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 | |||
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 | |||
IFT_PROPMUX = 0x36 | |||
IFT_PROPWIRELESSP2P = 0x9d | |||
IFT_PTPSERIAL = 0x16 | |||
IFT_PVC = 0xf1 | |||
IFT_QLLC = 0x44 | |||
IFT_RADIOMAC = 0xbc | |||
IFT_RADSL = 0x5f | |||
IFT_REACHDSL = 0xc0 | |||
IFT_RFC1483 = 0x9f | |||
IFT_RS232 = 0x21 | |||
IFT_RSRB = 0x4f | |||
IFT_SDLC = 0x11 | |||
IFT_SDSL = 0x60 | |||
IFT_SHDSL = 0xa9 | |||
IFT_SIP = 0x1f | |||
IFT_SLIP = 0x1c | |||
IFT_SMDSDXI = 0x2b | |||
IFT_SMDSICIP = 0x34 | |||
IFT_SONET = 0x27 | |||
IFT_SONETOVERHEADCHANNEL = 0xb9 | |||
IFT_SONETPATH = 0x32 | |||
IFT_SONETVT = 0x33 | |||
IFT_SRP = 0x97 | |||
IFT_SS7SIGLINK = 0x9c | |||
IFT_STACKTOSTACK = 0x6f | |||
IFT_STARLAN = 0xb | |||
IFT_STF = 0xd7 | |||
IFT_T1 = 0x12 | |||
IFT_TDLC = 0x74 | |||
IFT_TERMPAD = 0x5b | |||
IFT_TR008 = 0xb0 | |||
IFT_TRANSPHDLC = 0x7b | |||
IFT_TUNNEL = 0x83 | |||
IFT_ULTRA = 0x1d | |||
IFT_USB = 0xa0 | |||
IFT_V11 = 0x40 | |||
IFT_V35 = 0x2d | |||
IFT_V36 = 0x41 | |||
IFT_V37 = 0x78 | |||
IFT_VDSL = 0x61 | |||
IFT_VIRTUALIPADDRESS = 0x70 | |||
IFT_VOICEEM = 0x64 | |||
IFT_VOICEENCAP = 0x67 | |||
IFT_VOICEFXO = 0x65 | |||
IFT_VOICEFXS = 0x66 | |||
IFT_VOICEOVERATM = 0x98 | |||
IFT_VOICEOVERFRAMERELAY = 0x99 | |||
IFT_VOICEOVERIP = 0x68 | |||
IFT_X213 = 0x5d | |||
IFT_X25 = 0x5 | |||
IFT_X25DDN = 0x4 | |||
IFT_X25HUNTGROUP = 0x7a | |||
IFT_X25MLP = 0x79 | |||
IFT_X25PLE = 0x28 | |||
IFT_XETHER = 0x1a | |||
// missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go | |||
IFF_SMART = 0x20 | |||
IFT_FAITH = 0xf2 | |||
IFT_IPXIP = 0xf9 | |||
IPPROTO_MAXID = 0x34 | |||
IPV6_FAITH = 0x1d | |||
IP_FAITH = 0x16 | |||
MAP_NORESERVE = 0x40 | |||
MAP_RENAME = 0x20 | |||
NET_RT_MAXID = 0x6 | |||
RTF_PRCLONING = 0x10000 | |||
RTM_OLDADD = 0x9 | |||
RTM_OLDDEL = 0xa | |||
SIOCADDRT = 0x8030720a | |||
SIOCALIFADDR = 0x8118691b | |||
SIOCDELRT = 0x8030720b | |||
SIOCDLIFADDR = 0x8118691d | |||
SIOCGLIFADDR = 0xc118691c | |||
SIOCGLIFPHYADDR = 0xc118694b | |||
SIOCSLIFPHYADDR = 0x8118694a | |||
) |
@@ -1,17 +0,0 @@ | |||
// Copyright 2020 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. | |||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep | |||
// them here for backwards compatibility. | |||
package unix | |||
const ( | |||
DLT_HHDLC = 0x79 | |||
IPV6_MIN_MEMBERSHIPS = 0x1f | |||
IP_MAX_SOURCE_FILTER = 0x400 | |||
IP_MIN_MEMBERSHIPS = 0x1f | |||
RT_CACHING_CONTEXT = 0x1 | |||
RT_NORTREF = 0x2 | |||
) |
@@ -8,7 +8,6 @@ | |||
package unix | |||
import ( | |||
"bytes" | |||
"unsafe" | |||
) | |||
@@ -45,13 +44,7 @@ func NewIfreq(name string) (*Ifreq, error) { | |||
// Name returns the interface name associated with the Ifreq. | |||
func (ifr *Ifreq) Name() string { | |||
// BytePtrToString requires a NULL terminator or the program may crash. If | |||
// one is not present, just return the empty string. | |||
if !bytes.Contains(ifr.raw.Ifrn[:], []byte{0x00}) { | |||
return "" | |||
} | |||
return BytePtrToString(&ifr.raw.Ifrn[0]) | |||
return ByteSliceToString(ifr.raw.Ifrn[:]) | |||
} | |||
// According to netdevice(7), only AF_INET addresses are returned for numerous | |||
@@ -194,3 +194,26 @@ func ioctlIfreqData(fd int, req uint, value *ifreqData) error { | |||
// identical so pass *IfreqData directly. | |||
return ioctlPtr(fd, req, unsafe.Pointer(value)) | |||
} | |||
// IoctlKCMClone attaches a new file descriptor to a multiplexor by cloning an | |||
// existing KCM socket, returning a structure containing the file descriptor of | |||
// the new socket. | |||
func IoctlKCMClone(fd int) (*KCMClone, error) { | |||
var info KCMClone | |||
if err := ioctlPtr(fd, SIOCKCMCLONE, unsafe.Pointer(&info)); err != nil { | |||
return nil, err | |||
} | |||
return &info, nil | |||
} | |||
// IoctlKCMAttach attaches a TCP socket and associated BPF program file | |||
// descriptor to a multiplexor. | |||
func IoctlKCMAttach(fd int, info KCMAttach) error { | |||
return ioctlPtr(fd, SIOCKCMATTACH, unsafe.Pointer(&info)) | |||
} | |||
// IoctlKCMUnattach unattaches a TCP socket file descriptor from a multiplexor. | |||
func IoctlKCMUnattach(fd int, info KCMUnattach) error { | |||
return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info)) | |||
} |
@@ -89,25 +89,30 @@ dragonfly_amd64) | |||
freebsd_386) | |||
mkerrors="$mkerrors -m32" | |||
mksyscall="go run mksyscall.go -l32" | |||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" | |||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" | |||
mktypes="GOARCH=$GOARCH go tool cgo -godefs" | |||
;; | |||
freebsd_amd64) | |||
mkerrors="$mkerrors -m64" | |||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" | |||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" | |||
mktypes="GOARCH=$GOARCH go tool cgo -godefs" | |||
;; | |||
freebsd_arm) | |||
mkerrors="$mkerrors" | |||
mksyscall="go run mksyscall.go -l32 -arm" | |||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" | |||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" | |||
# Let the type of C char be signed for making the bare syscall | |||
# API consistent across platforms. | |||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" | |||
;; | |||
freebsd_arm64) | |||
mkerrors="$mkerrors -m64" | |||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" | |||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" | |||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" | |||
;; | |||
freebsd_riscv64) | |||
mkerrors="$mkerrors -m64" | |||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" | |||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" | |||
;; | |||
netbsd_386) | |||
@@ -128,6 +128,7 @@ includes_FreeBSD=' | |||
#include <sys/mount.h> | |||
#include <sys/wait.h> | |||
#include <sys/ioctl.h> | |||
#include <sys/ptrace.h> | |||
#include <net/bpf.h> | |||
#include <net/if.h> | |||
#include <net/if_types.h> | |||
@@ -202,9 +203,11 @@ struct ltchars { | |||
#include <sys/timerfd.h> | |||
#include <sys/uio.h> | |||
#include <sys/xattr.h> | |||
#include <linux/audit.h> | |||
#include <linux/bpf.h> | |||
#include <linux/can.h> | |||
#include <linux/can/error.h> | |||
#include <linux/can/netlink.h> | |||
#include <linux/can/raw.h> | |||
#include <linux/capability.h> | |||
#include <linux/cryptouser.h> | |||
@@ -214,6 +217,7 @@ struct ltchars { | |||
#include <linux/ethtool_netlink.h> | |||
#include <linux/falloc.h> | |||
#include <linux/fanotify.h> | |||
#include <linux/fib_rules.h> | |||
#include <linux/filter.h> | |||
#include <linux/fs.h> | |||
#include <linux/fscrypt.h> | |||
@@ -231,6 +235,7 @@ struct ltchars { | |||
#include <linux/if_packet.h> | |||
#include <linux/if_xdp.h> | |||
#include <linux/input.h> | |||
#include <linux/kcm.h> | |||
#include <linux/kexec.h> | |||
#include <linux/keyctl.h> | |||
#include <linux/landlock.h> | |||
@@ -292,6 +297,10 @@ struct ltchars { | |||
#define SOL_NETLINK 270 | |||
#endif | |||
#ifndef SOL_SMC | |||
#define SOL_SMC 286 | |||
#endif | |||
#ifdef SOL_BLUETOOTH | |||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h | |||
// but it is already in bluetooth_linux.go | |||
@@ -503,6 +512,7 @@ ccflags="$@" | |||
$2 ~ /^O?XTABS$/ || | |||
$2 ~ /^TC[IO](ON|OFF)$/ || | |||
$2 ~ /^IN_/ || | |||
$2 ~ /^KCM/ || | |||
$2 ~ /^LANDLOCK_/ || | |||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ || | |||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ || | |||
@@ -525,7 +535,7 @@ ccflags="$@" | |||
$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ || | |||
$2 ~ /^NS_GET_/ || | |||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || | |||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ || | |||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|PIOD|TFD)_/ || | |||
$2 ~ /^KEXEC_/ || | |||
$2 ~ /^LINUX_REBOOT_CMD_/ || | |||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || | |||
@@ -549,6 +559,7 @@ ccflags="$@" | |||
$2 ~ /^CLONE_[A-Z_]+/ || | |||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ && | |||
$2 ~ /^(BPF|DLT)_/ || | |||
$2 ~ /^AUDIT_/ || | |||
$2 ~ /^(CLOCK|TIMER)_/ || | |||
$2 ~ /^CAN_/ || | |||
$2 ~ /^CAP_/ || | |||
@@ -571,7 +582,6 @@ ccflags="$@" | |||
$2 ~ /^SEEK_/ || | |||
$2 ~ /^SPLICE_/ || | |||
$2 ~ /^SYNC_FILE_RANGE_/ || | |||
$2 !~ /^AUDIT_RECORD_MAGIC/ && | |||
$2 !~ /IOC_MAGIC/ && | |||
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ || | |||
$2 ~ /^(VM|VMADDR)_/ || | |||
@@ -597,8 +607,10 @@ ccflags="$@" | |||
$2 ~ /^DEVLINK_/ || | |||
$2 ~ /^ETHTOOL_/ || | |||
$2 ~ /^LWTUNNEL_IP/ || | |||
$2 ~ /^ITIMER_/ || | |||
$2 !~ "WMESGLEN" && | |||
$2 ~ /^W[A-Z0-9]+$/ || | |||
$2 ~ /^P_/ || | |||
$2 ~/^PPPIOC/ || | |||
$2 ~ /^FAN_|FANOTIFY_/ || | |||
$2 == "HID_MAX_DESCRIPTOR_SIZE" || | |||
@@ -608,6 +620,7 @@ ccflags="$@" | |||
$2 ~ /^OTP/ || | |||
$2 ~ /^MEM/ || | |||
$2 ~ /^WG/ || | |||
$2 ~ /^FIB_RULE_/ || | |||
$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)} | |||
@@ -37,6 +37,7 @@ func Creat(path string, mode uint32) (fd int, err error) { | |||
} | |||
//sys utimes(path string, times *[2]Timeval) (err error) | |||
func Utimes(path string, tv []Timeval) error { | |||
if len(tv) != 2 { | |||
return EINVAL | |||
@@ -45,6 +46,7 @@ func Utimes(path string, tv []Timeval) error { | |||
} | |||
//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) | |||
func UtimesNano(path string, ts []Timespec) error { | |||
if len(ts) != 2 { | |||
return EINVAL | |||
@@ -215,20 +217,63 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { | |||
return | |||
} | |||
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { | |||
// Recvmsg not implemented on AIX | |||
sa := new(SockaddrUnix) | |||
return -1, -1, -1, sa, ENOSYS | |||
} | |||
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { | |||
_, err = SendmsgN(fd, p, oob, to, flags) | |||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { | |||
var msg Msghdr | |||
msg.Name = (*byte)(unsafe.Pointer(rsa)) | |||
msg.Namelen = uint32(SizeofSockaddrAny) | |||
var dummy byte | |||
if len(oob) > 0 { | |||
// receive at least one normal byte | |||
if emptyIovecs(iov) { | |||
var iova [1]Iovec | |||
iova[0].Base = &dummy | |||
iova[0].SetLen(1) | |||
iov = iova[:] | |||
} | |||
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) | |||
msg.SetControllen(len(oob)) | |||
} | |||
if len(iov) > 0 { | |||
msg.Iov = &iov[0] | |||
msg.SetIovlen(len(iov)) | |||
} | |||
if n, err = recvmsg(fd, &msg, flags); n == -1 { | |||
return | |||
} | |||
oobn = int(msg.Controllen) | |||
recvflags = int(msg.Flags) | |||
return | |||
} | |||
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { | |||
// SendmsgN not implemented on AIX | |||
return -1, ENOSYS | |||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { | |||
var msg Msghdr | |||
msg.Name = (*byte)(unsafe.Pointer(ptr)) | |||
msg.Namelen = uint32(salen) | |||
var dummy byte | |||
var empty bool | |||
if len(oob) > 0 { | |||
// send at least one normal byte | |||
empty = emptyIovecs(iov) | |||
if empty { | |||
var iova [1]Iovec | |||
iova[0].Base = &dummy | |||
iova[0].SetLen(1) | |||
iov = iova[:] | |||
} | |||
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) | |||
msg.SetControllen(len(oob)) | |||
} | |||
if len(iov) > 0 { | |||
msg.Iov = &iov[0] | |||
msg.SetIovlen(len(iov)) | |||
} | |||
if n, err = sendmsg(fd, &msg, flags); err != nil { | |||
return 0, err | |||
} | |||
if len(oob) > 0 && empty { | |||
n = 0 | |||
} | |||
return n, nil | |||
} | |||
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { | |||
@@ -306,11 +351,13 @@ func direntNamlen(buf []byte) (uint64, bool) { | |||
} | |||
//sys getdirent(fd int, buf []byte) (n int, err error) | |||
func Getdents(fd int, buf []byte) (n int, err error) { | |||
return getdirent(fd, buf) | |||
} | |||
//sys wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error) | |||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { | |||
var status _C_int | |||
var r Pid_t | |||
@@ -378,6 +425,7 @@ func (w WaitStatus) TrapCause() int { return -1 } | |||
//sys fcntl(fd int, cmd int, arg int) (val int, err error) | |||
//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range | |||
func Fsync(fd int) error { | |||
return fsyncRange(fd, O_SYNC, 0, 0) | |||
} | |||
@@ -458,8 +506,8 @@ func Fsync(fd int) error { | |||
//sys Listen(s int, n int) (err error) | |||
//sys lstat(path string, stat *Stat_t) (err error) | |||
//sys Pause() (err error) | |||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64 | |||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64 | |||
//sys pread(fd int, p []byte, offset int64) (n int, err error) = pread64 | |||
//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64 | |||
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) | |||
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) | |||
//sysnb Setregid(rgid int, egid int) (err error) | |||
@@ -542,6 +590,7 @@ func Poll(fds []PollFd, timeout int) (n int, err error) { | |||
//sys Getsystemcfg(label int) (n uint64) | |||
//sys umount(target string) (err error) | |||
func Unmount(target string, flags int) (err error) { | |||
if flags != 0 { | |||
// AIX doesn't have any flags for umount. | |||
@@ -325,80 +325,62 @@ func GetsockoptString(fd, level, opt int) (string, error) { | |||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) | |||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) | |||
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { | |||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { | |||
var msg Msghdr | |||
var rsa RawSockaddrAny | |||
msg.Name = (*byte)(unsafe.Pointer(&rsa)) | |||
msg.Name = (*byte)(unsafe.Pointer(rsa)) | |||
msg.Namelen = uint32(SizeofSockaddrAny) | |||
var iov Iovec | |||
if len(p) > 0 { | |||
iov.Base = (*byte)(unsafe.Pointer(&p[0])) | |||
iov.SetLen(len(p)) | |||
} | |||
var dummy byte | |||
if len(oob) > 0 { | |||
// receive at least one normal byte | |||
if len(p) == 0 { | |||
iov.Base = &dummy | |||
iov.SetLen(1) | |||
if emptyIovecs(iov) { | |||
var iova [1]Iovec | |||
iova[0].Base = &dummy | |||
iova[0].SetLen(1) | |||
iov = iova[:] | |||
} | |||
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) | |||
msg.SetControllen(len(oob)) | |||
} | |||
msg.Iov = &iov | |||
msg.Iovlen = 1 | |||
if len(iov) > 0 { | |||
msg.Iov = &iov[0] | |||
msg.SetIovlen(len(iov)) | |||
} | |||
if n, err = recvmsg(fd, &msg, flags); err != nil { | |||
return | |||
} | |||
oobn = int(msg.Controllen) | |||
recvflags = int(msg.Flags) | |||
// source address is only specified if the socket is unconnected | |||
if rsa.Addr.Family != AF_UNSPEC { | |||
from, err = anyToSockaddr(fd, &rsa) | |||
} | |||
return | |||
} | |||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) | |||
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { | |||
_, err = SendmsgN(fd, p, oob, to, flags) | |||
return | |||
} | |||
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { | |||
var ptr unsafe.Pointer | |||
var salen _Socklen | |||
if to != nil { | |||
ptr, salen, err = to.sockaddr() | |||
if err != nil { | |||
return 0, err | |||
} | |||
} | |||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { | |||
var msg Msghdr | |||
msg.Name = (*byte)(unsafe.Pointer(ptr)) | |||
msg.Namelen = uint32(salen) | |||
var iov Iovec | |||
if len(p) > 0 { | |||
iov.Base = (*byte)(unsafe.Pointer(&p[0])) | |||
iov.SetLen(len(p)) | |||
} | |||
var dummy byte | |||
var empty bool | |||
if len(oob) > 0 { | |||
// send at least one normal byte | |||
if len(p) == 0 { | |||
iov.Base = &dummy | |||
iov.SetLen(1) | |||
empty = emptyIovecs(iov) | |||
if empty { | |||
var iova [1]Iovec | |||
iova[0].Base = &dummy | |||
iova[0].SetLen(1) | |||
iov = iova[:] | |||
} | |||
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) | |||
msg.SetControllen(len(oob)) | |||
} | |||
msg.Iov = &iov | |||
msg.Iovlen = 1 | |||
if len(iov) > 0 { | |||
msg.Iov = &iov[0] | |||
msg.SetIovlen(len(iov)) | |||
} | |||
if n, err = sendmsg(fd, &msg, flags); err != nil { | |||
return 0, err | |||
} | |||
if len(oob) > 0 && len(p) == 0 { | |||
if len(oob) > 0 && empty { | |||
n = 0 | |||
} | |||
return n, nil | |||
@@ -571,12 +553,7 @@ func UtimesNano(path string, ts []Timespec) error { | |||
if len(ts) != 2 { | |||
return EINVAL | |||
} | |||
// Darwin setattrlist can set nanosecond timestamps | |||
err := setattrlistTimes(path, ts, 0) | |||
if err != ENOSYS { | |||
return err | |||
} | |||
err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) | |||
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) | |||
if err != ENOSYS { | |||
return err | |||
} | |||
@@ -596,10 +573,6 @@ func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { | |||
if len(ts) != 2 { | |||
return EINVAL | |||
} | |||
err := setattrlistTimes(path, ts, flags) | |||
if err != ENOSYS { | |||
return err | |||
} | |||
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) | |||
} | |||
@@ -141,16 +141,6 @@ func direntNamlen(buf []byte) (uint64, bool) { | |||
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } | |||
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } | |||
type attrList struct { | |||
bitmapCount uint16 | |||
_ uint16 | |||
CommonAttr uint32 | |||
VolAttr uint32 | |||
DirAttr uint32 | |||
FileAttr uint32 | |||
Forkattr uint32 | |||
} | |||
//sysnb pipe(p *[2]int32) (err error) | |||
func Pipe(p []int) (err error) { | |||
@@ -282,36 +272,7 @@ func Flistxattr(fd int, dest []byte) (sz int, err error) { | |||
return flistxattr(fd, xattrPointer(dest), len(dest), 0) | |||
} | |||
func setattrlistTimes(path string, times []Timespec, flags int) error { | |||
_p0, err := BytePtrFromString(path) | |||
if err != nil { | |||
return err | |||
} | |||
var attrList attrList | |||
attrList.bitmapCount = ATTR_BIT_MAP_COUNT | |||
attrList.CommonAttr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME | |||
// order is mtime, atime: the opposite of Chtimes | |||
attributes := [2]Timespec{times[1], times[0]} | |||
options := 0 | |||
if flags&AT_SYMLINK_NOFOLLOW != 0 { | |||
options |= FSOPT_NOFOLLOW | |||
} | |||
return setattrlist( | |||
_p0, | |||
unsafe.Pointer(&attrList), | |||
unsafe.Pointer(&attributes), | |||
unsafe.Sizeof(attributes), | |||
options) | |||
} | |||
//sys setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) | |||
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error { | |||
// Darwin doesn't support SYS_UTIMENSAT | |||
return ENOSYS | |||
} | |||
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) | |||
/* | |||
* Wrapped | |||
@@ -432,6 +393,13 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { | |||
return x, err | |||
} | |||
func GetsockoptTCPConnectionInfo(fd, level, opt int) (*TCPConnectionInfo, error) { | |||
var value TCPConnectionInfo | |||
vallen := _Socklen(SizeofTCPConnectionInfo) | |||
err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |||
return &value, err | |||
} | |||
func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) { | |||
mib, err := sysctlmib(name, args...) | |||
if err != nil { | |||
@@ -543,11 +511,12 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { | |||
//sys Mkdirat(dirfd int, path string, mode uint32) (err error) | |||
//sys Mkfifo(path string, mode uint32) (err error) | |||
//sys Mknod(path string, mode uint32, dev int) (err error) | |||
//sys Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) | |||
//sys Open(path string, mode int, perm uint32) (fd int, err error) | |||
//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) | |||
//sys Pathconf(path string, name int) (val int, err error) | |||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) | |||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) | |||
//sys pread(fd int, p []byte, offset int64) (n int, err error) | |||
//sys pwrite(fd int, p []byte, offset int64) (n int, err error) | |||
//sys read(fd int, p []byte) (n int, err error) | |||
//sys Readlink(path string, buf []byte) (n int, err error) | |||
//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) | |||
@@ -611,7 +580,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { | |||
// Nfssvc | |||
// Getfh | |||
// Quotactl | |||
// Mount | |||
// Csops | |||
// Waitid | |||
// Add_profil | |||
@@ -125,12 +125,14 @@ func Pipe2(p []int, flags int) (err error) { | |||
} | |||
//sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error) | |||
func Pread(fd int, p []byte, offset int64) (n int, err error) { | |||
func pread(fd int, p []byte, offset int64) (n int, err error) { | |||
return extpread(fd, p, 0, offset) | |||
} | |||
//sys extpwrite(fd int, p []byte, flags int, offset int64) (n int, err error) | |||
func Pwrite(fd int, p []byte, offset int64) (n int, err error) { | |||
func pwrite(fd int, p []byte, offset int64) (n int, err error) { | |||
return extpwrite(fd, p, 0, offset) | |||
} | |||
@@ -169,11 +171,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { | |||
return | |||
} | |||
func setattrlistTimes(path string, times []Timespec, flags int) error { | |||
// used on Darwin for UtimesNano | |||
return ENOSYS | |||
} | |||
//sys ioctl(fd int, req uint, arg uintptr) (err error) | |||
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL | |||