diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index f2d3228..14d8ffe 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -9,6 +9,10 @@ name: golangci-lint - '**.go' - .golangci.yml - .github/workflows/golangci-lint.yml + pull_request: + branches: + - main + jobs: lint: diff --git a/.golangci.yml b/.golangci.yml index 43bbd03..1123bf4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,5 @@ run: deadline: 5m - skip-files: - # Skip autogenerated files. - - ^.*\.(pb|y)\.go$ output: sort-results: true @@ -20,6 +17,9 @@ linters: - misspell issues: + exclude-files: + # Skip autogenerated files. + - ^.*\.(pb|y)\.go$ exclude-rules: - path: _test.go linters: diff --git a/buffer.go b/buffer.go index 378fb5e..97c9e67 100644 --- a/buffer.go +++ b/buffer.go @@ -156,7 +156,7 @@ func (b *buffer) len() int { } func (b *buffer) flush(w io.Writer, n int) { - w.Write(b.data[:n]) + _, _ = w.Write(b.data[:n]) n = copy(b.data, b.data[n:]) b.data = b.data[:n] } diff --git a/cmd/dogstatsd/main.go b/cmd/dogstatsd/main.go index e8946df..a4ce285 100644 --- a/cmd/dogstatsd/main.go +++ b/cmd/dogstatsd/main.go @@ -59,7 +59,7 @@ func client(cmd string, args ...string) { args, extra = split(args, "--") fset.StringVar(&addr, "addr", "localhost:8125", "The network address where a dogstatsd server is listening for incoming UDP datagrams") fset.Var(&tags, "tags", "A comma-separated list of tags to set on the metric") - fset.Parse(args) + _ = fset.Parse(args) args = fset.Args() if len(args) == 0 { @@ -74,8 +74,6 @@ func client(cmd string, args ...string) { value = 1.0 } else if value, err = strconv.ParseFloat(args[0], 64); err != nil { errorf("bad metric value: %s", args[0]) - } else { - args = args[1:] } case "set": @@ -83,8 +81,6 @@ func client(cmd string, args ...string) { errorf("missing metric value") } else if value, err = strconv.ParseFloat(args[0], 64); err != nil { errorf("bad metric value: %s", args[0]) - } else { - args = args[1:] } } @@ -110,19 +106,19 @@ func server(args ...string) { var bind string fset.StringVar(&bind, "bind", ":8125", "The network address to listen on for incoming UDP datagrams") - fset.Parse(args) + _ = fset.Parse(args) log.Printf("listening for incoming UDP datagram on %s", bind) - datadog.ListenAndServe(bind, handlers{}) + _ = datadog.ListenAndServe(bind, handlers{}) } type handlers struct{} -func (h handlers) HandleMetric(m datadog.Metric, a net.Addr) { +func (h handlers) HandleMetric(m datadog.Metric, _ net.Addr) { log.Print(m) } -func (h handlers) HandleEvent(e datadog.Event, a net.Addr) { +func (h handlers) HandleEvent(e datadog.Event, _ net.Addr) { log.Print(e) } diff --git a/context_test.go b/context_test.go index c2c6993..22a326d 100644 --- a/context_test.go +++ b/context_test.go @@ -17,7 +17,8 @@ func TestContextTags(t *testing.T) { assert.Equal(t, 0, len(ContextTags(x)), "Original context should have no tags (because no context with key)") // create a child context which creates a child context - z := context.WithValue(y, interface{}("not"), "important") + type unimportant struct{} + z := context.WithValue(y, unimportant{}, "important") assert.Equal(t, 1, len(ContextTags(z)), "We should still be able to see original tags") // Add tags to the child context's reference to the original tag slice diff --git a/datadog/append_test.go b/datadog/append_test.go index ff07ae2..8f6fe57 100644 --- a/datadog/append_test.go +++ b/datadog/append_test.go @@ -4,7 +4,7 @@ import "testing" func TestAppendMetric(t *testing.T) { for _, test := range testMetrics { - t.Run(test.m.Name, func(b *testing.T) { + t.Run(test.m.Name, func(t *testing.T) { if s := string(appendMetric(nil, test.m)); s != test.s { t.Errorf("\n<<< %#v\n>>> %#v", test.s, s) } diff --git a/datadog/client.go b/datadog/client.go index 977f0cf..15acf70 100644 --- a/datadog/client.go +++ b/datadog/client.go @@ -4,10 +4,11 @@ import ( "log" "net" "os" - "syscall" "time" "github.com/segmentio/stats/v4" + + "golang.org/x/sys/unix" ) const ( @@ -158,7 +159,7 @@ func dial(address string, sizehint int) (conn net.Conn, bufsize int, err error) // sent in one batch we attempt to attempt to adjust the kernel buffer size // to accept larger datagrams, or fallback to the default socket buffer size // if it failed. - if bufsize, err = syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF); err != nil { + if bufsize, err = unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_SNDBUF); err != nil { conn.Close() return } @@ -169,7 +170,7 @@ func dial(address string, sizehint int) (conn net.Conn, bufsize int, err error) bufsize /= 2 for sizehint > bufsize && sizehint > 0 { - if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, sizehint); err == nil { + if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_SNDBUF, sizehint); err == nil { bufsize = sizehint break } @@ -194,6 +195,6 @@ func dial(address string, sizehint int) (conn net.Conn, bufsize int, err error) } // Creating the file put the socket in blocking mode, reverting. - syscall.SetNonblock(fd, true) + _ = unix.SetNonblock(fd, true) return } diff --git a/datadog/client_test.go b/datadog/client_test.go index d860cfe..e3dd9af 100644 --- a/datadog/client_test.go +++ b/datadog/client_test.go @@ -1,9 +1,9 @@ package datadog import ( + "errors" "fmt" "io" - "io/ioutil" "log" "net" "strings" @@ -11,9 +11,9 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" - "github.com/segmentio/stats/v4" + + "github.com/stretchr/testify/assert" ) func TestClient(t *testing.T) { @@ -72,7 +72,7 @@ func TestClientWithUseDistributions(t *testing.T) { UseDistributions: true, }) - testMeassure := stats.Measure{ + testMeasure := stats.Measure{ Name: "request", Fields: []stats.Field{ {Name: "count", Value: stats.ValueOf(5)}, @@ -83,14 +83,14 @@ func TestClientWithUseDistributions(t *testing.T) { stats.T("hello", "world"), }, } - client.HandleMeasures(time.Time{}, testMeassure) + client.HandleMeasures(time.Time{}, testMeasure) client.Flush() expectedPacket1 := "request.count:5|c|#answer:42,hello:world\nrequest.dist_rtt:0.1|d|#answer:42,hello:world\n" assert.EqualValues(t, expectedPacket1, string(<-packets)) client.useDistributions = false - client.HandleMeasures(time.Time{}, testMeassure) + client.HandleMeasures(time.Time{}, testMeasure) client.Flush() expectedPacket2 := "request.count:5|c|#answer:42,hello:world\nrequest.dist_rtt:0.1|h|#answer:42,hello:world\n" @@ -117,7 +117,7 @@ main.http.rtt.seconds:0.001215296|h|#http_req_content_charset:,http_req_content_ count := int32(0) expect := int32(strings.Count(data, "\n")) - addr, closer := startTestServer(t, HandlerFunc(func(m Metric, _ net.Addr) { + addr, closer := startTestServer(t, HandlerFunc(func(_ Metric, _ net.Addr) { atomic.AddInt32(&count, 1) })) defer closer.Close() @@ -136,7 +136,7 @@ main.http.rtt.seconds:0.001215296|h|#http_req_content_charset:,http_req_content_ } func BenchmarkClient(b *testing.B) { - log.SetOutput(ioutil.Discard) + log.SetOutput(io.Discard) for _, N := range []int{1, 10, 100} { b.Run(fmt.Sprintf("write a batch of %d measures to a client", N), func(b *testing.B) { @@ -169,6 +169,14 @@ func BenchmarkClient(b *testing.B) { } } +func isClosedNetworkConnectionErr(err error) bool { + var netErr *net.OpError + if errors.As(err, &netErr) { + return strings.Contains(netErr.Err.Error(), "use of closed network connection") + } + return false +} + // startUDPListener starts a goroutine listening for UDP packets on 127.0.0.1 and an available port. // The address listened to is returned as `addr`. The payloads of packets received are copied to `packets`. func startUDPListener(t *testing.T, packets chan []byte) (addr string, closer io.Closer) { @@ -186,7 +194,9 @@ func startUDPListener(t *testing.T, packets chan []byte) (addr string, closer io } if err != nil { - t.Log(err) + if !isClosedNetworkConnectionErr(err) { + fmt.Println("err reading from UDP connection in goroutine:", err) + } return } } diff --git a/datadog/event.go b/datadog/event.go index e9992eb..5f55046 100644 --- a/datadog/event.go +++ b/datadog/event.go @@ -51,6 +51,6 @@ func (e Event) String() string { func (e Event) Format(f fmt.State, _ rune) { buf := bufferPool.Get().(*buffer) buf.b = appendEvent(buf.b[:0], e) - f.Write(buf.b) + _, _ = f.Write(buf.b) bufferPool.Put(buf) } diff --git a/datadog/metric.go b/datadog/metric.go index a6bcc06..69c0abd 100644 --- a/datadog/metric.go +++ b/datadog/metric.go @@ -39,7 +39,7 @@ func (m Metric) String() string { func (m Metric) Format(f fmt.State, _ rune) { buf := bufferPool.Get().(*buffer) buf.b = appendMetric(buf.b[:0], m) - f.Write(buf.b) + _, _ = f.Write(buf.b) bufferPool.Put(buf) } diff --git a/datadog/server.go b/datadog/server.go index f876f86..8be04fd 100644 --- a/datadog/server.go +++ b/datadog/server.go @@ -33,9 +33,7 @@ func (f HandlerFunc) HandleMetric(m Metric, a net.Addr) { } // HandleEvent is a no-op for backwards compatibility. -func (f HandlerFunc) HandleEvent(Event, net.Addr) { - return -} +func (f HandlerFunc) HandleEvent(Event, net.Addr) {} // ListenAndServe starts a new dogstatsd server, listening for UDP datagrams on // addr and forwarding the metrics to handler. diff --git a/engine_test.go b/engine_test.go index 655edd7..31aaa09 100644 --- a/engine_test.go +++ b/engine_test.go @@ -64,6 +64,10 @@ func TestEngine(t *testing.T) { scenario: "calling Engine.Clock produces expected metrics", function: testEngineClock, }, + { + scenario: "calling Engine.WithTags produces expected tags", + function: testEngineWithTags, + }, } for _, test := range tests { @@ -307,6 +311,7 @@ func checkMeasuresEqual(t *testing.T, eng *stats.Engine, expected ...stats.Measu } func measures(t *testing.T, eng *stats.Engine) []stats.Measure { + t.Helper() return eng.Handler.(*statstest.Handler).Measures() } diff --git a/field_test.go b/field_test.go index 2dea0d2..1a395e3 100644 --- a/field_test.go +++ b/field_test.go @@ -17,10 +17,10 @@ func BenchmarkAssign40BytesStruct(b *testing.B) { c int } - s := S{} + var s S for i := 0; i != b.N; i++ { - s = S{a: "hello"} + s = S{a: "hello", b: "", c: 0} _ = s } } @@ -31,10 +31,10 @@ func BenchmarkAssign32BytesStruct(b *testing.B) { b string } - s := S{} + var s S for i := 0; i != b.N; i++ { - s = S{a: "hello"} + s = S{a: "hello", b: ""} _ = s } } diff --git a/go.mod b/go.mod index 7627566..699f557 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb golang.org/x/sync v0.3.0 + golang.org/x/sys v0.12.0 ) require github.com/davecgh/go-spew v1.1.1 // indirect @@ -20,7 +21,6 @@ require ( github.com/mdlayher/netlink v0.0.0-20190313131330-258ea9dff42c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.12.0 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/grafana/annotations.go b/grafana/annotations.go index b128ed0..8591c1c 100644 --- a/grafana/annotations.go +++ b/grafana/annotations.go @@ -117,7 +117,7 @@ type annotationsResponse struct { } func (res *annotationsResponse) WriteAnnotation(a Annotation) { - res.enc.Encode(annotationInfo{ + _ = res.enc.Encode(annotationInfo{ Annotation: annotation{ Name: res.name, Datasource: res.datasource, diff --git a/grafana/annotations_test.go b/grafana/annotations_test.go index 968105a..2de0439 100644 --- a/grafana/annotations_test.go +++ b/grafana/annotations_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/json" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -28,7 +28,7 @@ func TestAnnotationsHandler(t *testing.T) { client := http.Client{} server := httptest.NewServer(NewAnnotationsHandler( - AnnotationsHandlerFunc(func(ctx context.Context, res AnnotationsResponse, req *AnnotationsRequest) error { + AnnotationsHandlerFunc(func(_ context.Context, res AnnotationsResponse, req *AnnotationsRequest) error { if !req.From.Equal(ar.Range.From) { t.Error("bad 'from' time:", req.From, ar.Range.From) } @@ -79,7 +79,7 @@ func TestAnnotationsHandler(t *testing.T) { } defer r.Body.Close() - found, _ := ioutil.ReadAll(r.Body) + found, _ := io.ReadAll(r.Body) expect := annotationsResult if s := string(found); s != expect { diff --git a/grafana/handler.go b/grafana/handler.go index c7866eb..cb76704 100644 --- a/grafana/handler.go +++ b/grafana/handler.go @@ -47,7 +47,7 @@ func Handle(mux *http.ServeMux, prefix string, handler Handler) { if _, pattern := mux.Handler(&http.Request{ URL: &url.URL{Path: root}, }); len(pattern) == 0 { - mux.HandleFunc(root, func(res http.ResponseWriter, req *http.Request) { + mux.HandleFunc(root, func(res http.ResponseWriter, _ *http.Request) { setResponseHeaders(res) }) } diff --git a/grafana/query.go b/grafana/query.go index 67275ed..bd0e3b3 100644 --- a/grafana/query.go +++ b/grafana/query.go @@ -191,13 +191,13 @@ func (res *queryResponse) close() error { func (res *queryResponse) flush() { if res.timeserie != nil { - res.enc.Encode(res.timeserie) + _ = res.enc.Encode(res.timeserie) res.timeserie.closed = true res.timeserie = nil } if res.table != nil { - res.enc.Encode(res.table) + _ = res.enc.Encode(res.table) res.table.closed = true res.table = nil } diff --git a/grafana/query_test.go b/grafana/query_test.go index 015ad4a..c06fc21 100644 --- a/grafana/query_test.go +++ b/grafana/query_test.go @@ -32,7 +32,7 @@ func TestQueryHandler(t *testing.T) { client := http.Client{} server := httptest.NewServer(NewQueryHandler( - QueryHandlerFunc(func(ctx context.Context, res QueryResponse, req *QueryRequest) error { + QueryHandlerFunc(func(_ context.Context, res QueryResponse, req *QueryRequest) error { if !req.From.Equal(t0) { t.Error("bad 'from' time:", req.From, "!=", t0) } diff --git a/grafana/search.go b/grafana/search.go index 31ca4ce..0a5c0d8 100644 --- a/grafana/search.go +++ b/grafana/search.go @@ -81,11 +81,11 @@ type searchResponse struct { } func (res *searchResponse) WriteTarget(target string) { - res.enc.Encode(target) + _ = res.enc.Encode(target) } func (res *searchResponse) WriteTargetValue(target string, value interface{}) { - res.enc.Encode(struct { + _ = res.enc.Encode(struct { Target string `json:"target"` Value interface{} `json:"value"` }{target, value}) diff --git a/grafana/search_test.go b/grafana/search_test.go index 9a9fe4e..1467592 100644 --- a/grafana/search_test.go +++ b/grafana/search_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/json" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -19,7 +19,7 @@ func TestSearchHandler(t *testing.T) { client := http.Client{} server := httptest.NewServer(NewSearchHandler( - SearchHandlerFunc(func(ctx context.Context, res SearchResponse, req *SearchRequest) error { + SearchHandlerFunc(func(_ context.Context, res SearchResponse, req *SearchRequest) error { if req.Target != sr.Target { t.Error("bad 'from' time:", req.Target, "!=", sr.Target) } @@ -44,7 +44,7 @@ func TestSearchHandler(t *testing.T) { } defer r.Body.Close() - found, _ := ioutil.ReadAll(r.Body) + found, _ := io.ReadAll(r.Body) expect := searchResult if s := string(found); s != expect { diff --git a/handler.go b/handler.go index caa76a4..501536a 100644 --- a/handler.go +++ b/handler.go @@ -97,4 +97,4 @@ var Discard = &discard{} type discard struct{} -func (*discard) HandleMeasures(time time.Time, measures ...Measure) {} +func (*discard) HandleMeasures(time.Time, ...Measure) {} diff --git a/handler_test.go b/handler_test.go index 5418edf..58d1f81 100644 --- a/handler_test.go +++ b/handler_test.go @@ -13,7 +13,7 @@ import ( func TestMultiHandler(t *testing.T) { t.Run("calling HandleMeasures on a multi-handler dispatches to each handler", func(t *testing.T) { n := 0 - f := stats.HandlerFunc(func(time time.Time, measures ...stats.Measure) { n++ }) + f := stats.HandlerFunc(func(time.Time, ...stats.Measure) { n++ }) m := stats.MultiHandler(f, f, f) m.HandleMeasures(time.Now()) diff --git a/httpstats/context_test.go b/httpstats/context_test.go index cef18a8..f3ad93c 100644 --- a/httpstats/context_test.go +++ b/httpstats/context_test.go @@ -27,7 +27,8 @@ func TestRequestContextTagPropegation(t *testing.T) { assert.Equal(t, 0, len(RequestTags(x)), "Original request should have no tags (because no context with key)") // create a child request which creates a child context - z := y.WithContext(context.WithValue(y.Context(), interface{}("not"), "important")) + type contextVal struct{} + z := y.WithContext(context.WithValue(y.Context(), contextVal{}, "important")) assert.Equal(t, 1, len(RequestTags(z)), "We should still be able to see original tags") // Add tags to the child context's reference to the original tag slice diff --git a/httpstats/handler_test.go b/httpstats/handler_test.go index 2b29463..1c00e7d 100644 --- a/httpstats/handler_test.go +++ b/httpstats/handler_test.go @@ -68,7 +68,7 @@ func TestHandlerHijack(t *testing.T) { h := &statstest.Handler{} e := stats.NewEngine("", h) - server := httptest.NewServer(NewHandlerWith(e, http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + server := httptest.NewServer(NewHandlerWith(e, http.HandlerFunc(func(res http.ResponseWriter, _ *http.Request) { // make sure the response writer supports hijacking conn, _, _ := res.(http.Hijacker).Hijack() conn.Close() diff --git a/httpstats/metrics.go b/httpstats/metrics.go index e38217b..7051125 100644 --- a/httpstats/metrics.go +++ b/httpstats/metrics.go @@ -58,14 +58,14 @@ type nullBody struct{} func (n *nullBody) Close() error { return nil } -func (n *nullBody) Read(b []byte) (int, error) { return 0, io.EOF } +func (n *nullBody) Read([]byte) (int, error) { return 0, io.EOF } type requestBody struct { body io.ReadCloser eng *stats.Engine - req *http.Request metrics *metrics bytes int + req *http.Request op string once sync.Once } diff --git a/httpstats/transport_test.go b/httpstats/transport_test.go index 5370b42..c6a26c6 100644 --- a/httpstats/transport_test.go +++ b/httpstats/transport_test.go @@ -79,7 +79,7 @@ func TestTransportError(t *testing.T) { h := &statstest.Handler{} e := stats.NewEngine("", h) - server := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, _ *http.Request) { conn, _, _ := res.(http.Hijacker).Hijack() conn.Close() })) diff --git a/influxdb/client.go b/influxdb/client.go index f36e07a..9543d75 100644 --- a/influxdb/client.go +++ b/influxdb/client.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "log" "net/http" "net/url" @@ -215,7 +214,7 @@ func makeURL(address, database string) *url.URL { func readResponse(r *http.Response) error { if r.StatusCode < 300 { - io.Copy(ioutil.Discard, r.Body) + _, _ = io.Copy(io.Discard, r.Body) r.Body.Close() return nil } diff --git a/netstats/handler_test.go b/netstats/handler_test.go index a62ede5..85a285a 100644 --- a/netstats/handler_test.go +++ b/netstats/handler_test.go @@ -10,7 +10,7 @@ type testHandler struct { ok bool } -func (h *testHandler) ServeConn(ctx context.Context, conn net.Conn) { +func (h *testHandler) ServeConn(context.Context, net.Conn) { h.ok = true } diff --git a/procstats/delaystats_linux.go b/procstats/delaystats_linux.go index 495fe4c..26c3a54 100644 --- a/procstats/delaystats_linux.go +++ b/procstats/delaystats_linux.go @@ -2,20 +2,20 @@ package procstats import ( "errors" - "syscall" "github.com/mdlayher/taskstats" + "golang.org/x/sys/unix" ) func collectDelayInfo(pid int) DelayInfo { client, err := taskstats.New() - if err == syscall.ENOENT { + if err == unix.ENOENT { err = errors.New("failed to communicate with taskstats Netlink family, ensure this program is not running in a network namespace") } check(err) stats, err := client.TGID(pid) - if err == syscall.EPERM { + if err == unix.EPERM { err = errors.New("failed to open Netlink socket: permission denied, ensure CAP_NET_RAW is enabled for this process, or run it with root privileges") } check(err) diff --git a/procstats/linux/memory_linux.go b/procstats/linux/memory_linux.go index fbd10d2..afc126c 100644 --- a/procstats/linux/memory_linux.go +++ b/procstats/linux/memory_linux.go @@ -5,7 +5,8 @@ import ( "path/filepath" "strconv" "strings" - "syscall" + + "golang.org/x/sys/unix" ) func readMemoryLimit(pid int) (limit uint64, err error) { @@ -54,10 +55,10 @@ func readMemoryCGroupMemoryLimitFilePath(cgroupPath string) string { } func readSysinfoMemoryLimit() (limit uint64, err error) { - var sysinfo syscall.Sysinfo_t + var sysinfo unix.Sysinfo_t - if err = syscall.Sysinfo(&sysinfo); err == nil { - // syscall.Sysinfo returns an uint32 on linux/arm, but uint64 otherwise + if err = unix.Sysinfo(&sysinfo); err == nil { + // unix.Sysinfo returns an uint32 on linux/arm, but uint64 otherwise limit = uint64(sysinfo.Unit) * uint64(sysinfo.Totalram) } diff --git a/procstats/linux/stat.go b/procstats/linux/stat.go index 5eaa7bc..2c66cc8 100644 --- a/procstats/linux/stat.go +++ b/procstats/linux/stat.go @@ -15,9 +15,10 @@ const ( TracingStop ProcState = 't' Paging ProcState = 'P' Dead ProcState = 'X' - Dead_ ProcState = 'x' - Wakekill ProcState = 'W' - Parked ProcState = 'P' + //revive:disable-next-line + Dead_ ProcState = 'x' + Wakekill ProcState = 'W' + Parked ProcState = 'P' ) // Scan updates the ProcState for a process. diff --git a/procstats/proc.go b/procstats/proc.go index 70bfc3c..fead836 100644 --- a/procstats/proc.go +++ b/procstats/proc.go @@ -134,7 +134,7 @@ func (p *ProcMetrics) Collect() { now := time.Now() if !p.lastTime.IsZero() { - ratio := 1.0 + var ratio float64 switch { case m.CPU.Period > 0 && m.CPU.Quota > 0: ratio = float64(m.CPU.Quota) / float64(m.CPU.Period) diff --git a/procstats/proc_darwin.go b/procstats/proc_darwin.go index 6631c0e..9d00393 100644 --- a/procstats/proc_darwin.go +++ b/procstats/proc_darwin.go @@ -25,9 +25,10 @@ import "C" import ( "fmt" "os" - "syscall" "time" "unsafe" + + "golang.org/x/sys/unix" ) func collectProcInfo(pid int) (info ProcInfo, err error) { @@ -41,11 +42,11 @@ func collectProcInfo(pid int) (info ProcInfo, err error) { task := C.mach_port_name_t(0) checkKern(C.task_for_pid(self, C.int(pid), &task)) - rusage := syscall.Rusage{} - check(syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)) + rusage := unix.Rusage{} + check(unix.Getrusage(unix.RUSAGE_SELF, &rusage)) - nofile := syscall.Rlimit{} - check(syscall.Getrlimit(syscall.RLIMIT_NOFILE, &nofile)) + nofile := unix.Rlimit{} + check(unix.Getrlimit(unix.RLIMIT_NOFILE, &nofile)) info.CPU.User = time.Duration(rusage.Utime.Nano()) info.CPU.Sys = time.Duration(rusage.Stime.Nano()) diff --git a/procstats/proc_linux.go b/procstats/proc_linux.go index 3675d58..d2a7a9d 100644 --- a/procstats/proc_linux.go +++ b/procstats/proc_linux.go @@ -1,16 +1,17 @@ package procstats import ( - "io/ioutil" + "io" "os" "os/exec" "strconv" "strings" "sync" - "syscall" "time" "github.com/segmentio/stats/v4/procstats/linux" + + "golang.org/x/sys/unix" ) var ( @@ -54,15 +55,17 @@ func getconf(name string) (string, error) { } w.Close() - b, err := ioutil.ReadAll(r) - p.Wait() + b, err := io.ReadAll(r) + if _, err := p.Wait(); err != nil { + return "", err + } return string(b), err } func collectProcInfo(pid int) (info ProcInfo, err error) { defer func() { err = convertPanicToError(recover()) }() - var pagesize = uint64(syscall.Getpagesize()) + pagesize := uint64(unix.Getpagesize()) var cpu CPUInfo memoryLimit, err := linux.ReadMemoryLimit(pid) @@ -84,8 +87,8 @@ func collectProcInfo(pid int) (info ProcInfo, err error) { check(err) if pid == os.Getpid() { - rusage := syscall.Rusage{} - check(syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)) + rusage := unix.Rusage{} + check(unix.Getrusage(unix.RUSAGE_SELF, &rusage)) cpuPeriod, _ := linux.ReadCPUPeriod("") cpuQuota, _ := linux.ReadCPUQuota("") diff --git a/procstats/proc_test.go b/procstats/proc_test.go index bdf3c86..cfd2885 100644 --- a/procstats/proc_test.go +++ b/procstats/proc_test.go @@ -30,6 +30,7 @@ func TestProcMetrics(t *testing.T) { testProcMetrics(t, cmd.Process.Pid) cmd.Process.Signal(os.Interrupt) waitErr := cmd.Wait() + //revive:disable-next-line if exitErr, ok := waitErr.(*exec.ExitError); ok && exitErr.Error() == "signal: interrupt" { // This is expected from stopping the process } else { diff --git a/prometheus/handler.go b/prometheus/handler.go index 2a2d102..810f539 100644 --- a/prometheus/handler.go +++ b/prometheus/handler.go @@ -159,7 +159,7 @@ func (h *Handler) WriteStats(w io.Writer) { b = append(b, '\n') } - w.Write(appendMetric(b, m)) + _, _ = w.Write(appendMetric(b, m)) lastMetricName = name } } diff --git a/prometheus/label.go b/prometheus/label.go index 96a4ca2..c43feb2 100644 --- a/prometheus/label.go +++ b/prometheus/label.go @@ -11,13 +11,6 @@ type label struct { value string } -func (l label) hash() uint64 { - h := jody.Init64 - h = jody.AddString64(h, l.name) - h = jody.AddString64(h, l.value) - return h -} - func (l label) equal(other label) bool { return l.name == other.name && l.value == other.value } diff --git a/reflect.go b/reflect.go index afb0b94..45faf37 100644 --- a/reflect.go +++ b/reflect.go @@ -15,10 +15,6 @@ func (f structField) pointer(ptr unsafe.Pointer) unsafe.Pointer { return unsafe.Pointer(uintptr(ptr) + f.off) } -func (f structField) value(ptr unsafe.Pointer) reflect.Value { - return reflect.NewAt(f.typ, f.pointer(ptr)) -} - func (f structField) bool(ptr unsafe.Pointer) bool { return *(*bool)(f.pointer(ptr)) } diff --git a/statstest/handler.go b/statstest/handler.go index 4ff3e74..33e9ded 100644 --- a/statstest/handler.go +++ b/statstest/handler.go @@ -21,7 +21,7 @@ type Handler struct { } // HandleMeasures process a variadic list of stats.Measure. -func (h *Handler) HandleMeasures(time time.Time, measures ...stats.Measure) { +func (h *Handler) HandleMeasures(_ time.Time, measures ...stats.Measure) { h.Lock() for _, m := range measures { h.measures = append(h.measures, m.Clone()) diff --git a/tag.go b/tag.go index 58921be..1edbf0c 100644 --- a/tag.go +++ b/tag.go @@ -51,7 +51,7 @@ func SortTags(tags []Tag) []Tag { return deduplicateTags(tags) } -// reports whether a is less than b +// tagCompare reports whether a is less than b. func tagCompare(a, b Tag) int { if a.Name < b.Name { return -1 diff --git a/tag_test.go b/tag_test.go index 2eb5707..39f35f1 100644 --- a/tag_test.go +++ b/tag_test.go @@ -224,7 +224,7 @@ func BenchmarkSortTags_few(b *testing.B) { {"C", ""}, } - benchmark_SortTags(b, t0) + benchmarkSortTags(b, t0) } func BenchmarkSortTags_many(b *testing.B) { @@ -252,39 +252,39 @@ func BenchmarkSortTags_many(b *testing.B) { {"C", ""}, } - benchmark_SortTags(b, t0) + benchmarkSortTags(b, t0) } -func benchmark_SortTags(b *testing.B, t0 []Tag) { +func benchmarkSortTags(b *testing.B, t0 []Tag) { b.Helper() b.Run("SortTags", func(b *testing.B) { fn := func(tags []Tag) { SortTags(tags) } - benchmark_SortTags_func(b, t0, fn) + benchmarkSortTagsFunc(b, t0, fn) }) b.Run("slices.SortFunc", func(b *testing.B) { fn := func(tags []Tag) { slices.SortFunc(tags, tagCompare) } - benchmark_SortTags_func(b, t0, fn) + benchmarkSortTagsFunc(b, t0, fn) }) b.Run("slices.SortStableFunc", func(b *testing.B) { fn := func(tags []Tag) { slices.SortStableFunc(tags, tagCompare) } - benchmark_SortTags_func(b, t0, fn) + benchmarkSortTagsFunc(b, t0, fn) }) b.Run("sort.Slice", func(b *testing.B) { fn := func(tags []Tag) { sort.Slice(tags, tagIsLessByIndex(tags)) } - benchmark_SortTags_func(b, t0, fn) + benchmarkSortTagsFunc(b, t0, fn) }) b.Run("sort.SliceStable", func(b *testing.B) { fn := func(tags []Tag) { sort.SliceStable(tags, tagIsLessByIndex(tags)) } - benchmark_SortTags_func(b, t0, fn) + benchmarkSortTagsFunc(b, t0, fn) }) } -func benchmark_SortTags_func(b *testing.B, t0 []Tag, fn func([]Tag)) { +func benchmarkSortTagsFunc(b *testing.B, t0 []Tag, fn func([]Tag)) { b.Helper() b.ReportAllocs() @@ -296,7 +296,7 @@ func benchmark_SortTags_func(b *testing.B, t0 []Tag, fn func([]Tag)) { } } -func Benchmark_tagsBuffer_sort_sorted(b *testing.B) { +func BenchmarkTagsBufferSortSorted(b *testing.B) { b.ReportAllocs() tags := []Tag{ @@ -322,7 +322,7 @@ func Benchmark_tagsBuffer_sort_sorted(b *testing.B) { } } -func Benchmark_tagsBuffer_sort_unsorted(b *testing.B) { +func BenchmarkTagsBufferSortUnsorted(b *testing.B) { b.ReportAllocs() tags := []Tag{ @@ -348,7 +348,7 @@ func Benchmark_tagsBuffer_sort_unsorted(b *testing.B) { } } -func Benchmark_mergeTags(b *testing.B) { +func BenchmarkMergeTags(b *testing.B) { b.ReportAllocs() origT1 := []Tag{