From 05659e4fe8ae0c75629b43b7636f376d4ddccc93 Mon Sep 17 00:00:00 2001 From: Kevin Gillette Date: Tue, 18 Jul 2023 12:55:04 -0600 Subject: [PATCH 1/5] .golangci.yml: disable broken linter --- .golangci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index b44d546..43bbd03 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,8 +8,10 @@ output: sort-results: true linters: + disable: + - depguard # this linter is broken in golangci-lint as of 2023-07-18. + enable: - - depguard - godot - gofumpt - goimports From 10fd029132b7d67490b01e029a57862835219889 Mon Sep 17 00:00:00 2001 From: Kevin Gillette Date: Tue, 18 Jul 2023 12:55:21 -0600 Subject: [PATCH 2/5] golangci-lint run --fix autofixed changes. no other updates --- buckets.go | 2 +- cmd/dogstatsd/main.go | 6 +-- context.go | 6 +-- datadog/client_test.go | 6 +-- datadog/event.go | 2 +- datadog/parse.go | 9 ++-- datadog/serializer.go | 2 +- datadog/serializer_test.go | 86 +++++++++++++++++----------------- datadog/server_test.go | 1 - grafana/query.go | 2 +- handler.go | 2 +- httpstats/context_test.go | 3 +- httpstats/metrics.go | 4 +- httpstats/transport.go | 2 +- httpstats/transport_test.go | 2 +- influxdb/client.go | 3 +- measure.go | 29 ++++++------ netstats/conn.go | 3 +- procstats/collector.go | 2 + procstats/delaystats.go | 1 - procstats/go.go | 2 +- procstats/linux/cgroup.go | 4 ++ procstats/linux/limits.go | 10 ++-- procstats/linux/limits_test.go | 1 - procstats/linux/parse.go | 4 +- procstats/linux/parse_test.go | 2 +- procstats/linux/sched.go | 6 ++- procstats/linux/sched_test.go | 2 - procstats/linux/stat.go | 2 + procstats/linux/stat_test.go | 1 - procstats/linux/statm_test.go | 1 - procstats/proc.go | 7 ++- procstats/proc_darwin.go | 3 +- prometheus/append.go | 6 +-- prometheus/handler.go | 10 ++-- prometheus/label.go | 1 + prometheus/metric.go | 10 ++-- statstest/handler.go | 6 ++- tag.go | 2 +- value.go | 14 +++++- veneur/client.go | 10 ++-- 41 files changed, 148 insertions(+), 129 deletions(-) diff --git a/buckets.go b/buckets.go index 73e27bb..610e3b8 100644 --- a/buckets.go +++ b/buckets.go @@ -33,7 +33,7 @@ func makeKey(s string) Key { return Key{Measure: measure, Field: field} } -func splitMeasureField(s string) (measure string, field string) { +func splitMeasureField(s string) (measure, field string) { if i := strings.LastIndexByte(s, '.'); i >= 0 { measure, field = s[:i], s[i+1:] } else { diff --git a/cmd/dogstatsd/main.go b/cmd/dogstatsd/main.go index 14ee8e0..59d046d 100644 --- a/cmd/dogstatsd/main.go +++ b/cmd/dogstatsd/main.go @@ -48,7 +48,7 @@ commands: } func client(cmd string, args ...string) { - var fset = flag.NewFlagSet("dogstatsd "+cmd+" [options...] metric value [-- args...]", flag.ExitOnError) + fset := flag.NewFlagSet("dogstatsd "+cmd+" [options...] metric value [-- args...]", flag.ExitOnError) var extra []string var tags tags var addr string @@ -106,7 +106,7 @@ func client(cmd string, args ...string) { } func server(args ...string) { - var fset = flag.NewFlagSet("dogstatsd agent [options...]", flag.ExitOnError) + fset := flag.NewFlagSet("dogstatsd agent [options...]", flag.ExitOnError) var bind string fset.StringVar(&bind, "bind", ":8125", "The network address to listen on for incoming UDP datagrams") @@ -146,7 +146,7 @@ func errorf(msg string, args ...interface{}) { os.Exit(1) } -func split(args []string, sep string) (head []string, tail []string) { +func split(args []string, sep string) (head, tail []string) { if i := indexOf(args, sep); i < 0 { head = args } else { diff --git a/context.go b/context.go index 6251ade..bf31431 100644 --- a/context.go +++ b/context.go @@ -33,7 +33,7 @@ func ContextAddTags(ctx context.Context, tags ...Tag) bool { } // ContextTags returns a copy of the tags on the context if they exist and nil -// if they don't exist +// if they don't exist. func ContextTags(ctx context.Context) []Tag { if x := getTagSlice(ctx); x != nil { x.lock.Lock() @@ -62,12 +62,12 @@ type tagSlice struct { // for defining context keys was copied from Go 1.7's new use of context in net/http. type tagsKey struct{} -// String is Stringer implementation +// String is Stringer implementation. func (k tagsKey) String() string { return "stats_tags_context_key" } -// contextKeyReqTags is contextKey for tags +// contextKeyReqTags is contextKey for tags. var ( contextKeyReqTags = tagsKey{} ) diff --git a/datadog/client_test.go b/datadog/client_test.go index ea2dae2..d860cfe 100644 --- a/datadog/client_test.go +++ b/datadog/client_test.go @@ -11,8 +11,9 @@ import ( "testing" "time" - "github.com/segmentio/stats/v4" "github.com/stretchr/testify/assert" + + "github.com/segmentio/stats/v4" ) func TestClient(t *testing.T) { @@ -61,7 +62,6 @@ func TestClientWithDistributionPrefixes(t *testing.T) { } func TestClientWithUseDistributions(t *testing.T) { - // Start a goroutine listening for packets and giving them back on packets chan packets := make(chan []byte) addr, closer := startUDPListener(t, packets) @@ -170,7 +170,7 @@ func BenchmarkClient(b *testing.B) { } // 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` +// 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) { conn, err := net.ListenPacket("udp", "127.0.0.1:0") // :0 chooses an available port if err != nil { diff --git a/datadog/event.go b/datadog/event.go index b11d719..e9992eb 100644 --- a/datadog/event.go +++ b/datadog/event.go @@ -28,7 +28,7 @@ const ( EventAlertTypeSuccess EventAlertType = "success" ) -// Event is a representation of a datadog event +// Event is a representation of a datadog event. type Event struct { Title string Text string diff --git a/datadog/parse.go b/datadog/parse.go index 7a2225e..f4b0fd7 100644 --- a/datadog/parse.go +++ b/datadog/parse.go @@ -10,7 +10,7 @@ import ( // Adapted from https://github.com/DataDog/datadog-agent/blob/6789e98a1e41e98700fa1783df62238bb23cb454/pkg/dogstatsd/parser.go#L141 func parseEvent(s string) (e Event, err error) { - var next = strings.TrimSpace(s) + next := strings.TrimSpace(s) var header string var rawTitleLen string var rawTextLen string @@ -109,8 +109,9 @@ func parseEvent(s string) (e Event, err error) { return } + func parseMetric(s string) (m Metric, err error) { - var next = strings.TrimSpace(s) + next := strings.TrimSpace(s) var name string var val string var typ string @@ -201,7 +202,7 @@ func parseMetric(s string) (m Metric, err error) { return } -func nextToken(s string, b byte) (token string, next string) { +func nextToken(s string, b byte) (token, next string) { if off := strings.IndexByte(s, b); off >= 0 { token, next = s[:off], s[off+1:] } else { @@ -210,7 +211,7 @@ func nextToken(s string, b byte) (token string, next string) { return } -func split(s string, b byte) (head string, tail string) { +func split(s string, b byte) (head, tail string) { if off := strings.LastIndexByte(s, b); off >= 0 { head, tail = s[:off], s[off+1:] } else { diff --git a/datadog/serializer.go b/datadog/serializer.go index a9bdb88..6ffa8fd 100644 --- a/datadog/serializer.go +++ b/datadog/serializer.go @@ -150,7 +150,7 @@ func (s *serializer) AppendMeasure(b []byte, m stats.Measure) []byte { // sendDist determines whether to send a metric to datadog as histogram `h` type or // distribution `d` type. It's a confusing setup because useDistributions and distPrefixes // are independent implementations of a control mechanism for sending distributions that -// aren't elegantly coordinated +// aren't elegantly coordinated. func (s *serializer) sendDist(name string) bool { if s.useDistributions { return true diff --git a/datadog/serializer_test.go b/datadog/serializer_test.go index 7f6f1d5..f065c32 100644 --- a/datadog/serializer_test.go +++ b/datadog/serializer_test.go @@ -7,59 +7,57 @@ import ( "github.com/segmentio/stats/v4" ) -var ( - testMeasures = []struct { - m stats.Measure - s string - dp []string - }{ - { - m: stats.Measure{ - Name: "request", - Fields: []stats.Field{ - stats.MakeField("count", 5, stats.Counter), - }, +var testMeasures = []struct { + m stats.Measure + s string + dp []string +}{ + { + m: stats.Measure{ + Name: "request", + Fields: []stats.Field{ + stats.MakeField("count", 5, stats.Counter), }, - s: `request.count:5|c -`, - dp: []string{}, }, + s: `request.count:5|c +`, + dp: []string{}, + }, - { - m: stats.Measure{ - Name: "request", - Fields: []stats.Field{ - stats.MakeField("count", 5, stats.Counter), - stats.MakeField("rtt", 100*time.Millisecond, stats.Histogram), - }, - Tags: []stats.Tag{ - stats.T("answer", "42"), - stats.T("hello", "world"), - }, + { + m: stats.Measure{ + Name: "request", + Fields: []stats.Field{ + stats.MakeField("count", 5, stats.Counter), + stats.MakeField("rtt", 100*time.Millisecond, stats.Histogram), }, - s: `request.count:5|c|#answer:42,hello:world + Tags: []stats.Tag{ + stats.T("answer", "42"), + stats.T("hello", "world"), + }, + }, + s: `request.count:5|c|#answer:42,hello:world request.rtt:0.1|h|#answer:42,hello:world `, - dp: []string{}, - }, + dp: []string{}, + }, - { - m: stats.Measure{ - Name: "request", - Fields: []stats.Field{ - stats.MakeField("dist_rtt", 100*time.Millisecond, stats.Histogram), - }, - Tags: []stats.Tag{ - stats.T("answer", "42"), - stats.T("hello", "world"), - }, + { + m: stats.Measure{ + Name: "request", + Fields: []stats.Field{ + stats.MakeField("dist_rtt", 100*time.Millisecond, stats.Histogram), + }, + Tags: []stats.Tag{ + stats.T("answer", "42"), + stats.T("hello", "world"), }, - s: `request.dist_rtt:0.1|d|#answer:42,hello:world -`, - dp: []string{"dist_"}, }, - } -) + s: `request.dist_rtt:0.1|d|#answer:42,hello:world +`, + dp: []string{"dist_"}, + }, +} func TestAppendMeasure(t *testing.T) { client := NewClient(DefaultAddress) diff --git a/datadog/server_test.go b/datadog/server_test.go index 0030a6b..0d4abae 100644 --- a/datadog/server_test.go +++ b/datadog/server_test.go @@ -70,7 +70,6 @@ func TestServer(t *testing.T) { func startTestServer(t *testing.T, handler Handler) (addr string, closer io.Closer) { conn, err := net.ListenPacket("udp", "127.0.0.1:0") - if err != nil { t.Error(err) t.FailNow() diff --git a/grafana/query.go b/grafana/query.go index dda92ad..67275ed 100644 --- a/grafana/query.go +++ b/grafana/query.go @@ -109,7 +109,7 @@ func DescCol(text string, colType ColumnType) Column { // Grafana. type ColumnType string -// ColumnTypes +// ColumnTypes. const ( Untyped ColumnType = "" String ColumnType = "string" diff --git a/handler.go b/handler.go index 581f34c..caa76a4 100644 --- a/handler.go +++ b/handler.go @@ -74,7 +74,7 @@ func (m *multiHandler) Flush() { } } -// FilteredHandler constructs a Handler that processes Measures with `filter` before forwarding to `h` +// FilteredHandler constructs a Handler that processes Measures with `filter` before forwarding to `h`. func FilteredHandler(h Handler, filter func([]Measure) []Measure) Handler { return &filteredHandler{handler: h, filter: filter} } diff --git a/httpstats/context_test.go b/httpstats/context_test.go index d9bb6bf..cef18a8 100644 --- a/httpstats/context_test.go +++ b/httpstats/context_test.go @@ -6,8 +6,9 @@ import ( "net/http/httptest" "testing" - "github.com/segmentio/stats/v4" "github.com/stretchr/testify/assert" + + "github.com/segmentio/stats/v4" ) // TestRequestContextTagPropegation verifies that the root ancestor tags are diff --git a/httpstats/metrics.go b/httpstats/metrics.go index a943012..c34ee79 100644 --- a/httpstats/metrics.go +++ b/httpstats/metrics.go @@ -366,7 +366,7 @@ func transferEncoding(te []string) string { } } -func parseContentType(s string) (contentType string, charset string) { +func parseContentType(s string) (contentType, charset string) { for i := 0; len(s) != 0; i++ { var t string if t, s = parseHeaderToken(s); strings.HasPrefix(t, "charset=") { @@ -378,7 +378,7 @@ func parseContentType(s string) (contentType string, charset string) { return } -func parseHeaderToken(s string) (token string, next string) { +func parseHeaderToken(s string) (token, next string) { if i := strings.IndexByte(s, ';'); i >= 0 { token, next = strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+1:]) } else { diff --git a/httpstats/transport.go b/httpstats/transport.go index c617c17..16c9f7f 100644 --- a/httpstats/transport.go +++ b/httpstats/transport.go @@ -27,7 +27,7 @@ type transport struct { eng *stats.Engine } -// RoundTrip implements http.RoundTripper +// RoundTrip implements http.RoundTripper. func (t *transport) RoundTrip(req *http.Request) (res *http.Response, err error) { start := time.Now() rtrip := t.transport diff --git a/httpstats/transport_test.go b/httpstats/transport_test.go index 1900566..5370b42 100644 --- a/httpstats/transport_test.go +++ b/httpstats/transport_test.go @@ -13,7 +13,7 @@ import ( ) func TestTransport(t *testing.T) { - newRequest := func(method string, path string, body io.Reader) *http.Request { + newRequest := func(method, path string, body io.Reader) *http.Request { req, _ := http.NewRequest(method, path, body) return req } diff --git a/influxdb/client.go b/influxdb/client.go index 2f52d04..f36e07a 100644 --- a/influxdb/client.go +++ b/influxdb/client.go @@ -14,6 +14,7 @@ import ( "time" "github.com/segmentio/objconv/json" + "github.com/segmentio/stats/v4" ) @@ -184,7 +185,7 @@ func (s *serializer) Write(b []byte) (n int, err error) { return } -func makeURL(address string, database string) *url.URL { +func makeURL(address, database string) *url.URL { if !strings.Contains(address, "://") { address = "http://" + address } diff --git a/measure.go b/measure.go index acfe5aa..52392b5 100644 --- a/measure.go +++ b/measure.go @@ -63,18 +63,17 @@ func stringTags(tags []Tag) []string { // The rules for converting values to measure are: // // 1. All fields exposing a 'metric' tag are expected to be of type bool, int, -// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, -// float32, float64, or time.Duration, and represent fields of the measures. -// The struct fields may also define a 'type' tag with a value of "counter", -// "gauge" or "histogram" to tune the behavior of the measure handlers. +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, +// float32, float64, or time.Duration, and represent fields of the measures. +// The struct fields may also define a 'type' tag with a value of "counter", +// "gauge" or "histogram" to tune the behavior of the measure handlers. // // 2. All fields exposing a 'tag' tag are expected to be of type string and -// represent tags of the measures. +// represent tags of the measures. // // 3. All struct fields are searched recursively for fields matching rule (1) -// and (2). Tags found within a struct are inherited by measures generated from -// sub-fields, they may also be overwritten. -// +// and (2). Tags found within a struct are inherited by measures generated from +// sub-fields, they may also be overwritten. func MakeMeasures(prefix string, value interface{}, tags ...Tag) []Measure { if !TagsAreSorted(tags) { SortTags(tags) @@ -111,8 +110,8 @@ func appendMeasures(m []Measure, cache *measureCache, prefix string, v reflect.V return m } - var ptr = unsafe.Pointer(p.Pointer()) - var typ = v.Type() + ptr := unsafe.Pointer(p.Pointer()) + typ := v.Type() var mf []measureFuncs var ok bool @@ -447,11 +446,11 @@ func makeTagFunc(sf structField, name string) func(unsafe.Pointer) Tag { type tagFuncByName []namedTagFunc -func (t tagFuncByName) Len() int { return len(t) } -func (t tagFuncByName) Less(i int, j int) bool { return t[i].name < t[j].name } -func (t tagFuncByName) Swap(i int, j int) { t[i], t[j] = t[j], t[i] } +func (t tagFuncByName) Len() int { return len(t) } +func (t tagFuncByName) Less(i, j int) bool { return t[i].name < t[j].name } +func (t tagFuncByName) Swap(i, j int) { t[i], t[j] = t[j], t[i] } -func concat(prefix string, suffix string) string { +func concat(prefix, suffix string) string { if len(prefix) == 0 { return suffix } @@ -505,7 +504,7 @@ func (c *measureCache) load() *map[reflect.Type][]measureFuncs { return (*map[reflect.Type][]measureFuncs)(atomic.LoadPointer(&c.cache)) } -func (c *measureCache) compareAndSwap(old *map[reflect.Type][]measureFuncs, new *map[reflect.Type][]measureFuncs) bool { +func (c *measureCache) compareAndSwap(old, new *map[reflect.Type][]measureFuncs) bool { return atomic.CompareAndSwapPointer(&c.cache, unsafe.Pointer(old), unsafe.Pointer(new), diff --git a/netstats/conn.go b/netstats/conn.go index 669dc33..63eafd8 100644 --- a/netstats/conn.go +++ b/netstats/conn.go @@ -8,8 +8,9 @@ import ( "sync" "time" - "github.com/segmentio/stats/v4" "github.com/segmentio/vpcinfo" + + "github.com/segmentio/stats/v4" ) func init() { diff --git a/procstats/collector.go b/procstats/collector.go index 5dd3d46..6563555 100644 --- a/procstats/collector.go +++ b/procstats/collector.go @@ -23,6 +23,7 @@ type Config struct { Collector Collector CollectInterval time.Duration } + // MultiCollector coalesces a variadic number of Collectors // and returns a single Collector. func MultiCollector(collectors ...Collector) Collector { @@ -37,6 +38,7 @@ func MultiCollector(collectors ...Collector) Collector { func StartCollector(collector Collector) io.Closer { return StartCollectorWith(Config{Collector: collector}) } + // StartCollectorWith starts a Collector with the provided Config. func StartCollectorWith(config Config) io.Closer { config = setConfigDefaults(config) diff --git a/procstats/delaystats.go b/procstats/delaystats.go index 90f2aa4..39834f4 100644 --- a/procstats/delaystats.go +++ b/procstats/delaystats.go @@ -41,7 +41,6 @@ func (d *DelayMetrics) Collect() { } } - // DelayInfo stores delay Durations for various resources. type DelayInfo struct { CPUDelay time.Duration diff --git a/procstats/go.go b/procstats/go.go index c2eacec..cc8409e 100644 --- a/procstats/go.go +++ b/procstats/go.go @@ -228,7 +228,7 @@ func makeGCPauses(memstats *runtime.MemStats, lastNumGC uint32) (pauses []time.D return makePauses(memstats.PauseNs[i:j], nil) } -func makePauses(head []uint64, tail []uint64) (pauses []time.Duration) { +func makePauses(head, tail []uint64) (pauses []time.Duration) { pauses = make([]time.Duration, 0, len(head)+len(tail)) pauses = appendPauses(pauses, head) pauses = appendPauses(pauses, tail) diff --git a/procstats/linux/cgroup.go b/procstats/linux/cgroup.go index 1669898..223039f 100644 --- a/procstats/linux/cgroup.go +++ b/procstats/linux/cgroup.go @@ -29,6 +29,7 @@ func (pcg ProcCGroup) Lookup(name string) (cgroup CGroup, ok bool) { }) return } + // ReadProcCGroup takes an int argument representing a PID // and returns a ProcCGroup and error, if any is encountered. func ReadProcCGroup(pid int) (proc ProcCGroup, err error) { @@ -36,6 +37,7 @@ func ReadProcCGroup(pid int) (proc ProcCGroup, err error) { proc = parseProcCGroup(readProcFile(pid, "cgroup")) return } + // ParseProcCGroup parses Linux system cgroup data and returns a ProcCGroup and error, if any is encountered. func ParseProcCGroup(s string) (proc ProcCGroup, err error) { defer func() { err = convertPanicToError(recover()) }() @@ -62,6 +64,7 @@ func parseProcCGroup(s string) (proc ProcCGroup) { }) return } + // ReadCPUPeriod takes a string representing a Linux cgroup and returns // the period as a time.Duration that is applied for this cgroup and an error, if any. func ReadCPUPeriod(cgroup string) (period time.Duration, err error) { @@ -69,6 +72,7 @@ func ReadCPUPeriod(cgroup string) (period time.Duration, err error) { period = readCPUPeriod(cgroup) return } + // ReadCPUQuota takes a string representing a Linux cgroup and returns // the quota as a time.Duration that is applied for this cgroup and an error, if any. func ReadCPUQuota(cgroup string) (quota time.Duration, err error) { diff --git a/procstats/linux/limits.go b/procstats/linux/limits.go index 3222b04..4b2e995 100644 --- a/procstats/linux/limits.go +++ b/procstats/linux/limits.go @@ -2,18 +2,19 @@ package linux import "strconv" -// Represents Linux's unlimited for resource limits +// Represents Linux's unlimited for resource limits. const ( Unlimited uint64 = 1<<64 - 1 ) -// Limits holds configuration for resource limits +// Limits holds configuration for resource limits. type Limits struct { Name string Soft uint64 Hard uint64 Unit string } + // ProcLimits holds Limits for processes. type ProcLimits struct { CPUTime Limits // seconds @@ -33,12 +34,14 @@ type ProcLimits struct { RealtimePriority Limits RealtimeTimeout Limits } + // ReadProcLimits returns the ProcLimits and an error, if any, for a PID. func ReadProcLimits(pid int) (proc ProcLimits, err error) { defer func() { err = convertPanicToError(recover()) }() proc = parseProcLimits(readProcFile(pid, "limits")) return } + // ParseProcLimits parses system process limits and returns a ProcLimits and error, if any. func ParseProcLimits(s string) (proc ProcLimits, err error) { defer func() { err = convertPanicToError(recover()) }() @@ -68,12 +71,11 @@ func parseProcLimits(s string) (proc ProcLimits) { columns := make([]string, 0, 4) forEachLineExceptFirst(s, func(line string) { - columns = columns[:0] forEachColumn(line, func(col string) { columns = append(columns, col) }) var limits Limits - var length = len(columns) + length := len(columns) if length > 0 { limits.Name = columns[0] diff --git a/procstats/linux/limits_test.go b/procstats/linux/limits_test.go index 76c610a..8d8420c 100644 --- a/procstats/linux/limits_test.go +++ b/procstats/linux/limits_test.go @@ -26,7 +26,6 @@ Max realtime timeout unlimited unlimited us ` proc, err := ParseProcLimits(text) - if err != nil { t.Error(err) return diff --git a/procstats/linux/parse.go b/procstats/linux/parse.go index 924290f..f4a7fad 100644 --- a/procstats/linux/parse.go +++ b/procstats/linux/parse.go @@ -57,11 +57,11 @@ func forEachProperty(text string, call func(string, string)) { forEachLine(text, func(line string) { call(splitProperty(line)) }) } -func splitProperty(text string) (key string, val string) { +func splitProperty(text string) (key, val string) { return split(text, ':') } -func split(text string, sep byte) (head string, tail string) { +func split(text string, sep byte) (head, tail string) { if i := strings.IndexByte(text, sep); i >= 0 { head, tail = text[:i], text[i+1:] } else { diff --git a/procstats/linux/parse_test.go b/procstats/linux/parse_test.go index bd4cb11..185663c 100644 --- a/procstats/linux/parse_test.go +++ b/procstats/linux/parse_test.go @@ -81,7 +81,7 @@ func TestForEachProperty(t *testing.T) { for _, test := range tests { kv := []KV{} - forEachProperty(test.text, func(k string, v string) { kv = append(kv, KV{k, v}) }) + forEachProperty(test.text, func(k, v string) { kv = append(kv, KV{k, v}) }) if !reflect.DeepEqual(kv, test.kv) { t.Error(kv) diff --git a/procstats/linux/sched.go b/procstats/linux/sched.go index 20b2360..dd548ed 100644 --- a/procstats/linux/sched.go +++ b/procstats/linux/sched.go @@ -12,13 +12,15 @@ type ProcSched struct { SEAvgLoadAvg uint64 // se.avg.load_avg SEAvgUtilAvg uint64 // se.avg.util_avg } + // ReadProcSched returns a ProcSched and error, if any, for a PID. func ReadProcSched(pid int) (proc ProcSched, err error) { defer func() { err = convertPanicToError(recover()) }() proc = parseProcSched(readProcFile(pid, "sched")) return } -//ParseProcSched processes system process scheduling data and returns a ProcSched and error, if any. + +// ParseProcSched processes system process scheduling data and returns a ProcSched and error, if any. func ParseProcSched(s string) (proc ProcSched, err error) { defer func() { err = convertPanicToError(recover()) }() proc = parseProcSched(s) @@ -39,7 +41,7 @@ func parseProcSched(s string) (proc ProcSched) { s = skipLine(s) // (, #threads: 1) s = skipLine(s) // ------------------------------- - forEachProperty(s, func(key string, val string) { + forEachProperty(s, func(key, val string) { if field := intFields[key]; field != nil { v, e := strconv.ParseUint(val, 10, 64) check(e) diff --git a/procstats/linux/sched_test.go b/procstats/linux/sched_test.go index 1bf71f5..4b80593 100644 --- a/procstats/linux/sched_test.go +++ b/procstats/linux/sched_test.go @@ -26,7 +26,6 @@ clock-delta : 41 ` proc, err := ParseProcSched(text) - if err != nil { t.Error(err) return @@ -43,5 +42,4 @@ clock-delta : 41 }) { t.Error(proc) } - } diff --git a/procstats/linux/stat.go b/procstats/linux/stat.go index df2c90b..5eaa7bc 100644 --- a/procstats/linux/stat.go +++ b/procstats/linux/stat.go @@ -19,6 +19,7 @@ const ( Wakekill ProcState = 'W' Parked ProcState = 'P' ) + // Scan updates the ProcState for a process. func (ps *ProcState) Scan(s fmt.ScanState, _ rune) (err error) { var c rune @@ -30,6 +31,7 @@ func (ps *ProcState) Scan(s fmt.ScanState, _ rune) (err error) { return } + // ProcStat contains statistics associated with a process. type ProcStat struct { Pid int32 // (1) pid diff --git a/procstats/linux/stat_test.go b/procstats/linux/stat_test.go index 7e42bf8..841a917 100644 --- a/procstats/linux/stat_test.go +++ b/procstats/linux/stat_test.go @@ -9,7 +9,6 @@ func TestParseProcStat(t *testing.T) { text := `69 (cat) R 56 1 1 0 -1 4210944 83 0 0 0 0 0 0 0 20 0 1 0 1977676 4644864 193 18446744073709551615 4194304 4240332 140724300789216 140724300788568 140342654634416 0 0 0 0 0 0 0 17 0 0 0 0 0 0 6340112 6341364 24690688 140724300791495 140724300791515 140724300791515 140724300791791 0` proc, err := ParseProcStat(text) - if err != nil { t.Error(err) return diff --git a/procstats/linux/statm_test.go b/procstats/linux/statm_test.go index 4933dbb..451a42c 100644 --- a/procstats/linux/statm_test.go +++ b/procstats/linux/statm_test.go @@ -9,7 +9,6 @@ func TestParseProcStatm(t *testing.T) { text := `1134 172 153 12 0 115 0` proc, err := ParseProcStatm(text) - if err != nil { t.Error(err) return diff --git a/procstats/proc.go b/procstats/proc.go index 02f7241..752adaa 100644 --- a/procstats/proc.go +++ b/procstats/proc.go @@ -154,7 +154,6 @@ func (p *ProcMetrics) Collect() { p.cpu.total.time = (m.CPU.User + m.CPU.Sys) - (p.last.CPU.User + p.last.CPU.Sys) p.cpu.total.percent = 100 * float64(p.cpu.total.time) / interval - } p.memory.available = m.Memory.Available @@ -180,8 +179,7 @@ func (p *ProcMetrics) Collect() { } } - -// ProcInfo contains types which hold statistics for various resources +// ProcInfo contains types which hold statistics for various resources. type ProcInfo struct { CPU CPUInfo Memory MemoryInfo @@ -189,7 +187,7 @@ type ProcInfo struct { Threads ThreadInfo } -// CollectProcInfo return a ProcInfo and error (if any) for a given PID +// CollectProcInfo return a ProcInfo and error (if any) for a given PID. func CollectProcInfo(pid int) (ProcInfo, error) { return collectProcInfo(pid) } @@ -229,6 +227,7 @@ type FileInfo struct { Open uint64 // fds opened by the process Max uint64 // max number of fds the process can open } + // ThreadInfo holds statistics about number of threads and context switches for a process. type ThreadInfo struct { Num uint64 diff --git a/procstats/proc_darwin.go b/procstats/proc_darwin.go index e8137a1..cac113a 100644 --- a/procstats/proc_darwin.go +++ b/procstats/proc_darwin.go @@ -21,6 +21,7 @@ static mach_port_t mach_task_self() { return mach_task_self_; } #endif */ import "C" + import ( "errors" "fmt" @@ -76,7 +77,7 @@ func memoryAvailable() uint64 { return uint64(mem) } -func taskInfo(task C.mach_port_name_t) (virtual uint64, resident uint64, suspend uint64) { +func taskInfo(task C.mach_port_name_t) (virtual, resident, suspend uint64) { info := C.mach_task_basic_info_data_t{} count := C.mach_msg_type_number_t(C.MACH_TASK_BASIC_INFO_COUNT) diff --git a/prometheus/append.go b/prometheus/append.go index ace4d3e..38b1e8c 100644 --- a/prometheus/append.go +++ b/prometheus/append.go @@ -12,7 +12,7 @@ func appendMetricName(b []byte, s string) []byte { return b } -func appendMetricScopedName(b []byte, scope string, name string) []byte { +func appendMetricScopedName(b []byte, scope, name string) []byte { if len(scope) != 0 { b = appendMetricName(b, scope) b = append(b, '_') @@ -44,7 +44,7 @@ func appendMetric(b []byte, metric metric) []byte { return append(b, '\n') } -func appendMetricHelp(b []byte, scope string, name string, help string) []byte { +func appendMetricHelp(b []byte, scope, name, help string) []byte { b = append(b, "# HELP "...) b = appendMetricScopedName(b, scope, name) b = append(b, ' ') @@ -52,7 +52,7 @@ func appendMetricHelp(b []byte, scope string, name string, help string) []byte { return append(b, '\n') } -func appendMetricType(b []byte, scope string, name string, mtype string) []byte { +func appendMetricType(b []byte, scope, name, mtype string) []byte { b = append(b, "# TYPE "...) b = appendMetricScopedName(b, scope, name) b = append(b, ' ') diff --git a/prometheus/handler.go b/prometheus/handler.go index 41c33d1..2a2d102 100644 --- a/prometheus/handler.go +++ b/prometheus/handler.go @@ -61,7 +61,7 @@ func (h *Handler) HandleMeasures(mtime time.Time, measures ...stats.Measure) { for _, f := range m.Fields { var buckets []stats.Value - var mtype = typeOf(f.Type()) + mtype := typeOf(f.Type()) if mtype == histogram { k := stats.Key{Measure: m.Name, Field: f.Name} @@ -137,7 +137,7 @@ func (h *Handler) ServeHTTP(res http.ResponseWriter, req *http.Request) { // WriteStats accepts a writer and pushes metrics (one at a time) to it. // An example could be if you just want to print all the metrics on to Stdout -// It will not call flush. Make sure the Close and Flush are handled at the caller +// It will not call flush. Make sure the Close and Flush are handled at the caller. func (h *Handler) WriteStats(w io.Writer) { b := make([]byte, 1024) @@ -164,7 +164,7 @@ func (h *Handler) WriteStats(w io.Writer) { } } -func acceptEncoding(accept string, check string) bool { +func acceptEncoding(accept, check string) bool { for _, coding := range strings.Split(accept, ",") { if coding = strings.TrimSpace(coding); strings.HasPrefix(coding, check) { return true @@ -187,11 +187,11 @@ func (cache *handleMetricCache) Len() int { return len(cache.labels) } -func (cache *handleMetricCache) Swap(i int, j int) { +func (cache *handleMetricCache) Swap(i, j int) { cache.labels[i], cache.labels[j] = cache.labels[j], cache.labels[i] } -func (cache *handleMetricCache) Less(i int, j int) bool { +func (cache *handleMetricCache) Less(i, j int) bool { return cache.labels[i].less(cache.labels[j]) } diff --git a/prometheus/label.go b/prometheus/label.go index 311045d..96a4ca2 100644 --- a/prometheus/label.go +++ b/prometheus/label.go @@ -2,6 +2,7 @@ package prometheus import ( "github.com/segmentio/fasthash/jody" + "github.com/segmentio/stats/v4" ) diff --git a/prometheus/metric.go b/prometheus/metric.go index 597ec49..d8a81c3 100644 --- a/prometheus/metric.go +++ b/prometheus/metric.go @@ -142,7 +142,7 @@ type metricEntry struct { states metricStateMap } -func newMetricEntry(mtype metricType, scope string, name string, help string) *metricEntry { +func newMetricEntry(mtype metricType, scope, name, help string) *metricEntry { entry := &metricEntry{ mtype: mtype, scope: scope, @@ -406,7 +406,7 @@ func le(buckets []stats.Value) string { // This function converts the byte array to a string without additional // memory allocation. -// Source: https://stackoverflow.com/a/66865482 (license: CC BY-SA 4.0) +// Source: https://stackoverflow.com/a/66865482 (license: CC BY-SA 4.0). func unsafeByteSliceToString(b []byte) string { sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b)) var s string @@ -416,7 +416,7 @@ func unsafeByteSliceToString(b []byte) string { return s } -func nextLe(s string) (head string, tail string) { +func nextLe(s string) (head, tail string) { if i := strings.IndexByte(s, ':'); i >= 0 { head, tail = s[:i], s[i+1:] } else { @@ -435,11 +435,11 @@ func (metrics byNameAndLabels) Len() int { return len(metrics) } -func (metrics byNameAndLabels) Swap(i int, j int) { +func (metrics byNameAndLabels) Swap(i, j int) { metrics[i], metrics[j] = metrics[j], metrics[i] } -func (metrics byNameAndLabels) Less(i int, j int) bool { +func (metrics byNameAndLabels) Less(i, j int) bool { m1 := &metrics[i] m2 := &metrics[j] return m1.name < m2.name || (m1.name == m2.name && m1.labels.less(m2.labels)) diff --git a/statstest/handler.go b/statstest/handler.go index 30e6204..4ff3e74 100644 --- a/statstest/handler.go +++ b/statstest/handler.go @@ -8,8 +8,10 @@ import ( "github.com/segmentio/stats/v4" ) -var _ stats.Handler = (*Handler)(nil) -var _ stats.Flusher = (*Handler)(nil) +var ( + _ stats.Handler = (*Handler)(nil) + _ stats.Flusher = (*Handler)(nil) +) // Handler is a stats handler that can record measures for inspection. type Handler struct { diff --git a/tag.go b/tag.go index 599b3e3..abc8530 100644 --- a/tag.go +++ b/tag.go @@ -14,7 +14,7 @@ type Tag struct { } // T is shorthand for `stats.Tag{Name: "blah", Value: "foo"}` It returns -// the tag for Name k and Value v +// the tag for Name k and Value v. func T(k, v string) Tag { return Tag{Name: k, Value: v} } diff --git a/value.go b/value.go index de365d2..68bd148 100644 --- a/value.go +++ b/value.go @@ -21,8 +21,9 @@ func MustValueOf(v Value) Value { } return v } + // ValueOf inspects v's underlying type and returns a Value which encapsulates this type. -// If the underlying type of v is not supported by Value's encapsulation its Type() will return stats.Invalid +// If the underlying type of v is not supported by Value's encapsulation its Type() will return stats.Invalid. func ValueOf(v interface{}) Value { switch x := v.(type) { case Value: @@ -123,30 +124,37 @@ func float64Value(v float64) Value { func durationValue(v time.Duration) Value { return Value{typ: Duration, bits: uint64(v)} } + // Type returns the Type of this value. func (v Value) Type() Type { return v.typ } + // Bool returns a bool if the underlying data for this value is zero. func (v Value) Bool() bool { return v.bits != 0 } + // Int returns an new int64 representation of this Value. func (v Value) Int() int64 { return int64(v.bits) } + // Uint returns a uint64 representation of this Value. func (v Value) Uint() uint64 { return v.bits } + // Float returns a new float64 representation of this Value. func (v Value) Float() float64 { return math.Float64frombits(v.bits) } + // Duration returns a new time.Duration representation of this Value. func (v Value) Duration() time.Duration { return time.Duration(v.bits) } + // Interface returns an new interface{} representation of this value. // However, if the underlying Type is unsupported it panics. func (v Value) Interface() interface{} { @@ -167,6 +175,7 @@ func (v Value) Interface() interface{} { panic("unknown type found in a stats.Value") } } + // String returns a string representation of the underling value. func (v Value) String() string { switch v.Type() { @@ -186,6 +195,7 @@ func (v Value) String() string { return "" } } + // Type is an int32 type alias used to denote a values underlying type. type Type int32 @@ -199,6 +209,7 @@ const ( Duration Invalid ) + // String returns the string representation of a type. func (t Type) String() string { switch t { @@ -218,6 +229,7 @@ func (t Type) String() string { return "" } } + // GoString implements the GoStringer interface. func (t Type) GoString() string { switch t { diff --git a/veneur/client.go b/veneur/client.go index 30cebea..60578e6 100644 --- a/veneur/client.go +++ b/veneur/client.go @@ -7,7 +7,7 @@ import ( "github.com/segmentio/stats/v4/datadog" ) -// Const Sink Configuration types +// Const Sink Configuration types. const ( GlobalOnly = "veneurglobalonly" LocalOnly = "veneurlocalonly" @@ -18,7 +18,7 @@ const ( KafkaSink = "kafka" ) -// SinkOnly tags +// SinkOnly tags. var ( TagSignalfxOnly = stats.Tag{Name: SinkOnly, Value: SignalfxSink} TagDatadogOnly = stats.Tag{Name: SinkOnly, Value: DatadogSink} @@ -27,7 +27,7 @@ var ( // The ClientConfig type is used to configure veneur clients. // It inherits the datadog config since the veneur client reuses -// the logic in the datadog client to emit metrics +// the logic in the datadog client to emit metrics. type ClientConfig struct { datadog.ClientConfig @@ -57,7 +57,7 @@ func NewClient(addr string) *Client { return NewClientWith(ClientConfig{ClientConfig: datadog.ClientConfig{Address: addr}}) } -// NewClientGlobal creates a client that sends all metrics to the Global Veneur Aggregator +// NewClientGlobal creates a client that sends all metrics to the Global Veneur Aggregator. func NewClientGlobal(addr string) *Client { return NewClientWith(ClientConfig{ClientConfig: datadog.ClientConfig{Address: addr}, GlobalOnly: true}) } @@ -65,7 +65,6 @@ func NewClientGlobal(addr string) *Client { // NewClientWith creates and returns a new veneur client configured with the // given config. func NewClientWith(config ClientConfig) *Client { - // Construct Veneur-specific Tags we will append to measures tags := []stats.Tag{} if config.GlobalOnly { @@ -89,7 +88,6 @@ func NewClientWith(config ClientConfig) *Client { // HandleMeasures satisfies the stats.Handler interface. func (c *Client) HandleMeasures(time time.Time, measures ...stats.Measure) { - // If there are no tags to add, call HandleMeasures with measures directly if len(c.tags) == 0 { c.Client.HandleMeasures(time, measures...) From c7ad59d2e90f38fa61863940cc6525e8b8f6d51d Mon Sep 17 00:00:00 2001 From: Kevin Gillette Date: Tue, 18 Jul 2023 13:04:42 -0600 Subject: [PATCH 3/5] hand-fix some linting issues --- README.md | 2 +- buffer.go | 6 +----- cmd/dogstatsd/main.go | 2 +- datadog/parse.go | 10 ++++++---- datadog/server.go | 29 ++++++++++++++++++++--------- httpstats/metrics.go | 2 +- httpstats/transport.go | 21 +++++++++++---------- 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 30d975c..00fc260 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ type funcMetrics struct { ```go t := time.Now() f() -callTime := time.Now().Sub(t) +callTime := time.Since(t) m := &funcMetrics{} m.calls.count = 1 diff --git a/buffer.go b/buffer.go index b5ddc47..378fb5e 100644 --- a/buffer.go +++ b/buffer.go @@ -132,7 +132,7 @@ type Serializer interface { type buffer struct { lock uint64 data []byte - pad [32]byte // padding to avoid false sharing between threads + _ [32]byte // padding to avoid false sharing between threads } func (b *buffer) acquire() bool { @@ -155,10 +155,6 @@ func (b *buffer) len() int { return len(b.data) } -func (b *buffer) cap() int { - return cap(b.data) -} - func (b *buffer) flush(w io.Writer, n int) { w.Write(b.data[:n]) n = copy(b.data, b.data[n:]) diff --git a/cmd/dogstatsd/main.go b/cmd/dogstatsd/main.go index 59d046d..e8946df 100644 --- a/cmd/dogstatsd/main.go +++ b/cmd/dogstatsd/main.go @@ -101,7 +101,7 @@ func client(cmd string, args ...string) { case "time": start := time.Now() run(extra...) - stats.Observe(name, time.Now().Sub(start), tags...) + stats.Observe(name, time.Since(start), tags...) } } diff --git a/datadog/parse.go b/datadog/parse.go index f4b0fd7..7c9894f 100644 --- a/datadog/parse.go +++ b/datadog/parse.go @@ -222,12 +222,14 @@ func split(s string, b byte) (head, tail string) { func count(s string, b byte) (n int) { for { - if off := strings.IndexByte(s, b); off < 0 { + off := strings.IndexByte(s, b) + if off < 0 { break - } else { - n++ - s = s[off+1:] } + + n++ + s = s[off+1:] } + return } diff --git a/datadog/server.go b/datadog/server.go index 055d182..855ddc2 100644 --- a/datadog/server.go +++ b/datadog/server.go @@ -2,6 +2,7 @@ package datadog import ( "bytes" + "errors" "io" "net" "runtime" @@ -30,7 +31,7 @@ func (f HandlerFunc) HandleMetric(m Metric, a net.Addr) { } // HandleEvent is a no-op for backwards compatibility. -func (f HandlerFunc) HandleEvent(e Event, a net.Addr) { +func (f HandlerFunc) HandleEvent(Event, net.Addr) { return } @@ -49,7 +50,7 @@ func ListenAndServe(addr string, handler Handler) (err error) { // Serve runs a dogstatsd server, listening for datagrams on conn and forwarding // the metrics to handler. -func Serve(conn net.PacketConn, handler Handler) (err error) { +func Serve(conn net.PacketConn, handler Handler) error { defer conn.Close() concurrency := runtime.GOMAXPROCS(-1) @@ -58,22 +59,32 @@ func Serve(conn net.PacketConn, handler Handler) (err error) { } done := make(chan error, concurrency) - conn.SetDeadline(time.Time{}) + err := conn.SetDeadline(time.Time{}) + if err != nil { + return err + } - for i := 0; i != concurrency; i++ { + for i := 0; i < concurrency; i++ { go serve(conn, handler, done) } - for i := 0; i != concurrency; i++ { - switch e := <-done; e { - case nil, io.EOF, io.ErrClosedPipe, io.ErrUnexpectedEOF: + var lastErr error + + for i := 0; i < concurrency; i++ { + err = <-done + switch { + case err == nil: + case errors.Is(err, io.EOF): + case errors.Is(err, io.ErrClosedPipe): + case errors.Is(err, io.ErrUnexpectedEOF): default: - err = e + lastErr = err } + conn.Close() } - return + return lastErr } func serve(conn net.PacketConn, handler Handler, done chan<- error) { diff --git a/httpstats/metrics.go b/httpstats/metrics.go index c34ee79..e38217b 100644 --- a/httpstats/metrics.go +++ b/httpstats/metrics.go @@ -120,7 +120,7 @@ func (r *responseBody) close() { } func (r *responseBody) complete() { - r.metrics.observeResponse(r.res, r.op, r.bytes, time.Now().Sub(r.start)) + r.metrics.observeResponse(r.res, r.op, r.bytes, time.Since(r.start)) r.eng.ReportAt(r.start, r.metrics) } diff --git a/httpstats/transport.go b/httpstats/transport.go index 16c9f7f..889dd3a 100644 --- a/httpstats/transport.go +++ b/httpstats/transport.go @@ -60,17 +60,18 @@ func (t *transport) RoundTrip(req *http.Request) (res *http.Response, err error) req.Body.Close() // nolint if err != nil { - m.observeError(time.Now().Sub(start)) + m.observeError(time.Since(start)) eng.ReportAt(start, m) - } else { - res.Body = &responseBody{ - eng: eng, - res: res, - metrics: m, - body: res.Body, - op: "read", - start: start, - } + return + } + + res.Body = &responseBody{ + eng: eng, + res: res, + metrics: m, + body: res.Body, + op: "read", + start: start, } return From 3b4b0b55e9d6627cc79bd88a7cd04314434bd2e1 Mon Sep 17 00:00:00 2001 From: Kevin Gillette Date: Tue, 18 Jul 2023 13:11:11 -0600 Subject: [PATCH 4/5] just use errgroup instead of reinventing an errgroup --- datadog/server.go | 60 +++++++++++++++++++++++------------------------ go.mod | 1 + go.sum | 2 ++ 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/datadog/server.go b/datadog/server.go index 855ddc2..f876f86 100644 --- a/datadog/server.go +++ b/datadog/server.go @@ -7,6 +7,8 @@ import ( "net" "runtime" "time" + + "golang.org/x/sync/errgroup" ) // Handler defines the interface that types must satisfy to process metrics @@ -58,56 +60,51 @@ func Serve(conn net.PacketConn, handler Handler) error { concurrency = 1 } - done := make(chan error, concurrency) err := conn.SetDeadline(time.Time{}) if err != nil { return err } - for i := 0; i < concurrency; i++ { - go serve(conn, handler, done) - } - - var lastErr error + var errgrp errgroup.Group for i := 0; i < concurrency; i++ { - err = <-done - switch { - case err == nil: - case errors.Is(err, io.EOF): - case errors.Is(err, io.ErrClosedPipe): - case errors.Is(err, io.ErrUnexpectedEOF): - default: - lastErr = err - } + errgrp.Go(func() error { + return serve(conn, handler) + }) + } - conn.Close() + err = errgrp.Wait() + switch { + default: + return err + case err == nil: + case errors.Is(err, io.EOF): + case errors.Is(err, io.ErrClosedPipe): + case errors.Is(err, io.ErrUnexpectedEOF): } - return lastErr + return nil } -func serve(conn net.PacketConn, handler Handler, done chan<- error) { +func serve(conn net.PacketConn, handler Handler) error { b := make([]byte, 65536) for { n, a, err := conn.ReadFrom(b) if err != nil { - done <- err - return + return err } for s := b[:n]; len(s) != 0; { - var ln []byte - var off int - - if off = bytes.IndexByte(s, '\n'); off < 0 { + off := bytes.IndexByte(s, '\n') + if off < 0 { off = len(s) } else { off++ } - ln, s = s[:off], s[off:] + ln := s[:off] + s = s[off:] if bytes.HasPrefix(ln, []byte("_e")) { e, err := parseEvent(string(ln)) @@ -116,14 +113,15 @@ func serve(conn net.PacketConn, handler Handler, done chan<- error) { } handler.HandleEvent(e, a) - } else { - m, err := parseMetric(string(ln)) - if err != nil { - continue - } + continue + } - handler.HandleMetric(m, a) + m, err := parseMetric(string(ln)) + if err != nil { + continue } + + handler.HandleMetric(m, a) } } } diff --git a/go.mod b/go.mod index 3f89c7b..2ada8f1 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/net v0.7.0 // indirect + golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.5.0 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index dbc101e..5194c1c 100644 --- a/go.sum +++ b/go.sum @@ -35,6 +35,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= From fd74c9fcd1e50dd164a995ba388d3bb5bb17b76e Mon Sep 17 00:00:00 2001 From: Kevin Gillette Date: Wed, 19 Jul 2023 10:46:55 -0600 Subject: [PATCH 5/5] Update context.go Co-authored-by: Kevin Burke --- context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/context.go b/context.go index bf31431..7f9c28e 100644 --- a/context.go +++ b/context.go @@ -62,7 +62,7 @@ type tagSlice struct { // for defining context keys was copied from Go 1.7's new use of context in net/http. type tagsKey struct{} -// String is Stringer implementation. +// String implements the fmt.Stringer interface. func (k tagsKey) String() string { return "stats_tags_context_key" }