From 43c2422743c935acf334a427148421d0cb683aee Mon Sep 17 00:00:00 2001 From: maier Date: Fri, 2 Apr 2021 17:19:40 -0400 Subject: [PATCH 1/7] upd: lint ver upd: stricter linting fix: lint issues --- .github/workflows/golangci-lint.yml | 2 +- .golangci.yml | 227 ++---------------- api/api.go | 29 ++- api/get.go | 15 +- api/get_test.go | 39 +-- api/inventory.go | 9 +- api/inventory_test.go | 2 +- api/metrics.go | 7 +- api/metrics_test.go | 4 +- api/write.go | 21 +- cmd/root.go | 7 +- go.mod | 11 +- go.sum | 20 +- internal/agent/agent.go | 46 ++-- internal/agent/sighndlr_bsdsol.go | 2 +- internal/agent/sighndlr_linux.go | 2 +- internal/agent/sighndlr_windows.go | 2 +- internal/builtins/builtins.go | 14 +- internal/builtins/builtins_test.go | 6 + internal/builtins/collector/collector.go | 10 +- .../builtins/collector/generic/collector.go | 25 +- .../collector/generic/collector_test.go | 6 +- internal/builtins/collector/generic/cpu.go | 15 +- internal/builtins/collector/generic/disk.go | 14 +- internal/builtins/collector/generic/fs.go | 19 +- .../builtins/collector/generic/generic.go | 9 +- internal/builtins/collector/generic/load.go | 18 +- internal/builtins/collector/generic/net_if.go | 17 +- .../builtins/collector/generic/net_proto.go | 22 +- internal/builtins/collector/generic/vm.go | 14 +- .../collector/linux/procfs/collector.go | 34 +-- .../collector/linux/procfs/collector_test.go | 4 +- .../builtins/collector/linux/procfs/cpu.go | 48 ++-- .../builtins/collector/linux/procfs/disk.go | 61 +++-- .../builtins/collector/linux/procfs/load.go | 24 +- .../builtins/collector/linux/procfs/net_if.go | 27 +-- .../collector/linux/procfs/net_proto.go | 31 ++- .../collector/linux/procfs/net_socket.go | 31 ++- .../builtins/collector/linux/procfs/procfs.go | 10 +- .../builtins/collector/linux/procfs/vm.go | 30 +-- .../collector/prometheus/collector.go | 21 +- .../collector/prometheus/collector_test.go | 6 +- .../collector/prometheus/prometheus.go | 35 +-- .../collector/windows/nvidia/collector.go | 10 +- .../builtins/collector/windows/nvidia/gpu.go | 38 +-- .../collector/windows/nvidia/nvidia.go | 4 +- .../builtins/collector/windows/wmi/cache.go | 21 +- .../collector/windows/wmi/collector.go | 23 +- .../collector/windows/wmi/collector_test.go | 4 +- .../builtins/collector/windows/wmi/disk.go | 32 +-- .../builtins/collector/windows/wmi/memory.go | 23 +- .../windows/wmi/network_interface.go | 24 +- .../collector/windows/wmi/network_ip.go | 31 +-- .../collector/windows/wmi/network_tcp.go | 31 +-- .../collector/windows/wmi/network_udp.go | 31 +-- .../builtins/collector/windows/wmi/objects.go | 23 +- .../collector/windows/wmi/paging_file.go | 26 +- .../collector/windows/wmi/processes.go | 24 +- .../collector/windows/wmi/processor.go | 25 +- .../builtins/collector/windows/wmi/system.go | 21 +- .../builtins/collector/windows/wmi/wmi.go | 15 +- internal/builtins/configure.go | 3 +- internal/builtins/configure_linux.go | 5 +- internal/builtins/configure_windows.go | 7 +- internal/check/api.go | 2 +- internal/check/api_test.go | 26 +- internal/check/broker.go | 27 ++- internal/check/broker_test.go | 7 +- internal/check/bundle/api.go | 2 +- internal/check/bundle/api_test.go | 22 +- internal/check/bundle/broker.go | 18 +- internal/check/bundle/bundle.go | 126 ++++++---- internal/check/bundle/bundle_test.go | 7 +- internal/check/check.go | 67 +++--- internal/check/reverse.go | 19 +- internal/check/reverse_test.go | 4 +- internal/config/address.go | 10 +- internal/config/api.go | 20 +- internal/config/api_test.go | 12 +- internal/config/config.go | 181 +++++++------- internal/config/cosi.go | 59 ++--- internal/config/cosi_test.go | 90 ++++--- internal/config/defaults/defaults.go | 101 ++++---- internal/config/load_config.go | 14 +- internal/config/reverse.go | 10 +- internal/config/reverse_test.go | 10 +- internal/config/verifyfile.go | 16 +- internal/multiagent/multiagent.go | 42 ++-- internal/plugins/plugin.go | 35 ++- internal/plugins/plugin_test.go | 13 +- internal/plugins/plugins.go | 33 ++- internal/plugins/plugins_test.go | 5 +- internal/plugins/scan.go | 19 +- internal/release/main.go | 16 +- .../reverse/connection/command_processor.go | 11 +- internal/reverse/connection/command_reader.go | 10 +- internal/reverse/connection/connection.go | 35 ++- .../reverse/connection/connection_test.go | 1 - internal/reverse/connection/frame.go | 17 +- internal/reverse/connection/metrics.go | 14 +- internal/reverse/reverse.go | 25 +- internal/reverse/reverse_test.go | 1 - internal/server/agent_host_stats.go | 4 +- internal/server/agent_host_stats_openbsd.go | 2 +- internal/server/agent_mem_stats.go | 2 +- internal/server/agent_mem_stats_solaris.go | 2 +- internal/server/agent_mem_stats_windows.go | 2 +- internal/server/agent_stats.go | 2 +- internal/server/handlers.go | 10 +- internal/server/promrecv/promrecv.go | 12 +- internal/server/receiver/receiver.go | 14 +- internal/server/receiver/receiver_test.go | 15 +- internal/server/server.go | 16 +- internal/server/server_test.go | 4 +- internal/statsd/metrics.go | 14 +- internal/statsd/metrics_test.go | 28 +-- internal/statsd/statsd.go | 72 +++--- internal/statsd/statsd_test.go | 48 ++-- internal/tags/tags.go | 31 +-- main.go | 2 +- 120 files changed, 1376 insertions(+), 1448 deletions(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 75119eb4..e1cf7049 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -15,5 +15,5 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: - version: v1.38 + version: v1.39 args: --timeout=5m diff --git a/.golangci.yml b/.golangci.yml index d862e908..983ac6c9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,173 +1,30 @@ run: - # default is true. Enables skipping of directories: - # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + concurrency: 4 + timeout: 1m + issues-exit-code: 1 + tests: true skip-dirs-use-default: true skip-files: - ".*_mock_test.go$" - # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": - # If invoked with -mod=readonly, the go command is disallowed from the implicit - # automatic updating of go.mod described above. Instead, it fails when any changes - # to go.mod are needed. This setting is most useful to check that go.mod does - # not need updates, such as in a continuous integration and testing system. - # If invoked with -mod=vendor, the go command assumes that the vendor - # directory holds the correct copies of dependencies and ignores - # the dependency descriptions in go.mod. - #commented out for: https://github.com/golangci/golangci-lint/issues/1502 - #modules-download-mode: readonly + allow-parallel-runners: true # all available settings of specific linters linters-settings: - errcheck: - # report about not checking of errors in type assetions: `a := b.(MyStruct)`; - # default is false: such cases aren't reported by default. - check-type-assertions: false - - # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; - # default is false: such cases aren't reported by default. - check-blank: false - - funlen: - lines: 100 - statements: 50 - govet: - # report about shadowed variables check-shadowing: true - - # settings per analyzer - # settings: - # printf: # analyzer name, run `go tool vet help` to see all analyzers - # funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer - # - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - # - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - # - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - # - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf - - # enable or disable analyzers by name - # enable: - # - atomicalign enable-all: true - # disable: - # - shadow - # disable-all: false golint: - # minimal confidence for issues, default is 0.8 min-confidence: 0.8 gofmt: - # simplify code: gofmt with `-s` option, true by default simplify: true goimports: - # put imports beginning with prefix after 3rd-party packages; - # it's a comma-separated list of prefixes - local-prefixes: github.com/circonus-labs - gocyclo: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 10 - gocognit: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 10 - dupl: - # tokens count to trigger issue, 150 by default - threshold: 100 - goconst: - # minimal length of string constant, 3 by default - min-len: 3 - # minimal occurrences count to trigger, 3 by default - min-occurrences: 3 - depguard: - # list-type: blacklist - # include-go-root: false - # packages: - # - github.com/sirupsen/logrus - # packages-with-error-messages: - # # specify an error message to output when a blacklisted package is used - # github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" + local-prefixes: github.com/circonus-labs,github.com/openhistogram,github.com/circonus misspell: - # Correct spellings using locale preferences for US or UK. - # Default is to use a neutral variety of English. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. locale: US - # ignore-words: - # - someword - lll: - # max line length, lines longer will be reported. Default is 120. - # '\t' is counted as 1 character by default, and can be changed with the tab-width option - line-length: 120 - # tab width in spaces. Default to 1. - tab-width: 1 unused: - # treat code as a program (not a library) and report unused exported identifiers; default is false. - # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: - # if it's called for subdir of a project it can't find funcs usages. All text editor integrations - # with golangci-lint call it on a directory with the changed file. check-exported: false unparam: - # Inspect exported functions, default is false. Set to true if no external program/library imports your code. - # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: - # if it's called for subdir of a project it can't find external interfaces. All text editor integrations - # with golangci-lint call it on a directory with the changed file. check-exported: false - nakedret: - # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 - max-func-lines: 30 - prealloc: - # XXX: we don't recommend using this linter before doing performance profiling. - # For most programs usage of prealloc will be a premature optimization. - - # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. - # True by default. - simple: true - range-loops: true # Report preallocation suggestions on range loops, true by default - for-loops: false # Report preallocation suggestions on for loops, false by default - gocritic: - # # Which checks should be enabled; can't be combined with 'disabled-checks'; - # # See https://go-critic.github.io/overview#checks-overview - # # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` - # # By default list of stable checks is used. - # enabled-checks: - # - rangeValCopy - - # # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty - # disabled-checks: - # - regexpMust - - # # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. - # # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". - # enabled-tags: - # - performance - - # settings: # settings passed to gocritic - # captLocal: # must be valid enabled check name - # paramsOnly: true - # rangeValCopy: - # sizeThreshold: 32 - godox: - # # report any comments starting with keywords, this is useful for TODO or FIXME comments that - # # might be left in the code accidentally and should be resolved before merging - # keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting - # - NOTE - # - OPTIMIZE # marks code that should be optimized before merging - # - HACK # marks hack-arounds that should be removed before merging - dogsled: - # checks assignments with too many blank identifiers; default is 2 - max-blank-identifiers: 2 - - whitespace: - multi-if: false # Enforces newlines (or comments) after every multi-line if statement - multi-func: false # Enforces newlines (or comments) after every multi-line function signature - wsl: - # If true append is only allowed to be cuddled if appending value is - # matching variables, fields or types on line above. Default is true. - strict-append: true - # Allow calls and assignments to be cuddled as long as the lines have any - # matching variables, fields or types. Default is true. - allow-assign-and-call: true - # Allow multiline assignments to be cuddled. Default is true. - allow-multiline-assign: true - # Allow case blocks to end with a whitespace. - allow-case-traling-whitespace: true - # Allow declarations (var) to be cuddled. - allow-cuddle-declarations: false linters: enable: @@ -183,80 +40,24 @@ linters: - megacheck - misspell - prealloc - - scopelint - staticcheck - structcheck - typecheck - unparam - unused - varcheck + - gci + - godot + - godox + - goerr113 + - predeclared + - unconvert + - wrapcheck disable: + - scopelint # - prealloc disable-all: false presets: - bugs - unused fast: false - - -issues: - # List of regexps of issue texts to exclude, empty list by default. - # But independently from this option we use default exclude patterns, - # it can be disabled by `exclude-use-default: false`. To list all - # excluded by default patterns execute `golangci-lint run --help` - exclude: - - abcdef - - # Excluding configuration per-path, per-linter, per-text and per-source - exclude-rules: - # Exclude some linters from running on tests files. - - path: _test\.go - linters: - - gocyclo - - errcheck - - dupl - - gosec - - # Exclude known linters from partially hard-vendored code, - # which is impossible to exclude via "nolint" comments. - - path: internal/hmac/ - text: "weak cryptographic primitive" - linters: - - gosec - - # Exclude some staticcheck messages - - linters: - - staticcheck - text: "SA9003:" - - # Exclude lll issues for long lines with go:generate - - linters: - - lll - source: "^//go:generate " - - # # Independently from option `exclude` we use default exclude patterns, - # # it can be disabled by this option. To list all - # # excluded by default patterns execute `golangci-lint run --help`. - # # Default value for this option is true. - # exclude-use-default: false - - # Maximum issues count per one linter. Set to 0 to disable. Default is 50. - max-issues-per-linter: 0 - - # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. - max-same-issues: 0 - - # # Show only new issues: if there are unstaged changes or untracked files, - # # only those changes are analyzed, else only changes in HEAD~ are analyzed. - # # It's a super-useful option for integration of golangci-lint into existing - # # large codebase. It's not practical to fix all existing issues at the moment - # # of integration: much better don't allow issues in new code. - # # Default is false. - # new: false - - # # Show only new issues created after git revision `REV` - # new-from-rev: REV - - # # Show only new issues created in git patch with set file path. - # new-from-patch: path/to/patch/file - diff --git a/api/api.go b/api/api.go index 08d98df1..dfdcfb26 100644 --- a/api/api.go +++ b/api/api.go @@ -6,31 +6,30 @@ package api import ( + "fmt" "net/url" "regexp" - - "github.com/pkg/errors" ) -// Client defines the circonus-agent api client configuration +// Client defines the circonus-agent api client configuration. type Client struct { agentURL *url.URL pidVal *regexp.Regexp } -// Metric defines an individual metric +// Metric defines an individual metric. type Metric struct { Value interface{} `json:"_value"` Type string `json:"_type"` } -// Metrics holds host metrics +// Metrics holds host metrics. type Metrics map[string]Metric -// Inventory defines list of active plugins +// Inventory defines list of active plugins. type Inventory []Plugin -// Plugin defines an active plugin +// Plugin defines an active plugin. type Plugin struct { ID string `json:"id"` // combination of name`instance Name string `json:"name"` @@ -43,15 +42,25 @@ type Plugin struct { Args []string `json:"args"` } -// New creates a new circonus-agent api client +var ( + errInvalidAgentURL = fmt.Errorf("invalid agent URL (empty)") + errInvalidRequestPath = fmt.Errorf("invalid request path (empty)") + errInvalidHTTPResponse = fmt.Errorf("invalid HTTP response") + errInvalidPluginID = fmt.Errorf("invalid plugin ID") + errInvalidGroupID = fmt.Errorf("invalid group id (empty)") + errInvalidMetrics = fmt.Errorf("invalid metrics (nil)") + errInvalidMetricList = fmt.Errorf("invalid metrics (none)") +) + +// New creates a new circonus-agent api client. func New(agentURL string) (*Client, error) { if agentURL == "" { - return nil, errors.New("invalid agent URL (empty)") + return nil, errInvalidAgentURL } u, err := url.Parse(agentURL) if err != nil { - return nil, err + return nil, fmt.Errorf("url parse: %w", err) } pv := regexp.MustCompile("^[a-zA-Z0-9_-`]+$") // e.g. pluginName or pluginName`instanceID diff --git a/api/get.go b/api/get.go index ff401493..e2d52102 100644 --- a/api/get.go +++ b/api/get.go @@ -7,42 +7,41 @@ package api import ( "context" + "fmt" "io/ioutil" "net/http" "strings" - - "github.com/pkg/errors" ) func (c *Client) get(ctx context.Context, reqpath string) ([]byte, error) { if reqpath == "" { - return nil, errors.New("invalid request path (empty)") + return nil, errInvalidRequestPath } au, err := c.agentURL.Parse(reqpath) if err != nil { - return nil, errors.Wrap(err, "creating request url") + return nil, fmt.Errorf("creating request URL: %w", err) } client := &http.Client{} req, err := http.NewRequestWithContext(ctx, "GET", au.String(), nil) if err != nil { - return nil, errors.Wrap(err, "preparing request") + return nil, fmt.Errorf("preparing reqeust: %w", err) } resp, err := client.Do(req) if err != nil { - return nil, errors.Wrap(err, "request") + return nil, fmt.Errorf("do request (%s): %w", au.String(), err) } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { - return nil, errors.Wrap(err, "reading response") + return nil, fmt.Errorf("reading response: %w", err) } if resp.StatusCode != http.StatusOK { - return nil, errors.Errorf("%s - %s - %s", resp.Status, au.String(), strings.TrimSpace(string(data))) + return nil, fmt.Errorf("%s - %s - %s: %w", resp.Status, au.String(), strings.TrimSpace(string(data)), errInvalidHTTPResponse) } return data, nil diff --git a/api/get_test.go b/api/get_test.go index 399df943..b14306f3 100644 --- a/api/get_test.go +++ b/api/get_test.go @@ -7,6 +7,7 @@ package api import ( "context" + "errors" "net/http" "net/http/httptest" "testing" @@ -31,16 +32,17 @@ func TestGet(t *testing.T) { t.Fatalf("unexpected error (%s)", err) } - tests := []struct { - name string - rpath string - expectedErr string - shouldErr bool + tests := []struct { //nolint:govet + name string + rpath string + expectedErr error + expectedErrStr string + shouldErr bool }{ - {"invalid path (empty)", "", "invalid request path (empty)", true}, - {"invalid path (bad)", "/%/%", `creating request url: parse "/%/%": invalid URL escape "%/%"`, true}, - {"invalid path (not found)", "/not_found", "404 Not Found - " + ts.URL + "/not_found - Not Found", true}, - {"valid", "/valid", "", false}, + {"invalid path (empty)", "", errInvalidRequestPath, "", true}, + {"invalid path (bad)", "/%/%", nil, `creating request URL: parse "/%/%": invalid URL escape "%/%"`, true}, + {"invalid path (not found)", "/not_found", errInvalidHTTPResponse, "", true}, // "404 Not Found - " + ts.URL + "/not_found - Not Found", true}, + {"valid", "/valid", nil, "", false}, } for _, test := range tests { @@ -49,15 +51,20 @@ func TestGet(t *testing.T) { _, err := c.get(context.Background(), test.rpath) if test.shouldErr { - if err == nil { + switch { + case err == nil: t.Fatal("expected error") + case test.expectedErr != nil: + if !errors.Is(err, test.expectedErr) { + // if err.Error() != test.expectedErr { + t.Fatalf("unexpected error (%s)", err) + } + case test.expectedErrStr != "": + if err.Error() != test.expectedErrStr { + t.Fatalf("unexpected error (%s)", err) + } } - if err.Error() != test.expectedErr { - t.Fatalf("unexpected error (%s)", err) - } - continue - } - if err != nil { + } else if err != nil { t.Fatalf("expected no error, got (%s)", err) } } diff --git a/api/inventory.go b/api/inventory.go index 1a314199..e4c0a7b0 100644 --- a/api/inventory.go +++ b/api/inventory.go @@ -8,16 +8,15 @@ package api import ( "context" "encoding/json" - - "github.com/pkg/errors" + "fmt" ) -// Inventory retrieves the active plugin inventory from the agent +// Inventory retrieves the active plugin inventory from the agent. func (c *Client) Inventory() (*Inventory, error) { return c.InventoryWithContext(context.Background()) } -// InventoryWithContext retrieves the active plugin inventory from the agent +// InventoryWithContext retrieves the active plugin inventory from the agent. func (c *Client) InventoryWithContext(ctx context.Context) (*Inventory, error) { data, err := c.get(ctx, "/inventory/") if err != nil { @@ -26,7 +25,7 @@ func (c *Client) InventoryWithContext(ctx context.Context) (*Inventory, error) { var v Inventory if err := json.Unmarshal(data, &v); err != nil { - return nil, errors.Wrap(err, "parsing inventory") + return nil, fmt.Errorf("json parse - inventory: %w", err) } return &v, nil diff --git a/api/inventory_test.go b/api/inventory_test.go index 561b68d6..44ddf1e3 100644 --- a/api/inventory_test.go +++ b/api/inventory_test.go @@ -20,7 +20,7 @@ func TestInventory(t *testing.T) { expectedErr string shouldErr bool }{ - {"invalid (json/parse)", "invalid", "parsing inventory: invalid character 'i' looking for beginning of value", true}, + {"invalid (json/parse)", "invalid", "json parse - inventory: invalid character 'i' looking for beginning of value", true}, {"valid", `[{"id":"test","name":"test","instance":""}]`, "", false}, } diff --git a/api/metrics.go b/api/metrics.go index ecb14534..2609194c 100644 --- a/api/metrics.go +++ b/api/metrics.go @@ -8,8 +8,7 @@ package api import ( "context" "encoding/json" - - "github.com/pkg/errors" + "fmt" ) // Metrics retrieves metrics from one or all plugins @@ -28,7 +27,7 @@ func (c *Client) MetricsWithContext(ctx context.Context, pluginID string) (*Metr pid := "" if pluginID != "" { if !c.pidVal.MatchString(pluginID) { - return nil, errors.Errorf("invalid plugin id (%s)", pluginID) + return nil, fmt.Errorf("%s: %w", pluginID, errInvalidPluginID) } pid = pluginID } @@ -44,7 +43,7 @@ func (c *Client) MetricsWithContext(ctx context.Context, pluginID string) (*Metr var v Metrics if err := json.Unmarshal(data, &v); err != nil { - return nil, errors.Wrap(err, "parsing metrics") + return nil, fmt.Errorf("json parse - metrics: %w", err) } return &v, nil diff --git a/api/metrics_test.go b/api/metrics_test.go index 7c13e0d4..6c6fc558 100644 --- a/api/metrics_test.go +++ b/api/metrics_test.go @@ -21,8 +21,8 @@ func TestMetrics(t *testing.T) { expectedErr string shouldErr bool }{ - {"invalid (plugin id)", "[invalid]", "", "invalid plugin id ([invalid])", true}, - {"invalid (json/parse)", "", "invalid", "parsing metrics: invalid character 'i' looking for beginning of value", true}, + {"invalid (plugin id)", "[invalid]", "", "[invalid]: invalid plugin ID", true}, + {"invalid (json/parse)", "", "invalid", "json parse - metrics: invalid character 'i' looking for beginning of value", true}, {"valid", "", `{"foo":{"_type":"n", "_value":3.12}}`, "", false}, {"valid (plugin id)", "bar", "{\"bar`test\":{\"_type\":\"i\", \"_value\":1}}", "", false}, } diff --git a/api/write.go b/api/write.go index 0ca98831..31058119 100644 --- a/api/write.go +++ b/api/write.go @@ -9,11 +9,10 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io/ioutil" "net/http" "strings" - - "github.com/pkg/errors" ) func (c *Client) Write(groupID string, metrics *Metrics) error { @@ -22,34 +21,34 @@ func (c *Client) Write(groupID string, metrics *Metrics) error { func (c *Client) WriteWithContext(ctx context.Context, groupID string, metrics *Metrics) error { if groupID == "" { - return errors.New("invalid group id (empty)") + return errInvalidGroupID } if metrics == nil { - return errors.New("invalid metrics (nil)") + return errInvalidMetrics } if len(*metrics) == 0 { - return errors.New("invalid metrics (none)") + return errInvalidMetricList } au, err := c.agentURL.Parse("/write/" + groupID) if err != nil { - return errors.Wrap(err, "creating request url") + return fmt.Errorf("creating request url: %w", err) } m, err := json.Marshal(metrics) if err != nil { - return errors.Wrap(err, "converting metrics to JSON") + return fmt.Errorf("json encode - metrics: %w", err) } client := &http.Client{} req, err := http.NewRequestWithContext(ctx, "POST", au.String(), bytes.NewBuffer(m)) if err != nil { - return errors.Wrap(err, "preparing request") + return fmt.Errorf("preparing request: %w", err) } resp, err := client.Do(req) if err != nil { - return errors.Wrap(err, "request") + return fmt.Errorf("do request: %w", err) } switch resp.StatusCode { @@ -62,9 +61,9 @@ func (c *Client) WriteWithContext(ctx context.Context, groupID string, metrics * defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { - return errors.Wrap(err, "reading response") + return fmt.Errorf("reading response: %w", err) } - return errors.Errorf("%s - %s - %s", resp.Status, au.String(), strings.TrimSpace(string(data))) + return fmt.Errorf("%s - %s - %s: %w", resp.Status, au.String(), strings.TrimSpace(string(data)), errInvalidHTTPResponse) } } diff --git a/cmd/root.go b/cmd/root.go index a0231dce..472397be 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,7 +18,6 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/config/defaults" "github.com/circonus-labs/circonus-agent/internal/release" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" @@ -27,7 +26,7 @@ import ( var cfgFile string -// RootCmd represents the base command when called without any subcommands +// RootCmd represents the base command when called without any subcommands. var RootCmd = &cobra.Command{ Use: release.NAME, Short: "Circonus Host Agent", @@ -1410,7 +1409,7 @@ func init() { } -// initLogging initializes zerolog +// initLogging initializes zerolog. func initLogging(cmd *cobra.Command, args []string) error { // // Enable formatted output @@ -1450,7 +1449,7 @@ func initLogging(cmd *cobra.Command, args []string) error { case "disabled": zerolog.SetGlobalLevel(zerolog.Disabled) default: - return errors.Errorf("Unknown log level (%s)", level) + return fmt.Errorf("Unknown log level (%s)", level) //nolint:goerr113 } log.Debug().Str("log-level", level).Msg("Logging level") diff --git a/go.mod b/go.mod index ef3f59ce..3ef470ea 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,11 @@ module github.com/circonus-labs/circonus-agent require ( code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48 - github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d + github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 + github.com/bi-zone/wmi v1.1.4 github.com/circonus-labs/circonus-gometrics/v3 v3.4.0 github.com/circonus-labs/go-apiclient v0.7.13 - github.com/go-ole/go-ole v1.2.4 // indirect github.com/gojuno/minimock/v3 v3.0.8 github.com/google/uuid v1.2.0 github.com/hashicorp/go-hclog v0.10.1 // indirect @@ -14,11 +14,10 @@ require ( github.com/maier/go-appstats v0.2.0 github.com/onsi/ginkgo v1.14.0 // indirect github.com/pelletier/go-toml v1.8.1 - github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.2.0 github.com/prometheus/common v0.20.0 github.com/rs/zerolog v1.21.0 - github.com/shirou/gopsutil v3.21.2+incompatible + github.com/shirou/gopsutil v3.21.3+incompatible github.com/spf13/afero v1.2.2 // indirect github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cobra v1.1.3 @@ -26,9 +25,9 @@ require ( github.com/spf13/viper v1.7.1 github.com/tklauser/go-sysconf v0.3.5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 + golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 gopkg.in/ini.v1 v1.51.1 // indirect gopkg.in/yaml.v2 v2.4.0 ) -go 1.15 +go 1.16 diff --git a/go.sum b/go.sum index c23da49c..fa92cc14 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,10 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bi-zone/go-ole v1.2.5 h1:/4G2KrTbq1e3FsMkd40quzwIrLb4QdxZJnUUlG7UjcM= +github.com/bi-zone/go-ole v1.2.5/go.mod h1:BxzT498d9QAq10L6G/pTMscpDzqnpKN6DUBbmFKwyQY= +github.com/bi-zone/wmi v1.1.4 h1:82DmCVK/Qf0MKSvUP52tfoJPsD/LPebHI1gZMN6izG4= +github.com/bi-zone/wmi v1.1.4/go.mod h1:ydCNZo9UgRmfvgWAGZmyiaE/J4VbIFjcIJ1bftDIgwM= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -125,6 +129,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gonuts/commander v0.1.0/go.mod h1:qkb5mSlcWodYgo7vs8ulLnXhfinhZsZcm6+H/z1JjgY= +github.com/gonuts/flag v0.1.0/go.mod h1:ZTmTGtrSPejTo/SRNhCqwLTmiAgyBdCkLYhHrAoBdz4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -158,6 +164,7 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -166,6 +173,7 @@ github.com/hashicorp/go-hclog v0.10.1 h1:uyt/l0dWjJ879yiAu+T7FG3/6QX+zwm4bQ8P7Xs github.com/hashicorp/go-hclog v0.10.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= @@ -334,9 +342,11 @@ github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e h1:+/AzLkOdIXEPrAQtwAeWOBnPQ0BnYlBW0aCZmSb47u4= +github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e/go.mod h1:9Tc1SKnfACJb9N7cw2eyuI6xzy845G7uZONBsi5uPEA= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil v3.21.2+incompatible h1:U+YvJfjCh6MslYlIAXvPtzhW3YZEtc9uncueUNpD/0A= -github.com/shirou/gopsutil v3.21.2+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.3+incompatible h1:uenXGGa8ESCQq+dbgtl916dmg6PSAz2cXov0uORQ9v8= +github.com/shirou/gopsutil v3.21.3+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -489,6 +499,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -498,11 +509,12 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200806060901-a37d78b92225/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= diff --git a/internal/agent/agent.go b/internal/agent/agent.go index ff6e3b77..7ca5a3cd 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -7,6 +7,7 @@ package agent import ( "context" + "fmt" "os" "os/signal" @@ -26,7 +27,7 @@ import ( "golang.org/x/sync/errgroup" ) -// Agent holds the main circonus-agent process +// Agent holds the main circonus-agent process. type Agent struct { group *errgroup.Group groupCtx context.Context @@ -42,7 +43,7 @@ type Agent struct { logger zerolog.Logger } -// New returns a new agent instance +// New returns a new agent instance. func New() (*Agent, error) { ctx, cancel := context.WithCancel(context.Background()) g, gctx := errgroup.WithContext(ctx) @@ -58,53 +59,53 @@ func New() (*Agent, error) { err = config.Validate() if err != nil { - return nil, err + return nil, fmt.Errorf("config validate: %w", err) } a.check, err = check.New(nil) if err != nil { - return nil, err + return nil, fmt.Errorf("init check: %w", err) } a.builtins, err = builtins.New(a.groupCtx) if err != nil { - return nil, err + return nil, fmt.Errorf("init builtins: %w", err) } a.plugins, err = plugins.New(a.groupCtx, defaults.PluginPath) if err != nil { - return nil, err + return nil, fmt.Errorf("init plugins: %w", err) } if err = a.plugins.Scan(a.builtins); err != nil { - return nil, err + return nil, fmt.Errorf("scan plugins: %w", err) } a.statsdServer, err = statsd.New(a.groupCtx) if err != nil { - return nil, err + return nil, fmt.Errorf("init statsd: %w", err) } a.listenServer, err = server.New(a.groupCtx, a.check, a.builtins, a.plugins, a.statsdServer) if err != nil { - return nil, err + return nil, fmt.Errorf("init server: %w", err) } agentAddress, err := a.listenServer.GetReverseAgentAddress() if err != nil { - return nil, err + return nil, fmt.Errorf("agent addr: %w", err) } if viper.GetBool(config.KeyReverse) { a.reverseConn, err = reverse.New(a.logger, a.check, agentAddress) if err != nil { - return nil, err + return nil, fmt.Errorf("init reverse: %w", err) } } if viper.GetBool(config.KeyMultiAgent) { a.submitter, err = multiagent.New(a.logger, a.check, a.listenServer) if err != nil { - return nil, err + return nil, fmt.Errorf("init multi-agent: %w", err) } } @@ -113,18 +114,24 @@ func New() (*Agent, error) { return &a, nil } -// Start the agent +// Start the agent. func (a *Agent) Start() error { a.group.Go(a.handleSignals) a.group.Go(a.statsdServer.Start) if viper.GetBool(config.KeyReverse) { a.group.Go(func() error { - return a.reverseConn.Start(a.groupCtx) + if err := a.reverseConn.Start(a.groupCtx); err != nil { + return fmt.Errorf("start reverse: %w", err) + } + return nil }) } if viper.GetBool(config.KeyMultiAgent) { a.group.Go(func() error { - return a.submitter.Start(a.groupCtx) + if err := a.submitter.Start(a.groupCtx); err != nil { + return fmt.Errorf("start submitter: %w", err) + } + return nil }) } a.group.Go(a.listenServer.Start) @@ -134,10 +141,13 @@ func (a *Agent) Start() error { Str("name", release.NAME). Str("ver", release.VERSION).Msg("Starting wait") - return a.group.Wait() + if err := a.group.Wait(); err != nil { + return fmt.Errorf("start agent: %w", err) + } + return nil } -// Stop cleans up and shuts down the Agent +// Stop cleans up and shuts down the Agent. func (a *Agent) Stop() { a.stopSignalHandler() a.groupCancel() @@ -148,7 +158,7 @@ func (a *Agent) Stop() { Str("ver", release.VERSION).Msg("Stopped") } -// stopSignalHandler disables the signal handler +// stopSignalHandler disables the signal handler. func (a *Agent) stopSignalHandler() { signal.Stop(a.signalCh) signal.Reset() // so a second ctrl-c will force immediate stop diff --git a/internal/agent/sighndlr_bsdsol.go b/internal/agent/sighndlr_bsdsol.go index 48fdedf0..67f64e9f 100644 --- a/internal/agent/sighndlr_bsdsol.go +++ b/internal/agent/sighndlr_bsdsol.go @@ -24,7 +24,7 @@ func (a *Agent) signalNotifySetup() { signal.Notify(a.signalCh, os.Interrupt, unix.SIGTERM, unix.SIGHUP, unix.SIGPIPE, unix.SIGINFO) } -// handleSignals runs the signal handler thread +// handleSignals runs the signal handler thread. func (a *Agent) handleSignals() error { const stacktraceBufSize = 1 * units.MiB diff --git a/internal/agent/sighndlr_linux.go b/internal/agent/sighndlr_linux.go index d03633e2..b65dc1f2 100644 --- a/internal/agent/sighndlr_linux.go +++ b/internal/agent/sighndlr_linux.go @@ -24,7 +24,7 @@ func (a *Agent) signalNotifySetup() { signal.Notify(a.signalCh, os.Interrupt, unix.SIGTERM, unix.SIGHUP, unix.SIGPIPE, unix.SIGTRAP) } -// handleSignals runs the signal handler thread +// handleSignals runs the signal handler thread. func (a *Agent) handleSignals() error { const stacktraceBufSize = 1 * units.MiB diff --git a/internal/agent/sighndlr_windows.go b/internal/agent/sighndlr_windows.go index 861ade74..69d9875f 100644 --- a/internal/agent/sighndlr_windows.go +++ b/internal/agent/sighndlr_windows.go @@ -24,7 +24,7 @@ func (a *Agent) signalNotifySetup() { signal.Notify(a.signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE, syscall.SIGTRAP) } -// handleSignals runs the signal handler thread +// handleSignals runs the signal handler thread. func (a *Agent) handleSignals() error { const stacktraceBufSize = 1 * units.MiB diff --git a/internal/builtins/builtins.go b/internal/builtins/builtins.go index b4a0a28e..b10c49ac 100644 --- a/internal/builtins/builtins.go +++ b/internal/builtins/builtins.go @@ -8,6 +8,7 @@ package builtins import ( "context" + "fmt" "sync" "time" @@ -16,13 +17,12 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" cgm "github.com/circonus-labs/circonus-gometrics/v3" appstats "github.com/maier/go-appstats" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) -// Builtins defines the internal metric collector manager +// Builtins defines the internal metric collector manager. type Builtins struct { collectors map[string]collector.Collector logger zerolog.Logger @@ -30,7 +30,7 @@ type Builtins struct { sync.Mutex } -// New creates a new builtins manager +// New creates a new builtins manager. func New(ctx context.Context) (*Builtins, error) { b := Builtins{ collectors: make(map[string]collector.Collector), @@ -46,7 +46,7 @@ func New(ctx context.Context) (*Builtins, error) { err := b.configure(ctx) if err != nil { - return nil, errors.Wrap(err, "configuring builtins") + return nil, fmt.Errorf("configure builtins: %w", err) } // prom applies to all platforms @@ -67,7 +67,7 @@ func New(ctx context.Context) (*Builtins, error) { return &b, nil } -// Run triggers internal collectors to gather metrics +// Run triggers internal collectors to gather metrics. func (b *Builtins) Run(ctx context.Context, id string) error { b.Lock() @@ -143,7 +143,7 @@ func (b *Builtins) Run(ctx context.Context, id string) error { return nil } -// IsBuiltin determines if an id is a builtin or not +// IsBuiltin determines if an id is a builtin or not. func (b *Builtins) IsBuiltin(id string) bool { if id == "" { return false @@ -161,7 +161,7 @@ func (b *Builtins) IsBuiltin(id string) bool { return ok } -// Flush returns current metrics for all collectors +// Flush returns current metrics for all collectors. func (b *Builtins) Flush(id string) *cgm.Metrics { b.Lock() defer b.Unlock() diff --git a/internal/builtins/builtins_test.go b/internal/builtins/builtins_test.go index 7d8ff896..4f1a495d 100644 --- a/internal/builtins/builtins_test.go +++ b/internal/builtins/builtins_test.go @@ -123,6 +123,7 @@ func TestRun(t *testing.T) { } if b == nil { t.Fatal("expected a builtins instance") + return } b.collectors["foo"] = newFoo() @@ -142,6 +143,7 @@ func TestRun(t *testing.T) { } if b == nil { t.Fatal("expected a builtins instance") + return } b.collectors["foo"] = newFoo() @@ -160,6 +162,7 @@ func TestRun(t *testing.T) { } if b == nil { t.Fatal("expected a builtins instance") + return } b.collectors["foo"] = newFoo() @@ -178,6 +181,7 @@ func TestRun(t *testing.T) { } if b == nil { t.Fatal("expected a builtins instance") + return } b.collectors["foo"] = newFoo() @@ -216,6 +220,7 @@ func TestIsBuiltIn(t *testing.T) { } if b == nil { t.Fatal("expected a builtins instance") + return } if b.IsBuiltin("foo") { @@ -231,6 +236,7 @@ func TestIsBuiltIn(t *testing.T) { } if b == nil { t.Fatal("expected a builtins instance") + return } b.collectors["foo"] = newFoo() diff --git a/internal/builtins/collector/collector.go b/internal/builtins/collector/collector.go index 2f217b52..9a95745a 100644 --- a/internal/builtins/collector/collector.go +++ b/internal/builtins/collector/collector.go @@ -13,7 +13,7 @@ import ( "github.com/rs/zerolog" ) -// Collector defines the interface for builtin metric collectors +// Collector defines the interface for builtin metric collectors. type Collector interface { Collect(context.Context) error Flush() cgm.Metrics @@ -22,7 +22,7 @@ type Collector interface { Logger() zerolog.Logger } -// InventoryStats defines the stats a collector exposes for the /inventory endpoint +// InventoryStats defines the stats a collector exposes for the /inventory endpoint. type InventoryStats struct { ID string `json:"name"` LastError string `json:"last_error"` @@ -32,12 +32,12 @@ type InventoryStats struct { } var ( - // ErrNotImplemented collector type is not implemented on this os + // ErrNotImplemented collector type is not implemented on this os. ErrNotImplemented = errors.New("not implemented on OS") - // ErrAlreadyRunning collector is already running + // ErrAlreadyRunning collector is already running. ErrAlreadyRunning = errors.New("already running") - // ErrTTLNotExpired collector run ttl has not expired + // ErrTTLNotExpired collector run ttl has not expired. ErrTTLNotExpired = errors.New("TTL not expired") ) diff --git a/internal/builtins/collector/generic/collector.go b/internal/builtins/collector/generic/collector.go index 0890f1a1..c4258f50 100644 --- a/internal/builtins/collector/generic/collector.go +++ b/internal/builtins/collector/generic/collector.go @@ -14,11 +14,10 @@ import ( "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" ) -// gencommon defines psutils metrics common elements +// gencommon defines psutils metrics common elements. type gencommon struct { id string // OPT id of the collector (used as metric name prefix) pkgID string // package prefix used for logging and errors @@ -34,14 +33,14 @@ type gencommon struct { sync.Mutex } -// Collect returns collector metrics +// Collect returns collector metrics. func (c *gencommon) Collect(ctx context.Context) error { c.Lock() defer c.Unlock() return collector.ErrNotImplemented } -// Flush returns last metrics collected +// Flush returns last metrics collected. func (c *gencommon) Flush() cgm.Metrics { c.Lock() defer c.Unlock() @@ -51,7 +50,7 @@ func (c *gencommon) Flush() cgm.Metrics { return c.lastMetrics } -// ID returns the id of the instance +// ID returns the id of the instance. func (c *gencommon) ID() string { c.Lock() defer c.Unlock() @@ -61,7 +60,7 @@ func (c *gencommon) ID() string { return c.id } -// TTL return run TTL if set +// TTL return run TTL if set. func (c *gencommon) TTL() string { c.Lock() defer c.Unlock() @@ -71,7 +70,7 @@ func (c *gencommon) TTL() string { return c.runTTL.String() } -// Inventory returns collector stats for /inventory endpoint +// Inventory returns collector stats for /inventory endpoint. func (c *gencommon) Inventory() collector.InventoryStats { c.Lock() defer c.Unlock() @@ -84,23 +83,23 @@ func (c *gencommon) Inventory() collector.InventoryStats { } } -// Logger returns collector's instance of logger +// Logger returns collector's instance of logger. func (c *gencommon) Logger() zerolog.Logger { return c.logger } -// addMetric to internal buffer if metric is active +// addMetric to internal buffer if metric is active. func (c *gencommon) addMetric(metrics *cgm.Metrics, mname, mtype string, mval interface{}, mtags tags.Tags) error { if metrics == nil { - return errors.New("invalid metric submission") + return errInvalidMetric } if mname == "" { - return errors.New("invalid metric, no name") + return errInvalidMetricNoName } if mtype == "" { - return errors.New("invalid metric, no type") + return errInvalidMetricNoType } var tagList tags.Tags @@ -118,7 +117,7 @@ func (c *gencommon) addMetric(metrics *cgm.Metrics, mname, mtype string, mval in return nil } -// setStatus is used in Collect to set the collector status +// setStatus is used in Collect to set the collector status. func (c *gencommon) setStatus(metrics cgm.Metrics, err error) { c.Lock() if err == nil { diff --git a/internal/builtins/collector/generic/collector_test.go b/internal/builtins/collector/generic/collector_test.go index 6ec46d84..9dec54a4 100644 --- a/internal/builtins/collector/generic/collector_test.go +++ b/internal/builtins/collector/generic/collector_test.go @@ -7,7 +7,7 @@ package generic import ( "context" - "errors" + "fmt" "reflect" "testing" "time" @@ -83,7 +83,7 @@ func TestAddMetric(t *testing.T) { if err := c.addMetric(nil, "", "", "", tags.Tags{}); err == nil { t.Fatal("expected error") } else { - expect := "invalid metric submission" + expect := "invalid metric, nil" if err.Error() != expect { t.Fatalf("expected (%s) got (%v)", expect, err) } @@ -138,7 +138,7 @@ func TestSetStatus(t *testing.T) { t.Log("\tmetrics, no error") c.setStatus(m, nil) t.Log("\tmetrics, error") - c.setStatus(m, errors.New("foo")) + c.setStatus(m, fmt.Errorf("foo")) //nolint:goerr113 t.Log("\tmetrics, no error, add last start") c.lastStart = time.Now() diff --git a/internal/builtins/collector/generic/cpu.go b/internal/builtins/collector/generic/cpu.go index 09dfbb2c..6d3abd26 100644 --- a/internal/builtins/collector/generic/cpu.go +++ b/internal/builtins/collector/generic/cpu.go @@ -17,18 +17,17 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/shirou/gopsutil/cpu" ) -// CPU metrics from psutils +// CPU metrics from psutils. type CPU struct { gencommon reportAllCPUs bool // OPT report all cpus (vs just total) may be overridden in config file } -// cpuOptions defines what elements can be overridden in a config file +// cpuOptions defines what elements can be overridden in a config file. type cpuOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -38,7 +37,7 @@ type cpuOptions struct { AllCPU string `json:"report_all_cpus" toml:"report_all_cpus" yaml:"report_all_cpus"` } -// NewCPUCollector creates new psutils cpu collector +// NewCPUCollector creates new psutils cpu collector. func NewCPUCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := CPU{} c.id = NameCPU @@ -54,7 +53,7 @@ func NewCPUCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", opts).Msg("loaded config") @@ -62,7 +61,7 @@ func NewCPUCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector if opts.AllCPU != "" { rpt, err := strconv.ParseBool(opts.AllCPU) if err != nil { - return nil, errors.Wrapf(err, "%s parsing report_all_cpus", c.pkgID) + return nil, fmt.Errorf("%s parsing report_all_cpus: %w", c.pkgID, err) } c.reportAllCPUs = rpt } @@ -74,7 +73,7 @@ func NewCPUCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -82,7 +81,7 @@ func NewCPUCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector return &c, nil } -// Collect cpu metrics +// Collect cpu metrics. func (c *CPU) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { diff --git a/internal/builtins/collector/generic/disk.go b/internal/builtins/collector/generic/disk.go index 54b475c7..9c86ef4c 100644 --- a/internal/builtins/collector/generic/disk.go +++ b/internal/builtins/collector/generic/disk.go @@ -7,6 +7,7 @@ package generic import ( "context" + "fmt" "strings" "time" @@ -14,18 +15,17 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/shirou/gopsutil/disk" ) -// Disk metrics from the Linux ProcFS +// Disk metrics from the Linux ProcFS. type Disk struct { ioDevices []string gencommon } -// DiskOptions defines what elements can be overridden in a config file +// DiskOptions defines what elements can be overridden in a config file. type DiskOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -35,7 +35,7 @@ type DiskOptions struct { IODevices []string `json:"io_devices" toml:"io_devices" yaml:"io_devices"` } -// NewDiskCollector creates new psutils disk collector +// NewDiskCollector creates new psutils disk collector. func NewDiskCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := Disk{} c.id = NameDisk @@ -51,7 +51,7 @@ func NewDiskCollector(cfgBaseName string, parentLogger zerolog.Logger) (collecto return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -67,7 +67,7 @@ func NewDiskCollector(cfgBaseName string, parentLogger zerolog.Logger) (collecto if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -75,7 +75,7 @@ func NewDiskCollector(cfgBaseName string, parentLogger zerolog.Logger) (collecto return &c, nil } -// Collect disk device metrics +// Collect disk device metrics. func (c *Disk) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { diff --git a/internal/builtins/collector/generic/fs.go b/internal/builtins/collector/generic/fs.go index ad3398f8..7dfa80e4 100644 --- a/internal/builtins/collector/generic/fs.go +++ b/internal/builtins/collector/generic/fs.go @@ -18,12 +18,11 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/shirou/gopsutil/disk" ) -// FS metrics from the Linux ProcFS +// FS metrics from the Linux ProcFS. type FS struct { includeFS *regexp.Regexp excludeFS *regexp.Regexp @@ -32,7 +31,7 @@ type FS struct { allFSDevices bool } -// fsOptions defines what elements can be overridden in a config file +// fsOptions defines what elements can be overridden in a config file. type fsOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -45,7 +44,7 @@ type fsOptions struct { ExcludeFSType []string `json:"exclude_fs_type" toml:"exclude_fs_type" yaml:"exclude_fs_type"` } -// NewFSCollector creates new psutils disk collector +// NewFSCollector creates new psutils disk collector. func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := FS{} c.id = NameFS @@ -65,7 +64,7 @@ func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -73,7 +72,7 @@ func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. if opts.IncludeRegexFS != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.IncludeRegexFS)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include FS regex", c.pkgID) + return nil, fmt.Errorf("%s compiling include FS regex: %w", c.pkgID, err) } c.includeFS = rx } @@ -81,7 +80,7 @@ func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. if opts.ExcludeRegexFS != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.ExcludeRegexFS)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude FS regex", c.pkgID) + return nil, fmt.Errorf("%s compiling exclude FS regex: %w", c.pkgID, err) } c.excludeFS = rx } @@ -95,7 +94,7 @@ func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. if opts.IncludeAllDevices != "" { rpt, err := strconv.ParseBool(opts.IncludeAllDevices) if err != nil { - return nil, errors.Wrapf(err, "%s parsing include_all_devices", c.pkgID) + return nil, fmt.Errorf("%s parsing include_all_devices: %w", c.pkgID, err) } c.allFSDevices = rpt } @@ -107,7 +106,7 @@ func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -115,7 +114,7 @@ func NewFSCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. return &c, nil } -// Collect disk fs metrics +// Collect disk fs metrics. func (c *FS) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { diff --git a/internal/builtins/collector/generic/generic.go b/internal/builtins/collector/generic/generic.go index 6c60cb89..53ef729c 100644 --- a/internal/builtins/collector/generic/generic.go +++ b/internal/builtins/collector/generic/generic.go @@ -33,11 +33,14 @@ const ( ) var ( - defaultExcludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, "")) - defaultIncludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, ".+")) + errInvalidMetric = fmt.Errorf("invalid metric, nil") + errInvalidMetricNoName = fmt.Errorf("invalid metric, no name") + errInvalidMetricNoType = fmt.Errorf("invalid metric, no type") + defaultExcludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, "")) + defaultIncludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, ".+")) ) -// New creates new PSUtil collector +// New creates new PSUtil collector. func New() ([]collector.Collector, error) { none := []collector.Collector{} diff --git a/internal/builtins/collector/generic/load.go b/internal/builtins/collector/generic/load.go index 8b37bd3e..d8795337 100644 --- a/internal/builtins/collector/generic/load.go +++ b/internal/builtins/collector/generic/load.go @@ -7,6 +7,7 @@ package generic import ( "context" + "fmt" "math" "strings" "time" @@ -15,25 +16,24 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/shirou/gopsutil/load" ) -// Load metrics +// Load metrics. type Load struct { gencommon } -// loadOptions defines what elements can be overridden in a config file +// loadOptions defines what elements can be overridden in a config file. type loadOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewLoadCollector creates new psutils collector +// NewLoadCollector creates new psutils collector. func NewLoadCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := Load{} c.id = NameLoad @@ -48,7 +48,7 @@ func NewLoadCollector(cfgBaseName string, parentLogger zerolog.Logger) (collecto return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", opts).Msg("loaded config") @@ -60,7 +60,7 @@ func NewLoadCollector(cfgBaseName string, parentLogger zerolog.Logger) (collecto if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -68,7 +68,7 @@ func NewLoadCollector(cfgBaseName string, parentLogger zerolog.Logger) (collecto return &c, nil } -// Collect load metrics +// Collect load metrics. func (c *Load) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { @@ -116,10 +116,10 @@ func (c *Load) Collect(ctx context.Context) error { { // units:processes tagList := tags.Tags{tagUnitsProcesses} - // TODO: there is misc.ProcsTotal in a future release (probably 2.19.05 based on commits/PRs) - _ = c.addMetric(&metrics, "total", "i", misc.ProcsRunning+misc.ProcsBlocked, tagList) + _ = c.addMetric(&metrics, "created", "i", misc.ProcsCreated, tagList) _ = c.addMetric(&metrics, "running", "i", misc.ProcsRunning, tagList) _ = c.addMetric(&metrics, "blocked", "i", misc.ProcsBlocked, tagList) + _ = c.addMetric(&metrics, "total", "i", misc.ProcsTotal, tagList) } { // units:switches tagList := tags.Tags{tags.Tag{Category: "units", Value: "switches"}} diff --git a/internal/builtins/collector/generic/net_if.go b/internal/builtins/collector/generic/net_if.go index 027d096e..cd178e95 100644 --- a/internal/builtins/collector/generic/net_if.go +++ b/internal/builtins/collector/generic/net_if.go @@ -16,19 +16,18 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/shirou/gopsutil/net" ) -// IF metrics +// IF metrics. type IF struct { include *regexp.Regexp exclude *regexp.Regexp gencommon } -// ifOptions defines what elements can be overridden in a config file +// ifOptions defines what elements can be overridden in a config file. type ifOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -39,7 +38,7 @@ type ifOptions struct { ExcludeRegex string `json:"exclude_regex" toml:"exclude_regex" yaml:"exclude_regex"` } -// NewNetIFCollector creates new psutils collector +// NewNetIFCollector creates new psutils collector. func NewNetIFCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := IF{} c.id = NameIF @@ -57,7 +56,7 @@ func NewNetIFCollector(cfgBaseName string, parentLogger zerolog.Logger) (collect return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -65,7 +64,7 @@ func NewNetIFCollector(cfgBaseName string, parentLogger zerolog.Logger) (collect if opts.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compiling include regex: %w", c.pkgID, err) } c.include = rx } @@ -73,7 +72,7 @@ func NewNetIFCollector(cfgBaseName string, parentLogger zerolog.Logger) (collect if opts.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compiling exclude regex: %w", c.pkgID, err) } c.exclude = rx } @@ -85,7 +84,7 @@ func NewNetIFCollector(cfgBaseName string, parentLogger zerolog.Logger) (collect if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -93,7 +92,7 @@ func NewNetIFCollector(cfgBaseName string, parentLogger zerolog.Logger) (collect return &c, nil } -// Collect metrics +// Collect metrics. func (c *IF) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { diff --git a/internal/builtins/collector/generic/net_proto.go b/internal/builtins/collector/generic/net_proto.go index 3fab4547..d781c248 100644 --- a/internal/builtins/collector/generic/net_proto.go +++ b/internal/builtins/collector/generic/net_proto.go @@ -7,6 +7,7 @@ package generic import ( "context" + "fmt" "runtime" "strings" "time" @@ -15,18 +16,17 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/shirou/gopsutil/net" ) -// Proto metrics +// Proto metrics. type Proto struct { protocols []string gencommon } -// protoOptions defines what elements can be overridden in a config file +// protoOptions defines what elements can be overridden in a config file. type protoOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -36,7 +36,11 @@ type protoOptions struct { Protocols []string `json:"protocols" toml:"protocols" yaml:"protocols"` // default: empty (equates to all: ip,icmp,icmpmsg,tcp,udp,udplite) } -// NewNetProtoCollector creates new psutils collector +var ( + errNoProtoMetrics = fmt.Errorf("no network protocol metrics available") +) + +// NewNetProtoCollector creates new psutils collector. func NewNetProtoCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := Proto{} c.id = NameProto @@ -51,7 +55,7 @@ func NewNetProtoCollector(cfgBaseName string, parentLogger zerolog.Logger) (coll return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -67,7 +71,7 @@ func NewNetProtoCollector(cfgBaseName string, parentLogger zerolog.Logger) (coll if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -75,7 +79,7 @@ func NewNetProtoCollector(cfgBaseName string, parentLogger zerolog.Logger) (coll return &c, nil } -// Collect metrics +// Collect metrics. func (c *Proto) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { @@ -109,7 +113,7 @@ func (c *Proto) Collect(ctx context.Context) error { } if len(counters) == 0 { - return errors.New("no network protocol metrics available") + return errNoProtoMetrics } if runtime.GOOS == "linux" { @@ -161,7 +165,7 @@ func (c *Proto) Collect(ctx context.Context) error { } const ( - // repeated metric names + // repeated metric names. metricInCsumErrors = "InCsumErrors" metricInErrors = "InErrors" metricOutDatagrams = "OutDatagrams" diff --git a/internal/builtins/collector/generic/vm.go b/internal/builtins/collector/generic/vm.go index 8d30de0f..ee8fdfd1 100644 --- a/internal/builtins/collector/generic/vm.go +++ b/internal/builtins/collector/generic/vm.go @@ -7,6 +7,7 @@ package generic import ( "context" + "fmt" "math" "runtime" "strings" @@ -16,24 +17,23 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/shirou/gopsutil/mem" ) -// VM metrics +// VM metrics. type VM struct { gencommon } -// vmOptions defines what elements can be overridden in a config file +// vmOptions defines what elements can be overridden in a config file. type vmOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewVMCollector creates new psutils collector +// NewVMCollector creates new psutils collector. func NewVMCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector.Collector, error) { c := VM{} c.id = NameVM @@ -48,7 +48,7 @@ func NewVMCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -60,7 +60,7 @@ func NewVMCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -68,7 +68,7 @@ func NewVMCollector(cfgBaseName string, parentLogger zerolog.Logger) (collector. return &c, nil } -// Collect memory metrics +// Collect memory metrics. func (c *VM) Collect(ctx context.Context) error { c.Lock() if c.runTTL > time.Duration(0) { diff --git a/internal/builtins/collector/linux/procfs/collector.go b/internal/builtins/collector/linux/procfs/collector.go index b7be52d2..17bc6976 100644 --- a/internal/builtins/collector/linux/procfs/collector.go +++ b/internal/builtins/collector/linux/procfs/collector.go @@ -10,6 +10,7 @@ package procfs import ( "bufio" "context" + "fmt" "os" "path/filepath" "sync" @@ -20,12 +21,11 @@ import ( "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) -// common defines ProcFS metrics common elements +// common defines ProcFS metrics common elements. type common struct { id string // OPT id of the collector (used as metric name prefix) pkgID string // package prefix used for logging and errors @@ -62,14 +62,14 @@ func newCommon(id, procFSPath, procFile string, baseTags cgm.Tags) common { } } -// Collect returns collector metrics +// Collect returns collector metrics. func (c *common) Collect(ctx context.Context) error { c.Lock() defer c.Unlock() return collector.ErrNotImplemented } -// Flush returns last metrics collected +// Flush returns last metrics collected. func (c *common) Flush() cgm.Metrics { c.Lock() defer c.Unlock() @@ -79,14 +79,14 @@ func (c *common) Flush() cgm.Metrics { return c.lastMetrics } -// ID returns the id of the instance +// ID returns the id of the instance. func (c *common) ID() string { c.Lock() defer c.Unlock() return c.id } -// Inventory returns collector stats for /inventory endpoint +// Inventory returns collector stats for /inventory endpoint. func (c *common) Inventory() collector.InventoryStats { c.Lock() defer c.Unlock() @@ -99,12 +99,12 @@ func (c *common) Inventory() collector.InventoryStats { } } -// Logger returns collector's instance of logger +// Logger returns collector's instance of logger. func (c *common) Logger() zerolog.Logger { return c.logger } -// cleanName is used to clean the metric name +// cleanName is used to clean the metric name. func (c *common) cleanName(name string) string { // metric names are not dynamic for linux procfs - reintroduce cleaner if // procfs sources used return dirty dynamic names. @@ -113,18 +113,18 @@ func (c *common) cleanName(name string) string { return name } -// addMetric to internal buffer if metric is active +// addMetric to internal buffer if metric is active. func (c *common) addMetric(metrics *cgm.Metrics, prefix string, mname, mtype string, mval interface{}, mtags tags.Tags) error { if metrics == nil { - return errors.New("invalid metric submission") + return errInvalidMetric } if mname == "" { - return errors.New("invalid metric, no name") + return errInvalidMetricNoName } if mtype == "" { - return errors.New("invalid metric, no type") + return errInvalidMetricNoType } // cleanup the raw metric name, if needed @@ -148,7 +148,7 @@ func (c *common) addMetric(metrics *cgm.Metrics, prefix string, mname, mtype str return nil } -// setStatus is used in Collect to set the collector status +// setStatus is used in Collect to set the collector status. func (c *common) setStatus(metrics cgm.Metrics, err error) { c.Lock() if err == nil { @@ -170,12 +170,12 @@ func (c *common) setStatus(metrics cgm.Metrics, err error) { func (c *common) readFile(file string) ([]string, error) { if file == "" { - return nil, errors.New("invalid file (empty)") + return nil, errInvalidFile } f, err := os.Open(file) if err != nil { - return nil, errors.Wrapf(err, "opening file (%s)", file) + return nil, fmt.Errorf("opening file: %w", err) } var lines []string @@ -184,8 +184,8 @@ func (c *common) readFile(file string) ([]string, error) { lines = append(lines, s.Text()) } if err := s.Err(); err != nil { - return lines, errors.Wrapf(err, "scanning file (%s) [close:%v]", file, f.Close()) + return lines, fmt.Errorf("scanner: %w [close:%v]", err, f.Close()) } - return lines, f.Close() + return lines, f.Close() //nolint:wrapcheck } diff --git a/internal/builtins/collector/linux/procfs/collector_test.go b/internal/builtins/collector/linux/procfs/collector_test.go index 743e1125..995251bf 100644 --- a/internal/builtins/collector/linux/procfs/collector_test.go +++ b/internal/builtins/collector/linux/procfs/collector_test.go @@ -9,7 +9,7 @@ package procfs import ( "context" - "errors" + "fmt" "reflect" "testing" "time" @@ -137,7 +137,7 @@ func TestSetStatus(t *testing.T) { t.Log("\tmetrics, no error") c.setStatus(m, nil) t.Log("\tmetrics, error") - c.setStatus(m, errors.New("foo")) + c.setStatus(m, fmt.Errorf("foo")) //nolint:goerr113 t.Log("\tmetrics, no error, add last start") c.lastStart = time.Now() diff --git a/internal/builtins/collector/linux/procfs/cpu.go b/internal/builtins/collector/linux/procfs/cpu.go index 1ceb576e..5921f522 100644 --- a/internal/builtins/collector/linux/procfs/cpu.go +++ b/internal/builtins/collector/linux/procfs/cpu.go @@ -9,6 +9,7 @@ package procfs import ( "context" + "fmt" "os" "path/filepath" "runtime" @@ -20,10 +21,9 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// CPU metrics from the Linux ProcFS +// CPU metrics from the Linux ProcFS. type CPU struct { lastRunValues map[string]lastValues // values from last run common // common attributes @@ -32,7 +32,7 @@ type CPU struct { reportAllCPUs bool // OPT report all cpus (vs just total) may be overridden in config file } -// cpuOptions defines what elements can be overridden in a config file +// cpuOptions defines what elements can be overridden in a config file. type cpuOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -49,7 +49,7 @@ type lastValues struct { busy float64 } -// NewCPUCollector creates new procfs cpu collector +// NewCPUCollector creates new procfs cpu collector. func NewCPUCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { procFile := "stat" @@ -65,7 +65,7 @@ func NewCPUCollector(cfgBaseName, procFSPath string) (collector.Collector, error if cfgBaseName == "" { if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil @@ -76,7 +76,7 @@ func NewCPUCollector(cfgBaseName, procFSPath string) (collector.Collector, error if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Interface("config", opts).Msg("loaded config") @@ -85,7 +85,7 @@ func NewCPUCollector(cfgBaseName, procFSPath string) (collector.Collector, error if opts.ClockHZ != "" { v, err := strconv.ParseFloat(opts.ClockHZ, 64) if err != nil { - return nil, errors.Wrapf(err, "%s parsing clock_hz", c.pkgID) + return nil, fmt.Errorf("%s parsing clock_hz: %w", c.pkgID, err) } clockHZ = v c.clockNorm = clockHZ / 100 @@ -94,7 +94,7 @@ func NewCPUCollector(cfgBaseName, procFSPath string) (collector.Collector, error if opts.AllCPU != "" { rpt, err := strconv.ParseBool(opts.AllCPU) if err != nil { - return nil, errors.Wrapf(err, "%s parsing report_all_cpus", c.pkgID) + return nil, fmt.Errorf("%s parsing report_all_cpus: %w", c.pkgID, err) } c.reportAllCPUs = rpt } @@ -111,19 +111,19 @@ func NewCPUCollector(cfgBaseName, procFSPath string) (collector.Collector, error if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *CPU) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -152,7 +152,7 @@ func (c *CPU) Collect(ctx context.Context) error { lines, err := c.readFile(c.file) if err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } _ = c.addMetric(&metrics, "", "num_cpu", "I", runtime.NumCPU(), tags.Tags{}) @@ -195,7 +195,7 @@ func (c *CPU) Collect(ctx context.Context) error { id, cpuMetrics, err := c.parseCPU(fields) if err != nil { c.setStatus(metrics, err) - return errors.Wrapf(err, "%s parsing %s", c.pkgID, fields[0]) + return fmt.Errorf("%s parsing %s: %w", c.pkgID, fields[0], err) } for mn, mv := range *cpuMetrics { @@ -237,42 +237,42 @@ func (c *CPU) parseCPU(fields []string) (string, *cgm.Metrics, error) { userNormal, err := strconv.ParseFloat(fields[1], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse userNormal: %w", err) } busy += userNormal userNice, err := strconv.ParseFloat(fields[2], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse userNice: %w", err) } busy += userNice sys, err := strconv.ParseFloat(fields[3], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse sys: %w", err) } busy += sys idleNormal, err := strconv.ParseFloat(fields[4], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse idleNormal: %w", err) } waitIO, err := strconv.ParseFloat(fields[5], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse waitIO: %w", err) } busy += waitIO irq, err := strconv.ParseFloat(fields[6], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse irq: %w", err) } busy += irq softIRQ, err := strconv.ParseFloat(fields[7], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse softIRQ: %w", err) } busy += softIRQ @@ -280,7 +280,7 @@ func (c *CPU) parseCPU(fields []string) (string, *cgm.Metrics, error) { if len(fields) > 8 { v, err := strconv.ParseFloat(fields[8], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse steal: %w", err) } steal = v busy += steal @@ -290,7 +290,7 @@ func (c *CPU) parseCPU(fields []string) (string, *cgm.Metrics, error) { if len(fields) > 9 { v, err := strconv.ParseFloat(fields[9], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse guest: %w", err) } guest = v busy += guest @@ -300,7 +300,7 @@ func (c *CPU) parseCPU(fields []string) (string, *cgm.Metrics, error) { if len(fields) > 10 { v, err := strconv.ParseFloat(fields[10], 64) if err != nil { - return cpuID, nil, err + return cpuID, nil, fmt.Errorf("parse guestNice: %w", err) } guestNice = v busy += guestNice @@ -319,7 +319,7 @@ func (c *CPU) parseCPU(fields []string) (string, *cgm.Metrics, error) { "cpu_guest_nice": cgm.Metric{Type: metricType, Value: (guestNice / numCPU) / c.clockNorm}, } - all := float64(busy + idleNormal) + all := busy + idleNormal if lrv, ok := c.lastRunValues[fields[0]]; ok { used := ((busy - lrv.busy) / (all - lrv.all)) * 100 metrics["cpu_used"] = cgm.Metric{Type: metricType, Value: used} diff --git a/internal/builtins/collector/linux/procfs/disk.go b/internal/builtins/collector/linux/procfs/disk.go index 1588da19..656c41ba 100644 --- a/internal/builtins/collector/linux/procfs/disk.go +++ b/internal/builtins/collector/linux/procfs/disk.go @@ -24,11 +24,10 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config/defaults" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/spf13/viper" ) -// Disk metrics from the Linux ProcFS +// Disk metrics from the Linux ProcFS. type Disk struct { include *regexp.Regexp exclude *regexp.Regexp @@ -37,7 +36,7 @@ type Disk struct { sectorSizeDefault uint64 } -// diskOptions defines what elements can be overridden in a config file +// diskOptions defines what elements can be overridden in a config file. type diskOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -72,7 +71,7 @@ type dstats struct { discardms uint64 } -// NewDiskCollector creates new procfs disk collector +// NewDiskCollector creates new procfs disk collector. func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { procFile := "diskstats" @@ -87,7 +86,7 @@ func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if cfgBaseName == "" { if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } @@ -97,7 +96,7 @@ func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -106,7 +105,7 @@ func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if opts.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compile include rx: %w", c.pkgID, err) } c.include = rx } @@ -114,7 +113,7 @@ func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if opts.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compile exclude rx: %w", c.pkgID, err) } c.exclude = rx } @@ -122,7 +121,7 @@ func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if opts.DefaultSectorSize != "" { v, err := strconv.ParseUint(opts.DefaultSectorSize, 10, 64) if err != nil { - return nil, errors.Wrapf(err, "%s parsing default sector size", c.pkgID) + return nil, fmt.Errorf("%s parsing default sector size: %w", c.pkgID, err) } c.sectorSizeDefault = v } @@ -139,19 +138,19 @@ func NewDiskCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *Disk) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -179,7 +178,7 @@ func (c *Disk) Collect(ctx context.Context) error { lines, err := c.readFile(c.file) if err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } for _, line := range lines { fields := strings.Fields(line) @@ -335,12 +334,12 @@ func (c *Disk) parse(fields []string) (*dstats, error) { devName := fields[2] if devName == "" { c.logger.Debug().Msg("invalid device name (empty), ignoring") - return nil, errors.New("invalid device name (empty)") + return nil, fmt.Errorf("invalid device name (empty)") //nolint:goerr113 } sectorSz := c.getSectorSize(devName) - pe := errors.New("parsing field") + pe := fmt.Errorf("parsing field") //nolint:goerr113 d := dstats{ id: devName, haveKernel418: len(fields) > 14, @@ -350,14 +349,14 @@ func (c *Disk) parse(fields []string) (*dstats, error) { d.readsCompleted = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field reads completed") - return nil, pe + return nil, fmt.Errorf("%s parse readsCompleted: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[4], 10, 64); err == nil { d.readsMerged = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field reads merged") - return nil, pe + return nil, fmt.Errorf("%s parse readsMerged: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[5], 10, 64); err == nil { @@ -365,28 +364,28 @@ func (c *Disk) parse(fields []string) (*dstats, error) { d.bytesRead = v * sectorSz } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field sectors read") - return nil, pe + return nil, fmt.Errorf("%s parse sectorsRead: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[6], 10, 64); err == nil { d.readms = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field read ms") - return nil, pe + return nil, fmt.Errorf("%s parsing read ms: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[7], 10, 64); err == nil { d.writesCompleted = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field writes completed") - return nil, pe + return nil, fmt.Errorf("%s parsing writesCompleted: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[8], 10, 64); err == nil { d.writesMerged = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field writes merged") - return nil, pe + return nil, fmt.Errorf("%s parsing writesMerged: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[9], 10, 64); err == nil { @@ -394,35 +393,35 @@ func (c *Disk) parse(fields []string) (*dstats, error) { d.bytesWritten = v * sectorSz } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field sectors written") - return nil, pe + return nil, fmt.Errorf("%s parsing sectorsWritten: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[10], 10, 64); err == nil { d.writems = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field write ms") - return nil, pe + return nil, fmt.Errorf("%s parsing write ms: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[11], 10, 64); err == nil { d.currIO = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field IO ops in progress") - return nil, pe + return nil, fmt.Errorf("%s parsing curr io: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[12], 10, 64); err == nil { d.ioms = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field IO ms") - return nil, pe + return nil, fmt.Errorf("%s parsing io ms: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[13], 10, 64); err == nil { d.iomsWeighted = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field weighted IO ms") - return nil, pe + return nil, fmt.Errorf("%s parsing io ms weighted: %w", c.pkgID, pe) } if d.haveKernel418 { @@ -430,25 +429,25 @@ func (c *Disk) parse(fields []string) (*dstats, error) { d.discardsCompleted = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field discards completed") - return nil, pe + return nil, fmt.Errorf("%s parsing discardsCompleted: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[15], 10, 64); err == nil { d.discardsMerged = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field discards merged") - return nil, pe + return nil, fmt.Errorf("%s parsing discardsMerged: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[16], 10, 64); err == nil { d.sectorsDiscarded = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field sectors discarded") - return nil, pe + return nil, fmt.Errorf("%s parsing sectorsDiscarded: %w", c.pkgID, pe) } if v, err := strconv.ParseUint(fields[17], 10, 64); err == nil { d.discardms = v } else { c.logger.Warn().Err(err).Str("dev", devName).Msg("parsing field discard ms") - return nil, pe + return nil, fmt.Errorf("%s parsing discard ms: %w", c.pkgID, pe) } } @@ -469,7 +468,7 @@ func (c *Disk) parsemdstat() map[string][]string { for _, l := range lines { - line := strings.TrimSpace(string(l)) + line := strings.TrimSpace(l) if line == "" { continue } diff --git a/internal/builtins/collector/linux/procfs/load.go b/internal/builtins/collector/linux/procfs/load.go index 055c4636..9ef9f7ad 100644 --- a/internal/builtins/collector/linux/procfs/load.go +++ b/internal/builtins/collector/linux/procfs/load.go @@ -9,6 +9,7 @@ package procfs import ( "context" + "fmt" "os" "path/filepath" "strconv" @@ -19,16 +20,15 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// Load metrics from the Linux ProcFS (actually from unix.Sysinfo call) +// Load metrics from the Linux ProcFS (actually from unix.Sysinfo call). type Load struct { processStatsFile string common } -// loadOptions defines what elements can be overridden in a config file +// loadOptions defines what elements can be overridden in a config file. type loadOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -39,7 +39,7 @@ type loadOptions struct { MetricsDisabled []string `json:"metrics_disabled" toml:"metrics_disabled" yaml:"metrics_disabled"` } -// NewLoadCollector creates new procfs load collector +// NewLoadCollector creates new procfs load collector. func NewLoadCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { loadFile := "loadavg" statFile := "stat" @@ -52,7 +52,7 @@ func NewLoadCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if cfgBaseName == "" { if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } @@ -62,7 +62,7 @@ func NewLoadCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Interface("config", opts).Msg("loaded config") @@ -81,19 +81,19 @@ func NewLoadCollector(cfgBaseName, procFSPath string) (collector.Collector, erro if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *Load) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -126,7 +126,7 @@ func (c *Load) Collect(ctx context.Context) error { lines, err := c.readFile(c.file) if err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } for _, line := range lines { @@ -168,7 +168,7 @@ func (c *Load) Collect(ctx context.Context) error { lines, err := c.readFile(c.processStatsFile) if err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } for _, line := range lines { @@ -193,7 +193,7 @@ func (c *Load) Collect(ctx context.Context) error { if lineErr != nil { c.setStatus(metrics, err) - return errors.Wrapf(err, "%s parsing %s", c.pkgID, fields[0]) + return fmt.Errorf("%s parsing %s: %w", c.pkgID, fields[0], err) } } diff --git a/internal/builtins/collector/linux/procfs/net_if.go b/internal/builtins/collector/linux/procfs/net_if.go index ae278457..e7afa226 100644 --- a/internal/builtins/collector/linux/procfs/net_if.go +++ b/internal/builtins/collector/linux/procfs/net_if.go @@ -21,17 +21,16 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// NetIF metrics from the Linux ProcFS +// NetIF metrics from the Linux ProcFS. type NetIF struct { include *regexp.Regexp exclude *regexp.Regexp common } -// netIFOptions defines what elements can be overridden in a config file +// netIFOptions defines what elements can be overridden in a config file. type netIFOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -43,7 +42,7 @@ type netIFOptions struct { ExcludeRegex string `json:"exclude_regex" toml:"exclude_regex" yaml:"exclude_regex"` } -// NewNetIFCollector creates new procfs if collector +// NewNetIFCollector creates new procfs if collector. func NewNetIFCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { procFile := filepath.Join("net", "dev") @@ -56,7 +55,7 @@ func NewNetIFCollector(cfgBaseName, procFSPath string) (collector.Collector, err if cfgBaseName == "" { if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } @@ -66,7 +65,7 @@ func NewNetIFCollector(cfgBaseName, procFSPath string) (collector.Collector, err if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -75,7 +74,7 @@ func NewNetIFCollector(cfgBaseName, procFSPath string) (collector.Collector, err if opts.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compile include rx: %w", c.pkgID, err) } c.include = rx } @@ -83,7 +82,7 @@ func NewNetIFCollector(cfgBaseName, procFSPath string) (collector.Collector, err if opts.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compile exclude rx: %w", c.pkgID, err) } c.exclude = rx } @@ -100,19 +99,19 @@ func NewNetIFCollector(cfgBaseName, procFSPath string) (collector.Collector, err if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *NetIF) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -137,14 +136,14 @@ func (c *NetIF) Collect(ctx context.Context) error { if err := c.ifCollect(&metrics); err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s ifCollect: %w", c.pkgID, err) } c.setStatus(metrics, nil) return nil } -// ifCollect gets metrics from /proc/net/dev +// ifCollect gets metrics from /proc/net/dev. func (c *NetIF) ifCollect(metrics *cgm.Metrics) error { unitBytesTag := tags.Tag{Category: "units", Value: "bytes"} unitPacketsTag := tags.Tag{Category: "units", Value: "packets"} @@ -198,7 +197,7 @@ func (c *NetIF) ifCollect(metrics *cgm.Metrics) error { lines, err := c.readFile(c.file) if err != nil { - return errors.Wrapf(err, "parsing %s", c.file) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } for _, line := range lines { if strings.Contains(line, "|") { diff --git a/internal/builtins/collector/linux/procfs/net_proto.go b/internal/builtins/collector/linux/procfs/net_proto.go index 8d063cbe..82ff113e 100644 --- a/internal/builtins/collector/linux/procfs/net_proto.go +++ b/internal/builtins/collector/linux/procfs/net_proto.go @@ -21,17 +21,16 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// NetProto metrics from the Linux ProcFS +// NetProto metrics from the Linux ProcFS. type NetProto struct { include *regexp.Regexp exclude *regexp.Regexp common } -// netProtoOptions defines what elements can be overridden in a config file +// netProtoOptions defines what elements can be overridden in a config file. type netProtoOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -43,7 +42,7 @@ type netProtoOptions struct { ExcludeRegex string `json:"exclude_regex" toml:"exclude_regex" yaml:"exclude_regex"` } -// NewNetProtoCollector creates new procfs network protocol collector +// NewNetProtoCollector creates new procfs network protocol collector. func NewNetProtoCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { procFile := filepath.Join("net", "snmp") @@ -56,7 +55,7 @@ func NewNetProtoCollector(cfgBaseName, procFSPath string) (collector.Collector, if cfgBaseName == "" { if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } @@ -66,7 +65,7 @@ func NewNetProtoCollector(cfgBaseName, procFSPath string) (collector.Collector, if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -75,7 +74,7 @@ func NewNetProtoCollector(cfgBaseName, procFSPath string) (collector.Collector, if opts.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compile include rx: %w", c.pkgID, err) } c.include = rx } @@ -83,7 +82,7 @@ func NewNetProtoCollector(cfgBaseName, procFSPath string) (collector.Collector, if opts.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compile exclude rx: %w", c.pkgID, err) } c.exclude = rx } @@ -100,19 +99,19 @@ func NewNetProtoCollector(cfgBaseName, procFSPath string) (collector.Collector, if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s read file: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *NetProto) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -137,7 +136,7 @@ func (c *NetProto) Collect(ctx context.Context) error { if err := c.snmpCollect(&metrics); err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s snmpCollect: %w", c.pkgID, err) } c.setStatus(metrics, nil) @@ -149,7 +148,7 @@ type rawSNMPStat struct { val string } -// snmpCollect gets metrics from /proc/net/snmp and /proc/net/snmp6 +// snmpCollect gets metrics from /proc/net/snmp and /proc/net/snmp6. func (c *NetProto) snmpCollect(metrics *cgm.Metrics) error { stats := make(map[string][]rawSNMPStat) @@ -172,7 +171,7 @@ func (c *NetProto) snmpCollect(metrics *cgm.Metrics) error { */ lines, err := c.readFile(c.file) if err != nil { - return errors.Wrapf(err, "parsing %s", c.file) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } for _, line := range lines { fields := strings.Fields(line) @@ -204,7 +203,7 @@ func (c *NetProto) snmpCollect(metrics *cgm.Metrics) error { snmp6File := c.file + "6" lines, err := c.readFile(snmp6File) if err != nil { - return errors.Wrapf(err, "parsing %s", snmp6File) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } for _, line := range lines { fields := strings.Fields(line) @@ -264,7 +263,7 @@ func (c *NetProto) snmpCollect(metrics *cgm.Metrics) error { } const ( - // repeated metric names + // repeated metric names. metricInCsumErrors = "InCsumErrors" metricInErrors = "InErrors" metricOutDatagrams = "OutDatagrams" diff --git a/internal/builtins/collector/linux/procfs/net_socket.go b/internal/builtins/collector/linux/procfs/net_socket.go index bd75c4b8..153baa89 100644 --- a/internal/builtins/collector/linux/procfs/net_socket.go +++ b/internal/builtins/collector/linux/procfs/net_socket.go @@ -21,17 +21,16 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// NetSocket metrics from the Linux ProcFS +// NetSocket metrics from the Linux ProcFS. type NetSocket struct { include *regexp.Regexp exclude *regexp.Regexp common } -// netSocketOptions defines what elements can be overridden in a config file +// netSocketOptions defines what elements can be overridden in a config file. type netSocketOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -43,7 +42,7 @@ type netSocketOptions struct { ExcludeRegex string `json:"exclude_regex" toml:"exclude_regex" yaml:"exclude_regex"` } -// NewNetSocketCollector creates new procfs if collector +// NewNetSocketCollector creates new procfs if collector. func NewNetSocketCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { procFile := filepath.Join("net", "dev") @@ -56,7 +55,7 @@ func NewNetSocketCollector(cfgBaseName, procFSPath string) (collector.Collector, if cfgBaseName == "" { if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } @@ -66,7 +65,7 @@ func NewNetSocketCollector(cfgBaseName, procFSPath string) (collector.Collector, if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -75,7 +74,7 @@ func NewNetSocketCollector(cfgBaseName, procFSPath string) (collector.Collector, if opts.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compile include rx: %w", c.pkgID, err) } c.include = rx } @@ -83,7 +82,7 @@ func NewNetSocketCollector(cfgBaseName, procFSPath string) (collector.Collector, if opts.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, opts.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compile exclude rx: %w", c.pkgID, err) } c.exclude = rx } @@ -100,19 +99,19 @@ func NewNetSocketCollector(cfgBaseName, procFSPath string) (collector.Collector, if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *NetSocket) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -148,7 +147,7 @@ func (c *NetSocket) Collect(ctx context.Context) error { // val string // } -// sockstatCollect gets metrics from /proc/net/sockstat and /proc/net/sockstat6 +// sockstatCollect gets metrics from /proc/net/sockstat and /proc/net/sockstat6. func (c *NetSocket) sockstatCollect(metrics *cgm.Metrics) error { tagUnitsConnections := tags.Tag{Category: "units", Value: "connections"} @@ -161,7 +160,7 @@ func (c *NetSocket) sockstatCollect(metrics *cgm.Metrics) error { sockstatFile := strings.ReplaceAll(c.file, "dev", "sockstat") lines, err := c.readFile(sockstatFile) if err != nil { - return errors.Wrapf(err, "parsing %s", c.file) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } /* @@ -176,7 +175,7 @@ func (c *NetSocket) sockstatCollect(metrics *cgm.Metrics) error { // stats := make(map[string][]rawSocketStat) for _, l := range lines { - line := strings.TrimSpace(string(l)) + line := strings.TrimSpace(l) fields := strings.Fields(line) statType := strings.ToLower(strings.ReplaceAll(fields[0], ":", "")) @@ -409,7 +408,7 @@ func (c *NetSocket) sockstatCollect(metrics *cgm.Metrics) error { sockstatFile := strings.ReplaceAll(c.file, "dev", "sockstat6") lines, err := c.readFile(sockstatFile) if err != nil { - return errors.Wrapf(err, "parsing %s", c.file) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } /* @@ -423,7 +422,7 @@ func (c *NetSocket) sockstatCollect(metrics *cgm.Metrics) error { // stats := make(map[string][]rawSocketStat) for _, l := range lines { - line := strings.TrimSpace(string(l)) + line := strings.TrimSpace(l) fields := strings.Fields(line) statType := strings.ToLower(strings.ReplaceAll(fields[0], ":", "")) diff --git a/internal/builtins/collector/linux/procfs/procfs.go b/internal/builtins/collector/linux/procfs/procfs.go index de2365fd..778e99b1 100644 --- a/internal/builtins/collector/linux/procfs/procfs.go +++ b/internal/builtins/collector/linux/procfs/procfs.go @@ -37,11 +37,15 @@ const ( ) var ( - defaultExcludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, "")) - defaultIncludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, ".+")) + errInvalidMetric = fmt.Errorf("invalid metric, nil") + errInvalidMetricNoName = fmt.Errorf("invalid metric, no name") + errInvalidMetricNoType = fmt.Errorf("invalid metric, no type") + errInvalidFile = fmt.Errorf("invalid file, empty") + defaultExcludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, "")) + defaultIncludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, ".+")) ) -// New creates new ProcFS collector +// New creates new ProcFS collector. func New(ctx context.Context) ([]collector.Collector, error) { none := []collector.Collector{} diff --git a/internal/builtins/collector/linux/procfs/vm.go b/internal/builtins/collector/linux/procfs/vm.go index 2837d241..ca967da5 100644 --- a/internal/builtins/collector/linux/procfs/vm.go +++ b/internal/builtins/collector/linux/procfs/vm.go @@ -9,6 +9,7 @@ package procfs import ( "context" + "fmt" "os" "path/filepath" "strconv" @@ -19,15 +20,14 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// VM metrics from the Linux ProcFS +// VM metrics from the Linux ProcFS. type VM struct { common } -// vmOptions defines what elements can be overridden in a config file +// vmOptions defines what elements can be overridden in a config file. type vmOptions struct { // common ID string `json:"id" toml:"id" yaml:"id"` @@ -35,7 +35,7 @@ type vmOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewVMCollector creates new procfs vm collector +// NewVMCollector creates new procfs vm collector. func NewVMCollector(cfgBaseName, procFSPath string) (collector.Collector, error) { procFile := "meminfo" @@ -45,7 +45,7 @@ func NewVMCollector(cfgBaseName, procFSPath string) (collector.Collector, error) if cfgBaseName == "" { if _, err := os.Stat(c.file); err != nil { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } @@ -55,7 +55,7 @@ func NewVMCollector(cfgBaseName, procFSPath string) (collector.Collector, error) if err != nil { if !strings.Contains(err.Error(), "no config found matching") { c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } else { c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") @@ -73,19 +73,19 @@ func NewVMCollector(cfgBaseName, procFSPath string) (collector.Collector, error) if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } if _, err := os.Stat(c.file); os.IsNotExist(err) { - return nil, errors.Wrap(err, c.pkgID) + return nil, fmt.Errorf("%s procfile: %w", c.pkgID, err) } return &c, nil } -// Collect metrics from the procfs resource +// Collect metrics from the procfs resource. func (c *VM) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -110,12 +110,12 @@ func (c *VM) Collect(ctx context.Context) error { if err := c.parseMemstats(&metrics); err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s parseMemstats: %w", c.pkgID, err) } if err := c.parseVMstats(&metrics); err != nil { c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("%s parseVMstats: %w", c.pkgID, err) } c.setStatus(metrics, nil) @@ -125,7 +125,7 @@ func (c *VM) Collect(ctx context.Context) error { func (c *VM) parseMemstats(metrics *cgm.Metrics) error { lines, err := c.readFile(c.file) if err != nil { - return errors.Wrapf(err, "parsing %s", c.file) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } var memTotal, memFree, memCached, memBuffers, memSReclaimable, memShared, swapTotal, swapFree uint64 @@ -134,7 +134,7 @@ func (c *VM) parseMemstats(metrics *cgm.Metrics) error { tagUnitsHugePages := tags.Tag{Category: "units", Value: "hugepages"} for _, l := range lines { - line := strings.TrimSpace(string(l)) + line := strings.TrimSpace(l) fields := strings.Fields(line) if len(fields) < 2 { @@ -273,13 +273,13 @@ func (c *VM) parseVMstats(metrics *cgm.Metrics) error { file := strings.ReplaceAll(c.file, "meminfo", "vmstat") lines, err := c.readFile(file) if err != nil { - return errors.Wrapf(err, "parsing %s", file) + return fmt.Errorf("%s read file: %w", c.pkgID, err) } var pgFaults, pgMajorFaults, pgScan, pgSwap uint64 for _, l := range lines { - line := strings.TrimSpace(string(l)) + line := strings.TrimSpace(l) fields := strings.Fields(line) if len(fields) != 2 { diff --git a/internal/builtins/collector/prometheus/collector.go b/internal/builtins/collector/prometheus/collector.go index 24e685e6..0051dfd2 100644 --- a/internal/builtins/collector/prometheus/collector.go +++ b/internal/builtins/collector/prometheus/collector.go @@ -13,11 +13,10 @@ import ( "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" ) -// Flush returns last metrics collected +// Flush returns last metrics collected. func (c *Prom) Flush() cgm.Metrics { c.Lock() defer c.Unlock() @@ -27,12 +26,12 @@ func (c *Prom) Flush() cgm.Metrics { return c.lastMetrics } -// ID returns the id of the instance +// ID returns the id of the instance. func (c *Prom) ID() string { return "promfetch" } -// Inventory returns collector stats for /inventory endpoint +// Inventory returns collector stats for /inventory endpoint. func (c *Prom) Inventory() collector.InventoryStats { c.Lock() defer c.Unlock() @@ -45,28 +44,28 @@ func (c *Prom) Inventory() collector.InventoryStats { } } -// Logger returns collector's instance of logger +// Logger returns collector's instance of logger. func (c *Prom) Logger() zerolog.Logger { return c.logger } -// cleanName is used to clean the metric name +// cleanName is used to clean the metric name. func (c *Prom) cleanName(name string) string { return c.metricNameRegex.ReplaceAllString(name, "") } -// addMetric to internal buffer if metric is active +// addMetric to internal buffer if metric is active. func (c *Prom) addMetric(metrics *cgm.Metrics, prefix string, mname string, mtags tags.Tags, mtype string, mval interface{}) error { if metrics == nil { - return errors.New("invalid metric submission") + return errInvalidMetric } if mname == "" { - return errors.New("invalid metric, no name") + return errInvalidMetricNoName } if mtype == "" { - return errors.New("invalid metric, no type") + return errInvalidMetricNoType } // cleanup the raw metric name, if needed @@ -89,7 +88,7 @@ func (c *Prom) addMetric(metrics *cgm.Metrics, prefix string, mname string, mtag return nil } -// setStatus is used in Collect to set the collector status +// setStatus is used in Collect to set the collector status. func (c *Prom) setStatus(metrics cgm.Metrics, err error) { c.Lock() if err == nil { diff --git a/internal/builtins/collector/prometheus/collector_test.go b/internal/builtins/collector/prometheus/collector_test.go index 132a0abb..15527e24 100644 --- a/internal/builtins/collector/prometheus/collector_test.go +++ b/internal/builtins/collector/prometheus/collector_test.go @@ -6,7 +6,7 @@ package prometheus import ( - "errors" + "fmt" "reflect" "regexp" "testing" @@ -69,7 +69,7 @@ func TestAddMetric(t *testing.T) { if err := c.addMetric(nil, "", "", tags.Tags{}, "", ""); err == nil { t.Fatal("expected error") } else { - expect := "invalid metric submission" + expect := "invalid metric, nil" if err.Error() != expect { t.Fatalf("expected (%s) got (%v)", expect, err) } @@ -123,7 +123,7 @@ func TestSetStatus(t *testing.T) { t.Log("\tmetrics, no error") c.setStatus(m, nil) t.Log("\tmetrics, error") - c.setStatus(m, errors.New("foo")) + c.setStatus(m, fmt.Errorf("foo")) //nolint:goerr113 t.Log("\tmetrics, no error, add last start") c.lastStart = time.Now() diff --git a/internal/builtins/collector/prometheus/prometheus.go b/internal/builtins/collector/prometheus/prometheus.go index 1446868a..d5c4b787 100644 --- a/internal/builtins/collector/prometheus/prometheus.go +++ b/internal/builtins/collector/prometheus/prometheus.go @@ -7,6 +7,7 @@ package prometheus import ( "context" + "errors" "fmt" "io" "math" @@ -23,14 +24,13 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config/defaults" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) -// URLDef defines a url to fetch text formatted prom metrics from +// URLDef defines a url to fetch text formatted prom metrics from. type URLDef struct { ID string `json:"id" toml:"id" yaml:"id"` URL string `json:"url" toml:"url" yaml:"url"` @@ -38,7 +38,7 @@ type URLDef struct { uttl time.Duration } -// Prom defines prom collector +// Prom defines prom collector. type Prom struct { pkgID string // package prefix used for logging and errors lastError string // last collection error @@ -55,13 +55,20 @@ type Prom struct { sync.Mutex } -// promOptions defines what elements can be overridden in a config file +// promOptions defines what elements can be overridden in a config file. type promOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` URLs []URLDef `json:"urls" toml:"urls" yaml:"urls"` } -// New creates new prom collector +var ( + errInvalidMetric = fmt.Errorf("invalid metric, nil") + errInvalidMetricNoName = fmt.Errorf("invalid metric, no name") + errInvalidMetricNoType = fmt.Errorf("invalid metric, no type") + errInvalidURLs = fmt.Errorf("'urls' is REQUIRED in configuration") +) + +// New creates new prom collector. func New(cfgBaseName string) (collector.Collector, error) { c := Prom{ pkgID: "builtins.prometheus", @@ -87,13 +94,13 @@ func New(cfgBaseName string) (collector.Collector, error) { if errors.Is(err, os.ErrNotExist) { return nil, nil // if none found, return nothing } - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Str("base", cfgBaseName).Interface("config", opts).Msg("loaded config") if len(opts.URLs) == 0 { - return nil, errors.New("'urls' is REQUIRED in configuration") + return nil, errInvalidURLs } for i, u := range opts.URLs { if u.ID == "" { @@ -127,7 +134,7 @@ func New(cfgBaseName string) (collector.Collector, error) { if opts.RunTTL != "" { dur, err := time.ParseDuration(opts.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -135,7 +142,7 @@ func New(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect returns collector metrics +// Collect returns collector metrics. func (c *Prom) Collect(ctx context.Context) error { metrics := cgm.Metrics{} c.Lock() @@ -173,7 +180,7 @@ func (c *Prom) Collect(ctx context.Context) error { func (c *Prom) fetchPromMetrics(u URLDef, metrics *cgm.Metrics) error { req, err := http.NewRequest("GET", u.URL, nil) if err != nil { - return err + return fmt.Errorf("prepare reqeust: %w", err) } var ctx context.Context @@ -210,7 +217,7 @@ func (c *Prom) fetchPromMetrics(u URLDef, metrics *cgm.Metrics) error { select { case <-ctx.Done(): <-ec - return ctx.Err() + return ctx.Err() //nolint:wrapcheck case err := <-ec: return err } @@ -223,7 +230,7 @@ func (c *Prom) parse(id string, data io.Reader, metrics *cgm.Metrics) error { metricFamilies, err := parser.TextToMetricFamilies(data) if err != nil { - return err + return fmt.Errorf("parser - metric families: %w", err) } pfx := "" @@ -235,13 +242,13 @@ func (c *Prom) parse(id string, data io.Reader, metrics *cgm.Metrics) error { switch mf.GetType() { case dto.MetricType_SUMMARY: _ = c.addMetric(metrics, pfx, metricName+"_count", tags, "n", float64(m.GetSummary().GetSampleCount())) - _ = c.addMetric(metrics, pfx, metricName+"_sum", tags, "n", float64(m.GetSummary().GetSampleSum())) + _ = c.addMetric(metrics, pfx, metricName+"_sum", tags, "n", m.GetSummary().GetSampleSum()) for qn, qv := range c.getQuantiles(m) { _ = c.addMetric(metrics, pfx, metricName+"_"+qn, tags, "n", qv) } case dto.MetricType_HISTOGRAM: _ = c.addMetric(metrics, pfx, metricName+"_count", tags, "n", float64(m.GetHistogram().GetSampleCount())) - _ = c.addMetric(metrics, pfx, metricName+"_sum", tags, "n", float64(m.GetHistogram().GetSampleSum())) + _ = c.addMetric(metrics, pfx, metricName+"_sum", tags, "n", m.GetHistogram().GetSampleSum()) for bn, bv := range c.getBuckets(m) { _ = c.addMetric(metrics, pfx, metricName+"_"+bn, tags, "n", bv) } diff --git a/internal/builtins/collector/windows/nvidia/collector.go b/internal/builtins/collector/windows/nvidia/collector.go index 820a69bc..07e8d6f2 100644 --- a/internal/builtins/collector/windows/nvidia/collector.go +++ b/internal/builtins/collector/windows/nvidia/collector.go @@ -23,14 +23,14 @@ import ( // ID and Inventory are generic and do not need to be overridden unless the // collector implementation requires it. -// Collect metrics +// Collect metrics. func (c *common) Collect(ctx context.Context) error { c.Lock() defer c.Unlock() return collector.ErrNotImplemented } -// Flush returns last metrics collected +// Flush returns last metrics collected. func (c *common) Flush() cgm.Metrics { c.Lock() defer c.Unlock() @@ -41,14 +41,14 @@ func (c *common) Flush() cgm.Metrics { return *metrics } -// ID returns id of collector +// ID returns id of collector. func (c *common) ID() string { c.Lock() defer c.Unlock() return c.id } -// Inventory returns collector stats for /inventory endpoint +// Inventory returns collector stats for /inventory endpoint. func (c *common) Inventory() collector.InventoryStats { c.Lock() defer c.Unlock() @@ -61,7 +61,7 @@ func (c *common) Inventory() collector.InventoryStats { } } -// Logger returns collector's instance of logger +// Logger returns collector's instance of logger. func (c *common) Logger() zerolog.Logger { return c.logger } diff --git a/internal/builtins/collector/windows/nvidia/gpu.go b/internal/builtins/collector/windows/nvidia/gpu.go index 184ea963..80d9f9cc 100644 --- a/internal/builtins/collector/windows/nvidia/gpu.go +++ b/internal/builtins/collector/windows/nvidia/gpu.go @@ -12,6 +12,7 @@ import ( "bytes" "context" "encoding/csv" + "errors" "fmt" "os" "os/exec" @@ -24,13 +25,12 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) -// GPU metrics from the Windows Management Interface (wmi) +// GPU metrics from the Windows Management Interface (wmi). type GPU struct { exePath string exeArgs []string @@ -40,7 +40,7 @@ type GPU struct { interval time.Duration } -// gpuOptions defines what elements can be overridden in a config file +// gpuOptions defines what elements can be overridden in a config file. type gpuOptions struct { ID string `json:"id" toml:"id" yaml:"id"` ExePath string `mapstructure:"exe_path" json:"exe_path" toml:"exe_path" yaml:"exe_path"` @@ -62,7 +62,7 @@ type gpuMeta struct { TagName string `mapstructure:"tag_name" json:"tag_name" toml:"tag_name" yaml:"tag_name"` } -// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue) +// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue). type logshim struct { logh zerolog.Logger } @@ -71,7 +71,7 @@ func (l logshim) Printf(fmt string, v ...interface{}) { l.logh.Printf(fmt, v...) } -// NewGPUCollector creates new wmi collector +// NewGPUCollector creates new wmi collector. func NewGPUCollector(cfgBaseName string) (collector.Collector, error) { c := GPU{} c.id = "gpu" @@ -233,7 +233,7 @@ func NewGPUCollector(cfgBaseName string) (collector.Collector, error) { hm, err := cgm.NewCirconusMetrics(cmc) if err != nil { - return nil, errors.Wrap(err, "nvidia cgm") + return nil, fmt.Errorf("nvidia cgm: %w", err) } c.common.metrics = hm @@ -250,7 +250,7 @@ func NewGPUCollector(cfgBaseName string) (collector.Collector, error) { // return &c, nil } else { c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } } @@ -268,7 +268,7 @@ func NewGPUCollector(cfgBaseName string) (collector.Collector, error) { if cfg.Interval != "" { d, err := time.ParseDuration(cfg.Interval) if err != nil { - return nil, errors.Wrapf(err, "%s parsing interval", cfg.Interval) + return nil, fmt.Errorf("parsing interval: %w", err) } c.interval = d } @@ -322,20 +322,20 @@ func (gpu *GPU) tagMetadata() error { out, err := exec.Command(gpu.exePath, cmdArgs...).Output() //nolint:gosec if err != nil { - return errors.Wrap(err, "getting gpu metadata") + return fmt.Errorf("getting gpu metadata: %w", err) } r := csv.NewReader(bytes.NewBuffer(out)) records, err := r.ReadAll() if err != nil { - return errors.Wrap(err, "parsing gpu metadata") + return fmt.Errorf("parsing gpu metadata: %w", err) } if len(records) != 1 { - return errors.Errorf("invalid metadata %v", records) + return fmt.Errorf("invalid metadata %v", records) //nolint:goerr113 } if len(records[0]) != len(tagNames) { - return errors.Errorf("metadata mismatch expected %d, got %d", len(tagNames), len(records)) + return fmt.Errorf("metadata mismatch expected %d, got %d", len(tagNames), len(records)) //nolint:goerr113 } tagList := make([]tags.Tag, len(tagNames)) @@ -348,7 +348,7 @@ func (gpu *GPU) tagMetadata() error { return nil } -// Collect starts the background process if it is not running +// Collect starts the background process if it is not running. func (gpu *GPU) Collect(ctx context.Context) error { gpu.Lock() @@ -412,8 +412,8 @@ func (gpu *GPU) Collect(ctx context.Context) error { if errOut.Len() > 0 { stderr = strings.ReplaceAll(errOut.String(), "\n", "") } - var exiterr exec.ExitError - if errors.As(err, exiterr) { + var exiterr *exec.ExitError + if errors.As(err, &exiterr) { // if exiterr, ok := err.(*exec.ExitError); ok { errMsg := fmt.Sprintf("%s %s", stderr, exiterr.Stderr) gpu.logger.Error(). @@ -447,11 +447,11 @@ func (gpu *GPU) parseOutput(line string) error { records, err := r.ReadAll() if err != nil { - return errors.Wrap(err, "parsing csv") + return fmt.Errorf("parsing csv: %w", err) } if len(records) == 0 { - return fmt.Errorf("no metrics found in line (%s)", line) + return fmt.Errorf("no metrics found in line (%s)", line) //nolint:goerr113 } for lineID, record := range records { @@ -470,11 +470,11 @@ func (gpu *GPU) parseOutput(line string) error { metricName = metric.ArgName } origValue := strings.TrimSpace(record[i]) - if string(metric.MetricType[:1]) != "t" && origValue == "Not Available" { + if metric.MetricType[:1] != "t" && origValue == "Not Available" { // gpu.logger.Warn().Str("name", metricName).Str("value", origValue).Msg("ignoring") continue } - if string(metric.MetricType[:1]) != "t" && origValue == "N/A" { + if metric.MetricType[:1] != "t" && origValue == "N/A" { // gpu.logger.Warn().Str("name", metricName).Str("value", origValue).Msg("ignoring") continue } diff --git a/internal/builtins/collector/windows/nvidia/nvidia.go b/internal/builtins/collector/windows/nvidia/nvidia.go index d36c36ea..7b19d5f7 100644 --- a/internal/builtins/collector/windows/nvidia/nvidia.go +++ b/internal/builtins/collector/windows/nvidia/nvidia.go @@ -25,7 +25,7 @@ import ( "github.com/spf13/viper" ) -// common defines common elements for metrics collector +// common defines common elements for metrics collector. type common struct { id string // id of the collector (used as metric name prefix) pkgID string // package prefix used for logging and errors @@ -46,7 +46,7 @@ const ( pkgName = "builtins.windows.nvidia" ) -// New creates new Nvidia GPU collector +// New creates new Nvidia GPU collector. func New() ([]collector.Collector, error) { none := []collector.Collector{} l := log.With().Str("pkg", pkgName).Logger() diff --git a/internal/builtins/collector/windows/wmi/cache.go b/internal/builtins/collector/windows/wmi/cache.go index ead84e5e..e8610c30 100644 --- a/internal/builtins/collector/windows/wmi/cache.go +++ b/internal/builtins/collector/windows/wmi/cache.go @@ -9,16 +9,17 @@ package wmi import ( "context" + "fmt" "regexp" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -56,12 +57,12 @@ type Win32_PerfFormattedData_PerfOS_Cache struct { //nolint: golint SyncPinReadsPersec uint32 } -// Cache metrics from the Windows Management Interface (wmi) +// Cache metrics from the Windows Management Interface (wmi). type Cache struct { wmicommon } -// cacheOptions defines what elements can be overridden in a config file +// cacheOptions defines what elements can be overridden in a config file. type cacheOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -69,7 +70,7 @@ type cacheOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewCacheCollector creates new wmi collector +// NewCacheCollector creates new wmi collector. func NewCacheCollector(cfgBaseName string) (collector.Collector, error) { c := Cache{} c.id = "cache" @@ -90,7 +91,7 @@ func NewCacheCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -102,7 +103,7 @@ func NewCacheCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -114,7 +115,7 @@ func NewCacheCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -122,7 +123,7 @@ func NewCacheCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *Cache) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -154,7 +155,7 @@ func (c *Cache) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { diff --git a/internal/builtins/collector/windows/wmi/collector.go b/internal/builtins/collector/windows/wmi/collector.go index 0147744e..cf9c2d90 100644 --- a/internal/builtins/collector/windows/wmi/collector.go +++ b/internal/builtins/collector/windows/wmi/collector.go @@ -16,7 +16,6 @@ import ( "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" ) @@ -27,14 +26,14 @@ import ( // ID and Inventory are generic and do not need to be overridden unless the // collector implementation requires it. -// Collect metrics +// Collect metrics. func (c *wmicommon) Collect(ctx context.Context) error { c.Lock() defer c.Unlock() return collector.ErrNotImplemented } -// Flush returns last metrics collected +// Flush returns last metrics collected. func (c *wmicommon) Flush() cgm.Metrics { c.Lock() defer c.Unlock() @@ -44,14 +43,14 @@ func (c *wmicommon) Flush() cgm.Metrics { return c.lastMetrics } -// ID returns id of collector +// ID returns id of collector. func (c *wmicommon) ID() string { c.Lock() defer c.Unlock() return c.id } -// Inventory returns collector stats for /inventory endpoint +// Inventory returns collector stats for /inventory endpoint. func (c *wmicommon) Inventory() collector.InventoryStats { c.Lock() defer c.Unlock() @@ -64,28 +63,28 @@ func (c *wmicommon) Inventory() collector.InventoryStats { } } -// Logger returns collector's instance of logger +// Logger returns collector's instance of logger. func (c *wmicommon) Logger() zerolog.Logger { return c.logger } -// cleanName is used to clean the metric name +// cleanName is used to clean the metric name. func (c *wmicommon) cleanName(name string) string { return c.metricNameRegex.ReplaceAllString(name, c.metricNameChar) } -// addMetric to internal buffer if metric is active +// addMetric to internal buffer if metric is active. func (c *wmicommon) addMetric(metrics *cgm.Metrics, pfx, mname, mtype string, mval interface{}, mtags cgm.Tags) error { if metrics == nil { - return errors.New("invalid metric submission") + return errInvalidMetric } if mname == "" { - return errors.New("invalid metric, no name") + return errInvalidMetricNoName } if mtype == "" { - return errors.New("invalid metric, no type") + return errInvalidMetricNoType } var tagList cgm.Tags @@ -106,7 +105,7 @@ func (c *wmicommon) addMetric(metrics *cgm.Metrics, pfx, mname, mtype string, mv return nil } -// setStatus is used in Collect to set the collector status +// setStatus is used in Collect to set the collector status. func (c *wmicommon) setStatus(metrics cgm.Metrics, err error) { c.Lock() if err == nil { diff --git a/internal/builtins/collector/windows/wmi/collector_test.go b/internal/builtins/collector/windows/wmi/collector_test.go index a7b51bf2..2894caeb 100644 --- a/internal/builtins/collector/windows/wmi/collector_test.go +++ b/internal/builtins/collector/windows/wmi/collector_test.go @@ -9,7 +9,7 @@ package wmi import ( "context" - "errors" + "fmt" "reflect" "testing" "time" @@ -142,7 +142,7 @@ func TestSetStatus(t *testing.T) { t.Log("\tmetrics, no error") c.setStatus(m, nil) t.Log("\tmetrics, error") - c.setStatus(m, errors.New("foo")) + c.setStatus(m, fmt.Errorf("foo")) //nolint:goerr113 t.Log("\tmetrics, no error, add last start") c.lastStart = time.Now() diff --git a/internal/builtins/collector/windows/wmi/disk.go b/internal/builtins/collector/windows/wmi/disk.go index 50fdf484..29d51bcb 100644 --- a/internal/builtins/collector/windows/wmi/disk.go +++ b/internal/builtins/collector/windows/wmi/disk.go @@ -15,12 +15,12 @@ import ( "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -80,7 +80,7 @@ type Win32_PerfFormattedData_PerfDisk_LogicalDisk struct { //nolint: golint SplitIOPerSec uint32 } -// Win32_PerfFormattedData_PerfDisk_PhysicalDisk defines the metrics to collect +// Win32_PerfFormattedData_PerfDisk_PhysicalDisk defines the metrics to collect. type Win32_PerfFormattedData_PerfDisk_PhysicalDisk struct { //nolint: golint Name string AvgDiskBytesPerRead uint64 @@ -106,7 +106,7 @@ type Win32_PerfFormattedData_PerfDisk_PhysicalDisk struct { //nolint: golint SplitIOPerSec uint32 } -// Disk metrics from the Windows Management Interface (wmi) +// Disk metrics from the Windows Management Interface (wmi). type Disk struct { include *regexp.Regexp exclude *regexp.Regexp @@ -115,7 +115,7 @@ type Disk struct { physical bool } -// diskOptions defines what elements can be overridden in a config file +// diskOptions defines what elements can be overridden in a config file. type diskOptions struct { ID string `json:"id" toml:"id" yaml:"id"` IncludeLogical string `json:"logical_disks" toml:"logical_disks" yaml:"logical_disks"` @@ -127,7 +127,7 @@ type diskOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewDiskCollector creates new wmi collector +// NewDiskCollector creates new wmi collector. func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { c := Disk{} c.id = "disk" @@ -153,7 +153,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -161,7 +161,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { if cfg.IncludeLogical != "" { logical, err := strconv.ParseBool(cfg.IncludeLogical) if err != nil { - return nil, errors.Wrapf(err, "%s parsing disks", c.pkgID) + return nil, fmt.Errorf("%s parsing disks: %w", c.pkgID, err) } c.logical = logical } @@ -169,7 +169,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { if cfg.IncludePhysical != "" { physical, err := strconv.ParseBool(cfg.IncludePhysical) if err != nil { - return nil, errors.Wrapf(err, "%s parsing physical_disks", c.pkgID) + return nil, fmt.Errorf("%s parsing physical_disks: %w", c.pkgID, err) } c.physical = physical } @@ -178,7 +178,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { if cfg.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compile include rx: %w", c.pkgID, err) } c.include = rx } @@ -187,7 +187,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { if cfg.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compile exclude rx: %w", c.pkgID, err) } c.exclude = rx } @@ -199,7 +199,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric name rx: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -211,7 +211,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.wmicommon.runTTL = dur } @@ -219,7 +219,7 @@ func NewDiskCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *Disk) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -248,7 +248,7 @@ func (c *Disk) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) == 0 { @@ -267,7 +267,7 @@ func (c *Disk) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) == 0 { diff --git a/internal/builtins/collector/windows/wmi/memory.go b/internal/builtins/collector/windows/wmi/memory.go index cecbcfa2..010cfcd5 100644 --- a/internal/builtins/collector/windows/wmi/memory.go +++ b/internal/builtins/collector/windows/wmi/memory.go @@ -9,20 +9,21 @@ package wmi import ( "context" + "fmt" "regexp" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfFormattedData_PerfOS_Memory defines the metrics to collect +// Win32_PerfFormattedData_PerfOS_Memory defines the metrics to collect. type Win32_PerfFormattedData_PerfOS_Memory struct { //nolint: golint AvailableBytes uint64 CacheBytes uint64 @@ -56,12 +57,12 @@ type Win32_PerfFormattedData_PerfOS_Memory struct { //nolint: golint WriteCopiesPersec uint64 } -// Memory metrics from the Windows Management Interface (wmi) +// Memory metrics from the Windows Management Interface (wmi). type Memory struct { wmicommon } -// memoryOptions defines what elements can be overridden in a config file +// memoryOptions defines what elements can be overridden in a config file. type memoryOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -69,7 +70,7 @@ type memoryOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewMemoryCollector creates new wmi collector +// NewMemoryCollector creates new wmi collector. func NewMemoryCollector(cfgBaseName string) (collector.Collector, error) { c := Memory{} c.id = "memory" @@ -90,7 +91,7 @@ func NewMemoryCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -102,7 +103,7 @@ func NewMemoryCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric name rx: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -114,7 +115,7 @@ func NewMemoryCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -122,7 +123,7 @@ func NewMemoryCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *Memory) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -150,7 +151,7 @@ func (c *Memory) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricType := "L" diff --git a/internal/builtins/collector/windows/wmi/network_interface.go b/internal/builtins/collector/windows/wmi/network_interface.go index 3f2880ad..82973875 100644 --- a/internal/builtins/collector/windows/wmi/network_interface.go +++ b/internal/builtins/collector/windows/wmi/network_interface.go @@ -14,12 +14,12 @@ import ( "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -51,14 +51,14 @@ type Win32_PerfRawData_Tcpip_NetworkInterface struct { //nolint: golint TCPRSCExceptionsPersec uint64 } -// NetInterface metrics from the Windows Management Interface (wmi) +// NetInterface metrics from the Windows Management Interface (wmi). type NetInterface struct { include *regexp.Regexp exclude *regexp.Regexp wmicommon } -// netInterfaceOptions defines what elements can be overridden in a config file +// netInterfaceOptions defines what elements can be overridden in a config file. type netInterfaceOptions struct { ID string `json:"id" toml:"id" yaml:"id"` IncludeRegex string `json:"include_regex" toml:"include_regex" yaml:"include_regex"` @@ -68,7 +68,7 @@ type netInterfaceOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewNetInterfaceCollector creates new wmi collector +// NewNetInterfaceCollector creates new wmi collector. func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { c := NetInterface{} c.id = "network_interface" @@ -92,7 +92,7 @@ func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -101,7 +101,7 @@ func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { if cfg.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compile include rx: %w", c.pkgID, err) } c.include = rx } @@ -110,7 +110,7 @@ func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { if cfg.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compile exclude rx: %w", c.pkgID, err) } c.exclude = rx } @@ -122,7 +122,7 @@ func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric name rx: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -134,7 +134,7 @@ func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -142,7 +142,7 @@ func NewNetInterfaceCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *NetInterface) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -170,7 +170,7 @@ func (c *NetInterface) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricType := "L" diff --git a/internal/builtins/collector/windows/wmi/network_ip.go b/internal/builtins/collector/windows/wmi/network_ip.go index 53bf30ed..f3bf10e1 100755 --- a/internal/builtins/collector/windows/wmi/network_ip.go +++ b/internal/builtins/collector/windows/wmi/network_ip.go @@ -9,21 +9,22 @@ package wmi import ( "context" + "fmt" "regexp" "strconv" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfRawData_Tcpip_IPv4 defines the metrics to collect +// Win32_PerfRawData_Tcpip_IPv4 defines the metrics to collect. type Win32_PerfRawData_Tcpip_IPv4 struct { //nolint: golint DatagramsForwardedPersec uint32 DatagramsOutboundDiscarded uint32 @@ -44,7 +45,7 @@ type Win32_PerfRawData_Tcpip_IPv4 struct { //nolint: golint FragmentsReceivedPersec uint32 } -// Win32_PerfRawData_Tcpip_IPv6 defines the metrics to collect +// Win32_PerfRawData_Tcpip_IPv6 defines the metrics to collect. type Win32_PerfRawData_Tcpip_IPv6 struct { //nolint: golint DatagramsForwardedPersec uint32 DatagramsOutboundDiscarded uint32 @@ -65,14 +66,14 @@ type Win32_PerfRawData_Tcpip_IPv6 struct { //nolint: golint FragmentsReceivedPersec uint32 } -// NetIP metrics from the Windows Management Interface (wmi) +// NetIP metrics from the Windows Management Interface (wmi). type NetIP struct { wmicommon ipv4Enabled bool ipv6Enabled bool } -// NetIPOptions defines what elements can be overridden in a config file +// NetIPOptions defines what elements can be overridden in a config file. type NetIPOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -82,7 +83,7 @@ type NetIPOptions struct { EnableIPv6 string `json:"enable_ipv6" toml:"enable_ipv6" yaml:"enable_ipv6"` } -// NewNetIPCollector creates new wmi collector +// NewNetIPCollector creates new wmi collector. func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { c := NetIP{} c.id = "net_ip" @@ -106,7 +107,7 @@ func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -114,7 +115,7 @@ func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.EnableIPv4 != "" { ipv4, err := strconv.ParseBool(cfg.EnableIPv4) if err != nil { - return nil, errors.Wrapf(err, "%s parsing enable_ipv4", c.pkgID) + return nil, fmt.Errorf("%s parsing enable_ipv4: %w", c.pkgID, err) } c.ipv4Enabled = ipv4 } @@ -122,7 +123,7 @@ func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.EnableIPv6 != "" { ipv6, err := strconv.ParseBool(cfg.EnableIPv6) if err != nil { - return nil, errors.Wrapf(err, "%s parsing enable_ipv6", c.pkgID) + return nil, fmt.Errorf("%s parsing enable_ipv6: %w", c.pkgID, err) } c.ipv6Enabled = ipv6 } @@ -134,7 +135,7 @@ func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric name rx: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -146,7 +147,7 @@ func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -154,7 +155,7 @@ func NewNetIPCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *NetIP) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -187,7 +188,7 @@ func (c *NetIP) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { @@ -223,7 +224,7 @@ func (c *NetIP) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { diff --git a/internal/builtins/collector/windows/wmi/network_tcp.go b/internal/builtins/collector/windows/wmi/network_tcp.go index 35f0715b..07394e8b 100755 --- a/internal/builtins/collector/windows/wmi/network_tcp.go +++ b/internal/builtins/collector/windows/wmi/network_tcp.go @@ -9,21 +9,22 @@ package wmi import ( "context" + "fmt" "regexp" "strconv" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfRawData_Tcpip_TCPv4 defines the metrics to collect +// Win32_PerfRawData_Tcpip_TCPv4 defines the metrics to collect. type Win32_PerfRawData_Tcpip_TCPv4 struct { //nolint: golint ConnectionFailures uint32 ConnectionsActive uint32 @@ -36,7 +37,7 @@ type Win32_PerfRawData_Tcpip_TCPv4 struct { //nolint: golint SegmentsSentPersec uint32 } -// Win32_PerfRawData_Tcpip_TCPv6 defines the metrics to collect +// Win32_PerfRawData_Tcpip_TCPv6 defines the metrics to collect. type Win32_PerfRawData_Tcpip_TCPv6 struct { //nolint: golint ConnectionFailures uint32 ConnectionsActive uint32 @@ -49,14 +50,14 @@ type Win32_PerfRawData_Tcpip_TCPv6 struct { //nolint: golint SegmentsSentPersec uint32 } -// NetTCP metrics from the Windows Management Interface (wmi) +// NetTCP metrics from the Windows Management Interface (wmi). type NetTCP struct { wmicommon ipv4Enabled bool ipv6Enabled bool } -// NetTCPOptions defines what elements can be overridden in a config file +// NetTCPOptions defines what elements can be overridden in a config file. type NetTCPOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -66,7 +67,7 @@ type NetTCPOptions struct { EnableIPv6 string `json:"enable_ipv6" toml:"enable_ipv6" yaml:"enable_ipv6"` } -// NewNetTCPCollector creates new wmi collector +// NewNetTCPCollector creates new wmi collector. func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { c := NetTCP{} c.id = "net_tcp" @@ -90,7 +91,7 @@ func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -98,7 +99,7 @@ func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.EnableIPv4 != "" { ipv4, err := strconv.ParseBool(cfg.EnableIPv4) if err != nil { - return nil, errors.Wrapf(err, "%s parsing enable_ipv4", c.pkgID) + return nil, fmt.Errorf("%s parsing enable_ipv4: %w", c.pkgID, err) } c.ipv4Enabled = ipv4 } @@ -106,7 +107,7 @@ func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.EnableIPv6 != "" { ipv6, err := strconv.ParseBool(cfg.EnableIPv6) if err != nil { - return nil, errors.Wrapf(err, "%s parsing enable_ipv6", c.pkgID) + return nil, fmt.Errorf("%s parsing enable_ipv6: %w", c.pkgID, err) } c.ipv6Enabled = ipv6 } @@ -118,7 +119,7 @@ func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -130,7 +131,7 @@ func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -138,7 +139,7 @@ func NewNetTCPCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *NetTCP) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -171,7 +172,7 @@ func (c *NetTCP) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { @@ -199,7 +200,7 @@ func (c *NetTCP) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { diff --git a/internal/builtins/collector/windows/wmi/network_udp.go b/internal/builtins/collector/windows/wmi/network_udp.go index 30823f2e..9526b75f 100755 --- a/internal/builtins/collector/windows/wmi/network_udp.go +++ b/internal/builtins/collector/windows/wmi/network_udp.go @@ -9,21 +9,22 @@ package wmi import ( "context" + "fmt" "regexp" "strconv" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfRawData_Tcpip_UDPv4 defines the metrics to collect +// Win32_PerfRawData_Tcpip_UDPv4 defines the metrics to collect. type Win32_PerfRawData_Tcpip_UDPv4 struct { //nolint: golint DatagramsNoPortPersec uint32 DatagramsPersec uint32 @@ -32,7 +33,7 @@ type Win32_PerfRawData_Tcpip_UDPv4 struct { //nolint: golint DatagramsSentPersec uint32 } -// Win32_PerfRawData_Tcpip_UDPv6 defines the metrics to collect +// Win32_PerfRawData_Tcpip_UDPv6 defines the metrics to collect. type Win32_PerfRawData_Tcpip_UDPv6 struct { //nolint: golint DatagramsNoPortPersec uint32 DatagramsPersec uint32 @@ -41,14 +42,14 @@ type Win32_PerfRawData_Tcpip_UDPv6 struct { //nolint: golint DatagramsSentPersec uint32 } -// NetUDP metrics from the Windows Management Interface (wmi) +// NetUDP metrics from the Windows Management Interface (wmi). type NetUDP struct { wmicommon ipv4Enabled bool ipv6Enabled bool } -// NetUDPOptions defines what elements can be overridden in a config file +// NetUDPOptions defines what elements can be overridden in a config file. type NetUDPOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -58,7 +59,7 @@ type NetUDPOptions struct { EnableIPv6 string `json:"enable_ipv6" toml:"enable_ipv6" yaml:"enable_ipv6"` } -// NewNetUDPCollector creates new wmi collector +// NewNetUDPCollector creates new wmi collector. func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { c := NetUDP{} c.id = "net_udp" @@ -82,7 +83,7 @@ func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -90,7 +91,7 @@ func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.EnableIPv4 != "" { ipv4, err := strconv.ParseBool(cfg.EnableIPv4) if err != nil { - return nil, errors.Wrapf(err, "%s parsing enable_ipv4", c.pkgID) + return nil, fmt.Errorf("%s parsing enable_ipv4: %w", c.pkgID, err) } c.ipv4Enabled = ipv4 } @@ -98,7 +99,7 @@ func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.EnableIPv6 != "" { ipv6, err := strconv.ParseBool(cfg.EnableIPv6) if err != nil { - return nil, errors.Wrapf(err, "%s parsing enable_ipv6", c.pkgID) + return nil, fmt.Errorf("%s parsing enable_ipv6: %w", c.pkgID, err) } c.ipv6Enabled = ipv6 } @@ -110,7 +111,7 @@ func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -122,7 +123,7 @@ func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -130,7 +131,7 @@ func NewNetUDPCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *NetUDP) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -162,7 +163,7 @@ func (c *NetUDP) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { @@ -186,7 +187,7 @@ func (c *NetUDP) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } if len(dst) > 1 { diff --git a/internal/builtins/collector/windows/wmi/objects.go b/internal/builtins/collector/windows/wmi/objects.go index f3178019..803e17d1 100644 --- a/internal/builtins/collector/windows/wmi/objects.go +++ b/internal/builtins/collector/windows/wmi/objects.go @@ -9,20 +9,21 @@ package wmi import ( "context" + "fmt" "regexp" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfFormattedData_PerfOS_Objects defines the metrics to collect +// Win32_PerfFormattedData_PerfOS_Objects defines the metrics to collect. type Win32_PerfFormattedData_PerfOS_Objects struct { //nolint: golint Events uint32 Mutexes uint32 @@ -32,12 +33,12 @@ type Win32_PerfFormattedData_PerfOS_Objects struct { //nolint: golint Threads uint32 } -// Objects metrics from the Windows Management Interface (wmi) +// Objects metrics from the Windows Management Interface (wmi). type Objects struct { wmicommon } -// objectsOptions defines what elements can be overridden in a config file +// objectsOptions defines what elements can be overridden in a config file. type objectsOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -45,7 +46,7 @@ type objectsOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewObjectsCollector creates new wmi collector +// NewObjectsCollector creates new wmi collector. func NewObjectsCollector(cfgBaseName string) (collector.Collector, error) { c := Objects{} c.id = "objects" @@ -66,7 +67,7 @@ func NewObjectsCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -78,7 +79,7 @@ func NewObjectsCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -90,7 +91,7 @@ func NewObjectsCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -98,7 +99,7 @@ func NewObjectsCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *Objects) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -126,7 +127,7 @@ func (c *Objects) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricType := "I" diff --git a/internal/builtins/collector/windows/wmi/paging_file.go b/internal/builtins/collector/windows/wmi/paging_file.go index 3ea254a9..f68c03bd 100644 --- a/internal/builtins/collector/windows/wmi/paging_file.go +++ b/internal/builtins/collector/windows/wmi/paging_file.go @@ -14,29 +14,29 @@ import ( "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfFormattedData_PerfOS_PagingFile defines the metrics to collect +// Win32_PerfFormattedData_PerfOS_PagingFile defines the metrics to collect. type Win32_PerfFormattedData_PerfOS_PagingFile struct { //nolint: golint Name string PercentUsage uint32 } -// PagingFile metrics from the Windows Management Interface (wmi) +// PagingFile metrics from the Windows Management Interface (wmi). type PagingFile struct { include *regexp.Regexp exclude *regexp.Regexp wmicommon } -// pagingFileOptions defines what elements can be overridden in a config file +// pagingFileOptions defines what elements can be overridden in a config file. type pagingFileOptions struct { ID string `json:"id" toml:"id" yaml:"id"` IncludeRegex string `json:"include_regex" toml:"include_regex" yaml:"include_regex"` @@ -46,7 +46,7 @@ type pagingFileOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewPagingFileCollector creates new wmi collector +// NewPagingFileCollector creates new wmi collector. func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { c := PagingFile{} c.id = "paging_file" @@ -70,7 +70,7 @@ func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -79,7 +79,7 @@ func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { if cfg.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compiling include regex: %w", c.pkgID, err) } c.include = rx } @@ -88,7 +88,7 @@ func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { if cfg.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compiling exclude regex: %w", c.pkgID, err) } c.exclude = rx } @@ -100,7 +100,7 @@ func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -112,7 +112,7 @@ func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -120,7 +120,7 @@ func NewPagingFileCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *PagingFile) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -148,7 +148,7 @@ func (c *PagingFile) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricType := "I" diff --git a/internal/builtins/collector/windows/wmi/processes.go b/internal/builtins/collector/windows/wmi/processes.go index 9f956520..ffe90717 100755 --- a/internal/builtins/collector/windows/wmi/processes.go +++ b/internal/builtins/collector/windows/wmi/processes.go @@ -14,12 +14,12 @@ import ( "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -57,14 +57,14 @@ type Win32_PerfFormattedData_PerfProc_Process struct { //nolint: golint ThreadCount uint32 } -// Processes metrics from the Windows Management Interface (wmi) +// Processes metrics from the Windows Management Interface (wmi). type Processes struct { include *regexp.Regexp exclude *regexp.Regexp wmicommon } -// ProcessesOptions defines what elements can be overridden in a config file +// ProcessesOptions defines what elements can be overridden in a config file. type ProcessesOptions struct { ID string `json:"id" toml:"id" yaml:"id"` IncludeRegex string `json:"include_regex" toml:"include_regex" yaml:"include_regex"` @@ -74,7 +74,7 @@ type ProcessesOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewProcessesCollector creates new wmi collector +// NewProcessesCollector creates new wmi collector. func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { c := Processes{} c.id = "processes" @@ -98,7 +98,7 @@ func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -107,7 +107,7 @@ func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { if cfg.IncludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.IncludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling include regex", c.pkgID) + return nil, fmt.Errorf("%s compiling include regex: %w", c.pkgID, err) } c.include = rx } @@ -116,7 +116,7 @@ func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { if cfg.ExcludeRegex != "" { rx, err := regexp.Compile(fmt.Sprintf(regexPat, cfg.ExcludeRegex)) if err != nil { - return nil, errors.Wrapf(err, "%s compiling exclude regex", c.pkgID) + return nil, fmt.Errorf("%s compiling exclude regex: %w", c.pkgID, err) } c.exclude = rx } @@ -128,7 +128,7 @@ func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -140,7 +140,7 @@ func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -148,7 +148,7 @@ func NewProcessesCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *Processes) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -176,7 +176,7 @@ func (c *Processes) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricTypeUint32 := "I" diff --git a/internal/builtins/collector/windows/wmi/processor.go b/internal/builtins/collector/windows/wmi/processor.go index 0109a294..1c923b80 100644 --- a/internal/builtins/collector/windows/wmi/processor.go +++ b/internal/builtins/collector/windows/wmi/processor.go @@ -9,22 +9,23 @@ package wmi import ( "context" + "fmt" "regexp" "runtime" "strconv" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) -// Win32_PerfFormattedData_PerfOS_Processor defines the metrics to collect +// Win32_PerfFormattedData_PerfOS_Processor defines the metrics to collect. type Win32_PerfFormattedData_PerfOS_Processor struct { //nolint: golint Name string C1TransitionsPersec uint64 @@ -43,14 +44,14 @@ type Win32_PerfFormattedData_PerfOS_Processor struct { //nolint: golint PercentUserTime uint64 } -// Processor metrics from the Windows Management Interface (wmi) +// Processor metrics from the Windows Management Interface (wmi). type Processor struct { wmicommon numCPU float64 reportAllCPUs bool // may be overridden in config file } -// processorOptions defines what elements can be overridden in a config file +// processorOptions defines what elements can be overridden in a config file. type processorOptions struct { ID string `json:"id" toml:"id" yaml:"id"` AllCPU string `json:"report_all_cpus" toml:"report_all_cpus" yaml:"report_all_cpus"` @@ -59,7 +60,7 @@ type processorOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewProcessorCollector creates new wmi collector +// NewProcessorCollector creates new wmi collector. func NewProcessorCollector(cfgBaseName string) (collector.Collector, error) { c := Processor{} c.id = "processor" @@ -83,7 +84,7 @@ func NewProcessorCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -91,7 +92,7 @@ func NewProcessorCollector(cfgBaseName string) (collector.Collector, error) { if cfg.AllCPU != "" { rpt, err := strconv.ParseBool(cfg.AllCPU) if err != nil { - return nil, errors.Wrapf(err, "%s parsing report_all_cpus", c.pkgID) + return nil, fmt.Errorf("%s parsing report_all_cpus: %w", c.pkgID, err) } c.reportAllCPUs = rpt } @@ -103,7 +104,7 @@ func NewProcessorCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -115,7 +116,7 @@ func NewProcessorCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -123,7 +124,7 @@ func NewProcessorCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *Processor) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -151,7 +152,7 @@ func (c *Processor) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricType := "L" diff --git a/internal/builtins/collector/windows/wmi/system.go b/internal/builtins/collector/windows/wmi/system.go index c237ca8d..761d0af0 100644 --- a/internal/builtins/collector/windows/wmi/system.go +++ b/internal/builtins/collector/windows/wmi/system.go @@ -9,16 +9,17 @@ package wmi import ( "context" + "fmt" "regexp" "strings" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -52,12 +53,12 @@ type Win32_PerfFormattedData_PerfOS_System struct { Threads uint32 } -// System metrics from the Windows Management Interface (wmi) +// System metrics from the Windows Management Interface (wmi). type System struct { wmicommon } -// systemOptions defines what elements can be overridden in a config file +// systemOptions defines what elements can be overridden in a config file. type systemOptions struct { ID string `json:"id" toml:"id" yaml:"id"` MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"` @@ -65,7 +66,7 @@ type systemOptions struct { RunTTL string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"` } -// NewSystemCollector creates new wmi collector +// NewSystemCollector creates new wmi collector. func NewSystemCollector(cfgBaseName string) (collector.Collector, error) { c := System{} c.id = "system" @@ -86,7 +87,7 @@ func NewSystemCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file") - return nil, errors.Wrapf(err, "%s config", c.pkgID) + return nil, fmt.Errorf("%s config: %w", c.pkgID, err) } c.logger.Debug().Interface("config", cfg).Msg("loaded config") @@ -98,7 +99,7 @@ func NewSystemCollector(cfgBaseName string) (collector.Collector, error) { if cfg.MetricNameRegex != "" { rx, err := regexp.Compile(cfg.MetricNameRegex) if err != nil { - return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID) + return nil, fmt.Errorf("%s compile metric_name_regex: %w", c.pkgID, err) } c.metricNameRegex = rx } @@ -110,7 +111,7 @@ func NewSystemCollector(cfgBaseName string) (collector.Collector, error) { if cfg.RunTTL != "" { dur, err := time.ParseDuration(cfg.RunTTL) if err != nil { - return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID) + return nil, fmt.Errorf("%s parsing run_ttl: %w", c.pkgID, err) } c.runTTL = dur } @@ -118,7 +119,7 @@ func NewSystemCollector(cfgBaseName string) (collector.Collector, error) { return &c, nil } -// Collect metrics from the wmi resource +// Collect metrics from the wmi resource. func (c *System) Collect(ctx context.Context) error { metrics := cgm.Metrics{} @@ -146,7 +147,7 @@ func (c *System) Collect(ctx context.Context) error { if err := wmi.Query(qry, &dst); err != nil { c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error") c.setStatus(metrics, err) - return errors.Wrap(err, c.pkgID) + return fmt.Errorf("wmi %s query: %w", c.pkgID, err) } metricType := "L" diff --git a/internal/builtins/collector/windows/wmi/wmi.go b/internal/builtins/collector/windows/wmi/wmi.go index 15577408..52efbbf1 100644 --- a/internal/builtins/collector/windows/wmi/wmi.go +++ b/internal/builtins/collector/windows/wmi/wmi.go @@ -16,7 +16,8 @@ import ( "sync" "time" - "github.com/StackExchange/wmi" + // "github.com/StackExchange/wmi". + "github.com/bi-zone/wmi" "github.com/circonus-labs/circonus-agent/internal/builtins/collector" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/config/defaults" @@ -27,7 +28,7 @@ import ( "github.com/spf13/viper" ) -// wmicommon defines WMI metrics common elements +// wmicommon defines WMI metrics common elements. type wmicommon struct { id string // id of the collector (used as metric name prefix) pkgID string // package prefix used for logging and errors @@ -55,6 +56,9 @@ const ( ) var ( + errInvalidMetric = fmt.Errorf("invalid metric, nil") + errInvalidMetricNoName = fmt.Errorf("invalid metric, no name") + errInvalidMetricNoType = fmt.Errorf("invalid metric, no type") defaultExcludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, ``)) defaultIncludeRegex = regexp.MustCompile(fmt.Sprintf(regexPat, `.+`)) defaultMetricNameRegex = regexp.MustCompile(`[^a-zA-Z0-9.-_:` + metricNameSeparator + `]`) @@ -64,15 +68,16 @@ func initialize() error { // This initialization prevents a memory leak on WMF 5+. See // https://github.com/martinlindhe/wmi_exporter/issues/77 and // linked issues for details. - s, err := wmi.InitializeSWbemServices(wmi.DefaultClient) + // s, err := wmi.InitializeSWbemServices(wmi.DefaultClient) + s, err := wmi.NewSWbemServices() if err != nil { - return err + return fmt.Errorf("init SWbemSvc: %w", err) } wmi.DefaultClient.SWbemServicesClient = s return nil } -// New creates new WMI collector +// New creates new WMI collector. func New() ([]collector.Collector, error) { none := []collector.Collector{} l := log.With().Str("pkg", pkgName).Logger() diff --git a/internal/builtins/configure.go b/internal/builtins/configure.go index 620fb0fc..378a55bc 100644 --- a/internal/builtins/configure.go +++ b/internal/builtins/configure.go @@ -9,6 +9,7 @@ package builtins import ( "context" + "fmt" "github.com/circonus-labs/circonus-agent/internal/builtins/collector/generic" appstats "github.com/maier/go-appstats" @@ -21,7 +22,7 @@ func (b *Builtins) configure(ctx context.Context) error { l.Debug().Msg("calling generic.New") collectors, err := generic.New() if err != nil { - return err + return fmt.Errorf("generic collectors: %w", err) } for _, c := range collectors { b.logger.Info().Str("id", c.ID()).Msg("enabled builtin") diff --git a/internal/builtins/configure_linux.go b/internal/builtins/configure_linux.go index 34e8f60c..c45e8cda 100644 --- a/internal/builtins/configure_linux.go +++ b/internal/builtins/configure_linux.go @@ -9,6 +9,7 @@ package builtins import ( "context" + "fmt" "github.com/circonus-labs/circonus-agent/internal/builtins/collector/generic" "github.com/circonus-labs/circonus-agent/internal/builtins/collector/linux/procfs" @@ -27,7 +28,7 @@ func (b *Builtins) configure(ctx context.Context) error { l.Debug().Msg("calling procfs.New") collectors, err := procfs.New(ctx) if err != nil { - return err + return fmt.Errorf("procfs collectors: %w", err) } for _, c := range collectors { b.logger.Info().Str("id", c.ID()).Msg("enabled procfs builtin") @@ -46,7 +47,7 @@ func (b *Builtins) configure(ctx context.Context) error { l.Debug().Msg("calling generic.New") collectors, err := generic.New() if err != nil { - return err + return fmt.Errorf("generic collectors: %w", err) } for _, c := range collectors { if _, exists := b.collectors[c.ID()]; !exists { diff --git a/internal/builtins/configure_windows.go b/internal/builtins/configure_windows.go index c1e66f80..f6618fee 100644 --- a/internal/builtins/configure_windows.go +++ b/internal/builtins/configure_windows.go @@ -9,6 +9,7 @@ package builtins import ( "context" + "fmt" "github.com/circonus-labs/circonus-agent/internal/builtins/collector/generic" "github.com/circonus-labs/circonus-agent/internal/builtins/collector/windows/nvidia" @@ -25,7 +26,7 @@ func (b *Builtins) configure(ctx context.Context) error { l.Debug().Msg("calling wmi.New") collectors, err := wmi.New() if err != nil { - return err + return fmt.Errorf("wmi collectors: %w", err) } for _, c := range collectors { b.logger.Info().Str("id", c.ID()).Msg("enabled wmi builtin") @@ -39,7 +40,7 @@ func (b *Builtins) configure(ctx context.Context) error { l.Debug().Msg("calling nvidia.new") collectors, err := nvidia.New() if err != nil { - return err + return fmt.Errorf("nvidia collector: %w", err) } for _, c := range collectors { // kick off any long running processes @@ -61,7 +62,7 @@ func (b *Builtins) configure(ctx context.Context) error { l.Debug().Msg("calling generic.New") collectors, err := generic.New() if err != nil { - return err + return fmt.Errorf("generic collectors: %w", err) } for _, c := range collectors { if _, exists := b.collectors[c.ID()]; !exists { diff --git a/internal/check/api.go b/internal/check/api.go index a8581eb9..054443c7 100644 --- a/internal/check/api.go +++ b/internal/check/api.go @@ -9,7 +9,7 @@ import ( "github.com/circonus-labs/go-apiclient" ) -// API interface abstraction of circonus api (for mocking) +// API interface abstraction of circonus api (for mocking). type API interface { CreateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) FetchBroker(cid apiclient.CIDType) (*apiclient.Broker, error) diff --git a/internal/check/api_test.go b/internal/check/api_test.go index 49eae6c5..312c9e11 100644 --- a/internal/check/api_test.go +++ b/internal/check/api_test.go @@ -2,12 +2,12 @@ package check import ( "encoding/json" + "fmt" "io/ioutil" "strings" "github.com/circonus-labs/go-apiclient" "github.com/gojuno/minimock/v3" - "github.com/pkg/errors" ) type pkicacert struct { @@ -58,7 +58,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { m.FetchBrokerMock.Set(func(cid apiclient.CIDType) (*apiclient.Broker, error) { switch *cid { case "/broker/000": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/broker/123": return &apiclient.Broker{ CID: "/broker/123", @@ -88,7 +88,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/broker/1234": return &testBroker, nil default: - return nil, errors.Errorf("bad broker request cid (%s)", *cid) + return nil, fmt.Errorf("bad broker request cid (%s)", *cid) //nolint:goerr113 } }) @@ -101,7 +101,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { m.FetchCheckMock.Set(func(cid apiclient.CIDType) (*apiclient.Check, error) { switch *cid { case "/check_bundle/000": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/check/0002": x := testCheck x.CID = *cid @@ -109,14 +109,14 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/check/1234": return &testCheck, nil default: - return nil, errors.Errorf("bad request cid (%s)", *cid) + return nil, fmt.Errorf("bad request cid (%s)", *cid) //nolint:goerr113 } }) m.FetchCheckBundleMock.Set(func(cid apiclient.CIDType) (*apiclient.CheckBundle, error) { switch *cid { case "/check_bundle/000": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/check_bundle/0002": x := testCheckBundle x.CID = *cid @@ -124,7 +124,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/check_bundle/1234": return &testCheckBundle, nil default: - return nil, errors.Errorf("bad request cid (%s)", *cid) + return nil, fmt.Errorf("bad request cid (%s)", *cid) //nolint:goerr113 } }) @@ -141,7 +141,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { } return ret, nil case "/check_bundle_metrics/000?query_broker=1": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/check_bundle_metrics/0001?query_broker=1": return []byte("{"), nil case "/check_bundle_metrics/1234?query_broker=1": @@ -157,13 +157,13 @@ func genMockClient(mc *minimock.Controller) *APIMock { } return data, nil default: - return nil, errors.Errorf("bad apiclient.Get(%s), no handler for url", url) + return nil, fmt.Errorf("bad apiclient.Get(%s), no handler for url", url) //nolint:goerr113 } }) m.SearchCheckBundlesMock.Set(func(searchCriteria *apiclient.SearchQueryType, filterCriteria *apiclient.SearchFilterType) (*[]apiclient.CheckBundle, error) { if strings.Contains(string(*searchCriteria), `target:"000"`) { - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 } if strings.Contains(string(*searchCriteria), `target:"not_found"`) { return &[]apiclient.CheckBundle{}, nil @@ -174,7 +174,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { if strings.Contains(string(*searchCriteria), `target:"valid"`) { return &[]apiclient.CheckBundle{testCheckBundle}, nil } - return nil, errors.Errorf("don't know what to do with search criteria (%s)", string(*searchCriteria)) + return nil, fmt.Errorf("don't know what to do with search criteria (%s)", string(*searchCriteria)) //nolint:goerr113 }) m.UpdateCheckBundleMock.Set(func(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) { @@ -182,9 +182,9 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/check_bundle/1234": return cfg, nil case "/check_bundle/0002": - return nil, errors.New("api update check bundle error") + return nil, fmt.Errorf("api update check bundle error") //nolint:goerr113 default: - return nil, errors.Errorf("add handler for %s", cfg.CID) + return nil, fmt.Errorf("add handler for %s", cfg.CID) //nolint:goerr113 } }) diff --git a/internal/check/broker.go b/internal/check/broker.go index f945e775..40814e27 100644 --- a/internal/check/broker.go +++ b/internal/check/broker.go @@ -14,14 +14,19 @@ import ( "net/url" "github.com/circonus-labs/circonus-agent/internal/config" - "github.com/pkg/errors" "github.com/spf13/viper" ) -// brokerTLSConfig returns the correct TLS configuration for the broker +var ( + errBrokerNotInitialized = fmt.Errorf("broker not initialized") + errBrokerAddCACertToPool = fmt.Errorf("unable to add Broker CA Certificate to x509 cert pool") + errBrokerMatchRevURLHost = fmt.Errorf("unable to match reverse URL host to broker") +) + +// brokerTLSConfig returns the correct TLS configuration for the broker. func (c *Check) brokerTLSConfig(reverseURL *url.URL) (*tls.Config, string, error) { if c.broker == nil { - return nil, "", errors.New("broker not initialized") + return nil, "", errBrokerNotInitialized } cn, err := c.getBrokerCN(reverseURL) @@ -34,7 +39,7 @@ func (c *Check) brokerTLSConfig(reverseURL *url.URL) (*tls.Config, string, error } cp := x509.NewCertPool() if !cp.AppendCertsFromPEM(cert) { - return nil, "", errors.New("unable to add Broker CA Certificate to x509 cert pool") + return nil, "", errBrokerAddCACertToPool } tlsConfig := &tls.Config{ @@ -46,7 +51,7 @@ func (c *Check) brokerTLSConfig(reverseURL *url.URL) (*tls.Config, string, error VerifyConnection: func(cs tls.ConnectionState) error { commonName := cs.PeerCertificates[0].Subject.CommonName if commonName != cs.ServerName { - return fmt.Errorf("invalid certificate name %q, expected %q", commonName, cs.ServerName) + return fmt.Errorf("invalid certificate name %q, expected %q", commonName, cs.ServerName) //nolint:goerr113 } opts := x509.VerifyOptions{ Roots: cp, @@ -56,7 +61,7 @@ func (c *Check) brokerTLSConfig(reverseURL *url.URL) (*tls.Config, string, error opts.Intermediates.AddCert(cert) } _, err := cs.PeerCertificates[0].Verify(opts) - return err + return fmt.Errorf("verify peer cert: %w", err) }, } @@ -92,7 +97,7 @@ func (c *Check) getBrokerCN(reverseURL *url.URL) (string, error) { } if cn == "" { - return "", errors.Errorf("unable to match reverse URL host (%s) to broker", host) + return "", fmt.Errorf("%s: %w", host, errBrokerMatchRevURLHost) } return cn, nil @@ -104,7 +109,7 @@ func (c *Check) fetchBrokerCA() ([]byte, error) { if file != "" { cert, err := ioutil.ReadFile(file) if err != nil { - return nil, errors.Wrapf(err, "reading specified broker-ca-file (%s)", file) + return nil, fmt.Errorf("read file: %w", err) } return cert, nil } @@ -112,7 +117,7 @@ func (c *Check) fetchBrokerCA() ([]byte, error) { // otherwise, try the api data, err := c.client.Get("/pki/ca.crt") if err != nil { - return nil, errors.Wrap(err, "fetching Broker CA certificate") + return nil, fmt.Errorf("fetching Broker CA certificate: %w", err) } type cacert struct { @@ -122,11 +127,11 @@ func (c *Check) fetchBrokerCA() ([]byte, error) { var cadata cacert if err := json.Unmarshal(data, &cadata); err != nil { - return nil, errors.Wrap(err, "parsing Broker CA certificate") + return nil, fmt.Errorf("json parse - Broker CA certificate: %w", err) } if cadata.Contents == "" { - return nil, errors.Errorf("no Broker CA certificate in response (%#v)", string(data)) + return nil, fmt.Errorf("no Broker CA certificate in response (%#v)", string(data)) //nolint:goerr113 } return []byte(cadata.Contents), nil diff --git a/internal/check/broker_test.go b/internal/check/broker_test.go index 459cbc53..bfbca2fe 100644 --- a/internal/check/broker_test.go +++ b/internal/check/broker_test.go @@ -6,6 +6,7 @@ package check import ( + "errors" "net/url" "testing" @@ -36,7 +37,7 @@ func TestBrokerTLSConfig(t *testing.T) { if err == nil { t.Fatal("expected error") } - if err.Error() != "broker not initialized" { + if !errors.Is(err, errBrokerNotInitialized) { t.Fatalf("unexpected error (%s)", err) } } @@ -55,7 +56,7 @@ func TestBrokerTLSConfig(t *testing.T) { if err == nil { t.Fatal("expected error") } - if err.Error() != "unable to match reverse URL host (1.2.3.4) to broker" { + if !errors.Is(err, errBrokerMatchRevURLHost) { t.Fatalf("unexpected error (%s)", err) } } @@ -70,7 +71,7 @@ func TestBrokerTLSConfig(t *testing.T) { if err == nil { t.Fatal("expected error") } - if err.Error() != "reading specified broker-ca-file (testdata/missingca.crt): open testdata/missingca.crt: no such file or directory" { + if err.Error() != "read file: open testdata/missingca.crt: no such file or directory" { t.Fatalf("unexpected error (%s)", err) } } diff --git a/internal/check/bundle/api.go b/internal/check/bundle/api.go index 95ba9e52..edd22ee5 100644 --- a/internal/check/bundle/api.go +++ b/internal/check/bundle/api.go @@ -7,7 +7,7 @@ package bundle import "github.com/circonus-labs/go-apiclient" -// API interface abstraction of circonus api (for mocking) +// API interface abstraction of circonus api (for mocking). type API interface { CreateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) FetchBroker(cid apiclient.CIDType) (*apiclient.Broker, error) diff --git a/internal/check/bundle/api_test.go b/internal/check/bundle/api_test.go index 8dc9a647..4b54ce32 100644 --- a/internal/check/bundle/api_test.go +++ b/internal/check/bundle/api_test.go @@ -2,13 +2,13 @@ package bundle import ( "encoding/json" + "fmt" "io/ioutil" "strings" "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/go-apiclient" "github.com/gojuno/minimock/v3" - "github.com/pkg/errors" ) type pkicacert struct { @@ -62,7 +62,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { m.FetchBrokerMock.Set(func(cid apiclient.CIDType) (*apiclient.Broker, error) { switch *cid { case "/broker/000": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/broker/123": return &apiclient.Broker{ CID: "/broker/123", @@ -92,7 +92,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/broker/1234": return &testBroker, nil default: - return nil, errors.Errorf("bad broker request cid (%s)", *cid) + return nil, fmt.Errorf("bad broker request cid (%s)", *cid) //nolint:goerr113 } }) @@ -109,7 +109,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { m.FetchCheckBundleMock.Set(func(cid apiclient.CIDType) (*apiclient.CheckBundle, error) { switch *cid { case "/check_bundle/000": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/check_bundle/0002": x := testCheckBundle x.CID = *cid @@ -117,7 +117,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/check_bundle/1234": return &testCheckBundle, nil default: - return nil, errors.Errorf("bad request cid (%s)", *cid) + return nil, fmt.Errorf("bad request cid (%s)", *cid) //nolint:goerr113 } }) @@ -134,7 +134,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { } return ret, nil case "/check_bundle_metrics/000?query_broker=1": - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 case "/check_bundle_metrics/0001?query_broker=1": return []byte("{"), nil case "/check_bundle_metrics/1234?query_broker=1": @@ -150,13 +150,13 @@ func genMockClient(mc *minimock.Controller) *APIMock { } return data, nil default: - return nil, errors.Errorf("bad apiclient.Get(%s), no handler for url", url) + return nil, fmt.Errorf("bad apiclient.Get(%s), no handler for url", url) //nolint:goerr113 } }) m.SearchCheckBundlesMock.Set(func(searchCriteria *apiclient.SearchQueryType, filterCriteria *apiclient.SearchFilterType) (*[]apiclient.CheckBundle, error) { if strings.Contains(string(*searchCriteria), `target:"000"`) { - return nil, errors.New("forced mock api call error") + return nil, fmt.Errorf("forced mock api call error") //nolint:goerr113 } if strings.Contains(string(*searchCriteria), `target:"not_found"`) { return &[]apiclient.CheckBundle{}, nil @@ -173,7 +173,7 @@ func genMockClient(mc *minimock.Controller) *APIMock { if strings.Contains(string(*searchCriteria), `target:"valid"`) { return &[]apiclient.CheckBundle{testCheckBundle}, nil } - return nil, errors.Errorf("don't know what to do with search criteria (%s)", string(*searchCriteria)) + return nil, fmt.Errorf("don't know what to do with search criteria (%s)", string(*searchCriteria)) //nolint:goerr113 }) m.UpdateCheckBundleMock.Set(func(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) { @@ -181,9 +181,9 @@ func genMockClient(mc *minimock.Controller) *APIMock { case "/check_bundle/1234": return cfg, nil case "/check_bundle/0002": - return nil, errors.New("api update check bundle error") + return nil, fmt.Errorf("api update check bundle error") //nolint:goerr113 default: - return nil, errors.Errorf("add handler for %s", cfg.CID) + return nil, fmt.Errorf("add handler for %s", cfg.CID) //nolint:goerr113 } }) diff --git a/internal/check/bundle/broker.go b/internal/check/bundle/broker.go index a2bc0a0a..96aaf8d2 100644 --- a/internal/check/bundle/broker.go +++ b/internal/check/bundle/broker.go @@ -6,6 +6,7 @@ package bundle import ( + "fmt" "math/rand" "net" "reflect" @@ -15,7 +16,6 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/go-apiclient" - "github.com/pkg/errors" "github.com/spf13/viper" ) @@ -23,15 +23,15 @@ import ( // was not specified. func (cb *Bundle) selectBroker(checkType string, brokerList *[]apiclient.Broker) (*apiclient.Broker, error) { if checkType == "" { - return nil, errors.New("invalid check type (empty)") + return nil, errInvalidCheckType } if brokerList == nil { - return nil, errors.New("invalid broker list (nil)") + return nil, errInvalidBrokerList } if len(*brokerList) == 0 { - return nil, errors.New("invalid broker list (empty)") + return nil, errInvalidBrokerListEmpty } validBrokers := make(map[string]apiclient.Broker) @@ -67,7 +67,7 @@ func (cb *Bundle) selectBroker(checkType string, brokerList *[]apiclient.Broker) } if !haveEnterprise && viper.GetBool(config.KeyMultiAgent) { - return nil, errors.New("no enterprise brokers satisfy multi-agent requirements") + return nil, errIvalidEnterpriseForMultiAgent } if haveEnterprise { // eliminate non-enterprise brokers from valid brokers @@ -79,7 +79,7 @@ func (cb *Bundle) selectBroker(checkType string, brokerList *[]apiclient.Broker) } if len(validBrokers) == 0 { - return nil, errors.Errorf("found %d broker(s), zero are valid", len(*brokerList)) + return nil, fmt.Errorf("%d broker(s): %w", len(*brokerList), errNoValidBrokersFound) } var selectedBroker apiclient.Broker @@ -95,7 +95,7 @@ func (cb *Bundle) selectBroker(checkType string, brokerList *[]apiclient.Broker) return &selectedBroker, nil } -// Is the broker valid (active, supports check type, and reachable) +// Is the broker valid (active, supports check type, and reachable). func (cb *Bundle) isValidBroker(broker *apiclient.Broker, checkType string) (time.Duration, bool) { if broker == nil { return 0, false @@ -209,7 +209,7 @@ func (cb *Bundle) isValidBroker(broker *apiclient.Broker, checkType string) (tim return connDuration, valid } -// brokerSupportsCheckType verifies a broker supports the check type to be used +// brokerSupportsCheckType verifies a broker supports the check type to be used. func brokerSupportsCheckType(checkType string, details *apiclient.BrokerDetail) bool { if checkType == "" { return false @@ -218,7 +218,7 @@ func brokerSupportsCheckType(checkType string, details *apiclient.BrokerDetail) return false } - baseType := string(checkType) + baseType := checkType if idx := strings.Index(baseType, ":"); idx > 0 { baseType = baseType[0:idx] diff --git a/internal/check/bundle/bundle.go b/internal/check/bundle/bundle.go index 38a0dfe8..80b4fcb3 100644 --- a/internal/check/bundle/bundle.go +++ b/internal/check/bundle/bundle.go @@ -20,13 +20,12 @@ import ( "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/go-apiclient" apiconf "github.com/circonus-labs/go-apiclient/config" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) -// Bundle exposes the check bundle management interface +// Bundle exposes the check bundle management interface. type Bundle struct { statusActiveBroker string bundle *apiclient.CheckBundle @@ -37,7 +36,31 @@ type Bundle struct { sync.Mutex } -var ErrUninitialized = errors.New("uninitialized check bundle") +var ( + // broker errors. + + errInvalidCheckType = fmt.Errorf("invalid check type (empty)") + errInvalidBrokerList = fmt.Errorf("invalid broker list (nil)") + errInvalidBrokerListEmpty = fmt.Errorf("invalid broker list (empty)") + errIvalidEnterpriseForMultiAgent = fmt.Errorf("no enterprise brokers satisfy multi-agent requirements") + errNoValidBrokersFound = fmt.Errorf("no valid brokers found") + + // bundle errors. + + ErrUninitialized = fmt.Errorf("uninitialized check bundle") + errInvalidCheckBundle = fmt.Errorf("invalid check bundle (nil)") + errInvalidReverseRules = fmt.Errorf("invalid check bundle (0 reverse urls)") + errNoChecksInBundle = fmt.Errorf("no checks found in check bundle") + errInvalidCheckIndex = fmt.Errorf("invalid check index") + errInvalidCheckBundleState = fmt.Errorf("invalid Check object state, bundle is nil") + errInvalidCID = fmt.Errorf("invalid CID") + errInvalidTarget = fmt.Errorf("invalid check bundle target (empty)") + errNoBundlesMatched = fmt.Errorf("no check bundles matched") + + // other errors. + + errInvalidClient = fmt.Errorf("invalid client (nil)") +) type ErrNotActive struct { Err string @@ -70,7 +93,7 @@ const ( func New(client API) (*Bundle, error) { if client == nil { - return nil, errors.New("invalid client (nil)") + return nil, errInvalidClient } cb := Bundle{ @@ -98,7 +121,7 @@ func New(client API) (*Bundle, error) { // initialize the check bundle if err := cb.initCheckBundle(cid, isCreate); err != nil { - return nil, errors.Wrap(err, "initializing check bundle") + return nil, fmt.Errorf("initializing check bundle: %w", err) } // ensure a) the global check bundle id is set and b) it is set correctly @@ -111,7 +134,7 @@ func New(client API) (*Bundle, error) { return &cb, nil } -// CID returns the check bundle cid +// CID returns the check bundle cid. func (cb *Bundle) CID() (string, error) { cb.Lock() defer cb.Unlock() @@ -123,7 +146,7 @@ func (cb *Bundle) CID() (string, error) { return "", ErrUninitialized } -// Period returns check bundle period (intetrval between when broker should make requests) +// Period returns check bundle period (intetrval between when broker should make requests). func (cb *Bundle) Period() (uint, error) { cb.Lock() defer cb.Unlock() @@ -135,13 +158,13 @@ func (cb *Bundle) Period() (uint, error) { return 0, ErrUninitialized } -// SubmissionURL returns the submission url (derived from mtev_reverse) +// SubmissionURL returns the submission url (derived from mtev_reverse). func (cb *Bundle) SubmissionURL() (string, error) { if cb.bundle == nil { - return "", errors.New("invalid check bundle (nil)") + return "", errInvalidCheckBundle } if len(cb.bundle.ReverseConnectURLs) == 0 { - return "", errors.New("invalid check bundle (0 reverse urls)") + return "", errInvalidReverseRules } // submission url from mtev_reverse url, given: @@ -158,7 +181,7 @@ func (cb *Bundle) SubmissionURL() (string, error) { return submissionURL, nil } -// Refresh re-loads the check bundle using the API (sets metric states if check bundle is managed) +// Refresh re-loads the check bundle using the API (sets metric states if check bundle is managed). func (cb *Bundle) Refresh() error { cb.Lock() defer cb.Unlock() @@ -171,7 +194,7 @@ func (cb *Bundle) Refresh() error { b, err := cb.fetchCheckBundle(viper.GetString(config.KeyCheckBundleID)) if err != nil { - return errors.Wrap(err, "refresh check, fetching check") + return fmt.Errorf("refresh check, fetching check: %w", err) } cb.bundle = b @@ -179,7 +202,8 @@ func (cb *Bundle) Refresh() error { return nil } -// CheckCID returns the check cid at the passed index within the check bundle's checks array or an error if bundle not initialized +// CheckCID returns the check cid at the passed index within the check bundle's +// checks array or an error if bundle not initialized. func (cb *Bundle) CheckCID(idx uint) (string, error) { cb.Lock() defer cb.Unlock() @@ -188,10 +212,10 @@ func (cb *Bundle) CheckCID(idx uint) (string, error) { return "", ErrUninitialized } if len(cb.bundle.Checks) == 0 { - return "", errors.New("no checks found in check bundle") + return "", errNoChecksInBundle } if int(idx) > len(cb.bundle.Checks) { - return "", errors.Errorf("invalid check index (%d>%d)", idx, len(cb.bundle.Checks)) + return "", fmt.Errorf("index(%d) checks(%d): %w", idx, len(cb.bundle.Checks), errInvalidCheckIndex) } return cb.bundle.Checks[idx], nil @@ -202,7 +226,7 @@ func (cb *Bundle) CheckCID(idx uint) (string, error) { // 2. search for a check matching the current system // 3. create a check for the system if --check-create specified // if fetched, found, or created - set Check.bundle -// otherwise, return an error +// otherwise, return an error. func (cb *Bundle) initCheckBundle(cid string, create bool) error { var bundle *apiclient.CheckBundle @@ -210,7 +234,7 @@ func (cb *Bundle) initCheckBundle(cid string, create bool) error { if cid != "" { b, err := cb.fetchCheckBundle(cid) if err != nil { - return errors.Wrapf(err, "fetching check for cid %s", cid) + return fmt.Errorf("fetching check for cid %s: %w", cid, err) } bundle = b } else { @@ -218,20 +242,20 @@ func (cb *Bundle) initCheckBundle(cid string, create bool) error { b, found, err := cb.findCheckBundle() if err != nil { if !create || found != 0 { - return errors.Wrap(err, "unable to find a check for this system") + return fmt.Errorf("unable to find a check for this system: %w", err) } cb.logger.Info().Msg("no existing check found, creating") // attempt to create if not found and create flag ON b, err = cb.createCheckBundle() if err != nil { - return errors.Wrap(err, "creating new check for this system") + return fmt.Errorf("creating new check for this system: %w", err) } } bundle = b } if bundle == nil { - return errors.New("invalid Check object state, bundle is nil") + return errInvalidCheckBundleState } if bundle.Status != StatusActive { @@ -248,21 +272,21 @@ func (cb *Bundle) initCheckBundle(cid string, create bool) error { cb.logger.Info().Str("cid", bundle.CID).Msg("updating check bundle") b, err := cb.updateCheckBundle(bundle) if err != nil { - return errors.Wrap(err, "updating check bundle") + return fmt.Errorf("updating check bundle: %w", err) } bundle = b case viper.GetBool(config.KeyCheckUpdateMetricFilters): cb.logger.Info().Str("cid", bundle.CID).Msg("updating check bundle metric filters and host tags") b, err := cb.updateCheckBundleMetricFilters(bundle) if err != nil { - return errors.Wrap(err, "updating check bundle metric filters") + return fmt.Errorf("updating check bundle metric filters: %w", err) } bundle = b default: cb.logger.Info().Str("cid", bundle.CID).Msg("updating check bundle host tags") b, err := cb.updateCheckBundleTags(bundle) if err != nil { - return errors.Wrap(err, "updating check bundle tags") + return fmt.Errorf("updating check bundle tags: %w", err) } bundle = b } @@ -275,7 +299,7 @@ func (cb *Bundle) initCheckBundle(cid string, create bool) error { func (cb *Bundle) fetchCheckBundle(cid string) (*apiclient.CheckBundle, error) { if cid == "" { - return nil, errors.New("invalid cid (empty)") + return nil, fmt.Errorf("empty: %w", errInvalidCID) } if ok, _ := regexp.MatchString(`^[0-9]+$`, cid); ok { @@ -283,12 +307,12 @@ func (cb *Bundle) fetchCheckBundle(cid string) (*apiclient.CheckBundle, error) { } if ok, _ := regexp.MatchString(`^/check_bundle/[0-9]+$`, cid); !ok { - return nil, errors.Errorf("invalid cid (%s)", cid) + return nil, fmt.Errorf("cid %s: %w", cid, errInvalidCID) } bundle, err := cb.client.FetchCheckBundle(apiclient.CIDType(&cid)) if err != nil { - return nil, errors.Wrapf(err, "unable to retrieve check bundle (%s)", cid) + return nil, fmt.Errorf("unable to retrieve check bundle (%s): %w", cid, err) } if bundle.Status != StatusActive { @@ -306,19 +330,19 @@ func (cb *Bundle) fetchCheckBundle(cid string) (*apiclient.CheckBundle, error) { func (cb *Bundle) findCheckBundle() (*apiclient.CheckBundle, int, error) { target := viper.GetString(config.KeyCheckTarget) if target == "" { - return nil, -1, errors.New("invalid check bundle target (empty)") + return nil, -1, errInvalidTarget } criteria := apiclient.SearchQueryType(fmt.Sprintf(`(active:1)(type:"`+defaults.CheckType+`")(target:"%s")`, target)) bundles, err := cb.client.SearchCheckBundles(&criteria, nil) if err != nil { - return nil, -1, errors.Wrap(err, "searching for check bundle") + return nil, -1, fmt.Errorf("searching for check bundle: %w", err) } found := len(*bundles) if found == 0 { - return nil, found, errors.Errorf("no check bundles matched criteria (%s)", string(criteria)) + return nil, found, fmt.Errorf("criteria - %s: %w", string(criteria), errNoBundlesMatched) } if found > 1 { @@ -338,7 +362,7 @@ func (cb *Bundle) findCheckBundle() (*apiclient.CheckBundle, int, error) { Int("matched", matched). Str("criteria", string(criteria)). Msgf("multiple check bundles found, none created by (%s)", release.NAME) - return nil, matched, errors.Errorf("multiple check bundles (%d) found matching criteria (%s), none created by (%s)", found, string(criteria), release.NAME) + return nil, matched, fmt.Errorf("multiple check bundles (%d) found matching criteria (%s), none created by (%s)", found, string(criteria), release.NAME) //nolint:goerr113 } if matched == 1 { cb.logger.Warn(). @@ -349,7 +373,7 @@ func (cb *Bundle) findCheckBundle() (*apiclient.CheckBundle, int, error) { Msgf("multiple check bundles found, using one created by (%s)", release.NAME) return &(*bundles)[idx], matched, nil } - return nil, found, errors.Errorf("multiple check bundles (%d) found matching criteria (%s) created by (%s)", matched, string(criteria), release.NAME) + return nil, found, fmt.Errorf("multiple check bundles (%d) found matching criteria (%s) created by (%s)", matched, string(criteria), release.NAME) //nolint:goerr113 } // search does not always return a valid mtev_reverse url (e.g. mtev_reverse://:43191/ no host/ip) @@ -359,7 +383,7 @@ func (cb *Bundle) findCheckBundle() (*apiclient.CheckBundle, int, error) { // cb.logger.Debug().Str("cid", cid).Msg("fetching check bundle found by search") b, err := cb.fetchCheckBundle(cid) if err != nil { - return nil, 0, errors.Errorf("unable to retrieve check bundle by id (%s): %s", cid, err) + return nil, 0, fmt.Errorf("unable to retrieve check bundle by id (%s): %w", cid, err) } // cb.logger.Debug().Interface("search", *bundles).Interface("fetch", b).Msg("bundles") @@ -382,14 +406,14 @@ func (cb *Bundle) createCheckBundle() (*apiclient.CheckBundle, error) { ta, err := config.ParseListen(serverList[0]) if err != nil { cb.logger.Error().Err(err).Str("addr", serverList[0]).Msg("resolving address") - return nil, errors.Wrap(err, "parsing listen address") + return nil, fmt.Errorf("parsing listen address: %w", err) } targetAddr = ta.String() } target := viper.GetString(config.KeyCheckTarget) if target == "" { - return nil, errors.New("invalid check bundle target (empty)") + return nil, errInvalidTarget } if targetAddr[0:1] == ":" && !viper.GetBool(config.KeyReverse) { @@ -426,7 +450,7 @@ func (cb *Bundle) createCheckBundle() (*apiclient.CheckBundle, error) { { // get metric filter configuration filters, err := cb.getMetricFilters() if err != nil { - return nil, errors.Wrap(err, "getting metric filters") + return nil, fmt.Errorf("getting metric filters: %w", err) } cfg.MetricFilters = filters } @@ -435,12 +459,12 @@ func (cb *Bundle) createCheckBundle() (*apiclient.CheckBundle, error) { if brokerCID == "" || strings.ToLower(brokerCID) == "select" { brokerList, err := cb.client.FetchBrokers() if err != nil { - return nil, errors.Wrap(err, "select broker") + return nil, fmt.Errorf("select broker: %w", err) } broker, err := cb.selectBroker(defaults.CheckType, brokerList) if err != nil { - return nil, errors.Wrap(err, "selecting broker to create check bundle") + return nil, fmt.Errorf("selecting broker to create check bundle: %w", err) } brokerCID = broker.CID @@ -454,13 +478,13 @@ func (cb *Bundle) createCheckBundle() (*apiclient.CheckBundle, error) { bundle, err := cb.client.CreateCheckBundle(cfg) if err != nil { - return nil, errors.Wrap(err, "creating check bundle") + return nil, fmt.Errorf("creating check bundle: %w", err) } return bundle, nil } -// updateCheckBundle will update all check bundle settings/tags/filters controlled by agent +// updateCheckBundle will update all check bundle settings/tags/filters controlled by agent. func (cb *Bundle) updateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) { // this is an explicit update - all configurable values will be overwritten with their configuration settings @@ -479,14 +503,14 @@ func (cb *Bundle) updateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.Chec ta, err := config.ParseListen(serverList[0]) if err != nil { cb.logger.Error().Err(err).Str("addr", serverList[0]).Msg("resolving address") - return nil, errors.Wrap(err, "parsing listen address") + return nil, fmt.Errorf("parsing listen address: %w", err) } targetAddr = ta.String() } target := viper.GetString(config.KeyCheckTarget) if target == "" { - return nil, errors.New("invalid check bundle target (empty)") + return nil, errInvalidTarget } if targetAddr[0:1] == ":" && !viper.GetBool(config.KeyReverse) { @@ -521,7 +545,7 @@ func (cb *Bundle) updateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.Chec { // get metric filter configuration filters, err := cb.getMetricFilters() if err != nil { - return nil, errors.Wrap(err, "getting metric filters") + return nil, fmt.Errorf("getting metric filters: %w", err) } cfg.MetricFilters = filters } @@ -536,7 +560,7 @@ func (cb *Bundle) updateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.Chec bundle, err := cb.client.UpdateCheckBundle(cfg) if err != nil { - return nil, errors.Wrap(err, "updating check bundle") + return nil, fmt.Errorf("updating check bundle: %w", err) } return bundle, nil @@ -552,12 +576,12 @@ func (cb *Bundle) getMetricFilters() ([][]string, error) { data, err := ioutil.ReadFile(mff) if err != nil { if !os.IsNotExist(err) { - return nil, errors.Wrapf(err, "reading %s", mff) + return nil, fmt.Errorf("reading %s: %w", mff, err) } } else { var filters MetricFilterFile if err := json.Unmarshal(data, &filters); err != nil { - return nil, errors.Wrap(err, "parsing metric filters") + return nil, fmt.Errorf("json parse - metric filters file: %w", err) } cb.logger.Debug().Interface("filters", filters).Str("file", mff).Msg("using metric filter file") return filters.Filters, nil @@ -567,7 +591,7 @@ func (cb *Bundle) getMetricFilters() ([][]string, error) { if viper.GetString(config.KeyCheckMetricFilters) != "" { var filters [][]string if err := json.Unmarshal([]byte(viper.GetString(config.KeyCheckMetricFilters)), &filters); err != nil { - return nil, errors.Wrap(err, "parsing check bundle metric filters") + return nil, fmt.Errorf("json parse - metric filters cfg: %w", err) } cb.logger.Debug().Interface("filters", filters).Msg("using metric filters option") return filters, nil @@ -577,27 +601,27 @@ func (cb *Bundle) getMetricFilters() ([][]string, error) { return defaults.CheckMetricFilters, nil } -// updateCheckBundleMetricFilters only (forced); then merge/update tags +// updateCheckBundleMetricFilters only (forced); then merge/update tags. func (cb *Bundle) updateCheckBundleMetricFilters(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) { // this is an explicit, forced update and bundle metric filters will be overwritten with configured filters filters, err := cb.getMetricFilters() if err != nil { - return nil, errors.Wrap(err, "getting metric filters") + return nil, fmt.Errorf("getting metric filters: %w", err) } cfg.MetricFilters = filters cb.logger.Info().Interface("filters", filters).Msg("updating check bundle metric filters") bundle, err := cb.client.UpdateCheckBundle(cfg) if err != nil { - return nil, errors.Wrap(err, "updating metric filters") + return nil, fmt.Errorf("updating metric filters: %w", err) } return cb.updateCheckBundleTags(bundle) } -// updateCheckBundleTags only, merge w/user-added; update any host tags where value has changed +// updateCheckBundleTags only, merge w/user-added; update any host tags where value has changed. func (cb *Bundle) updateCheckBundleTags(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) { // this is a passive update, so tags are merged with user tags and any host tags are updated to new values if they've changed @@ -648,7 +672,7 @@ func (cb *Bundle) updateCheckBundleTags(cfg *apiclient.CheckBundle) (*apiclient. if updateCheck { bundle, err := cb.client.UpdateCheckBundle(cfg) if err != nil { - return nil, errors.Wrap(err, "updating check bundle") + return nil, fmt.Errorf("updating check bundle: %w", err) } return bundle, nil } diff --git a/internal/check/bundle/bundle_test.go b/internal/check/bundle/bundle_test.go index c3f60c6b..610496e5 100644 --- a/internal/check/bundle/bundle_test.go +++ b/internal/check/bundle/bundle_test.go @@ -6,6 +6,7 @@ package bundle import ( + "errors" "reflect" "testing" @@ -71,7 +72,7 @@ func TestFetchCheck(t *testing.T) { t.Fatal("expected error") } - if err.Error() != "invalid cid (empty)" { + if !errors.Is(err, errInvalidCID) { t.Fatalf("unexpected error return (%s)", err) } } @@ -86,7 +87,7 @@ func TestFetchCheck(t *testing.T) { t.Fatal("expected error") } - if err.Error() != "invalid cid (abc)" { + if !errors.Is(err, errInvalidCID) { t.Fatalf("unexpected error return (%s)", err) } } @@ -182,7 +183,7 @@ func TestFindCheck(t *testing.T) { t.Fatal("expected found == 0") } - if err.Error() != `no check bundles matched criteria ((active:1)(type:"`+defaults.CheckType+`")(target:"not_found"))` { + if err.Error() != `criteria - (active:1)(type:"`+defaults.CheckType+`")(target:"not_found"): no check bundles matched` { t.Fatalf("unexpected error return (%s)", err) } } diff --git a/internal/check/check.go b/internal/check/check.go index 079959ba..0206330f 100644 --- a/internal/check/check.go +++ b/internal/check/check.go @@ -9,6 +9,7 @@ package check import ( "crypto/tls" "crypto/x509" + "fmt" "io/ioutil" "net" "net/url" @@ -18,13 +19,12 @@ import ( "github.com/circonus-labs/circonus-agent/internal/check/bundle" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/go-apiclient" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) -// Check exposes the check bundle management interface +// Check exposes the check bundle management interface. type Check struct { checkConfig *apiclient.Check checkBundle *bundle.Bundle @@ -40,14 +40,14 @@ type Check struct { sync.Mutex } -// Meta contains check id meta data +// Meta contains check id meta data. type Meta struct { BundleID string CheckUUID string CheckID string } -// ReverseConfig contains the reverse configuration for the check +// ReverseConfig contains the reverse configuration for the check. type ReverseConfig struct { BrokerAddr *net.TCPAddr ReverseURL *url.URL @@ -63,6 +63,10 @@ const ( PrimaryCheckIndex = 0 ) +var ( + errCheckNotInitialized = fmt.Errorf("check not initialized") +) + type ErrNoOwnerFound struct { Err string CheckID string @@ -119,7 +123,7 @@ func (e *ErrInvalidOwner) Error() string { return s } -// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue) +// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue). type logshim struct { logh zerolog.Logger } @@ -128,7 +132,7 @@ func (l logshim) Printf(fmt string, v ...interface{}) { l.logh.Printf(fmt, v...) } -// New returns a new check instance +// New returns a new check instance. func New(apiClient API) (*Check, error) { // NOTE: TBD, make broker max retries and response time configurable c := Check{ @@ -171,7 +175,7 @@ func New(apiClient API) (*Check, error) { } client, err := apiclient.New(cfg) if err != nil { - return nil, errors.Wrap(err, "creating circonus api client") + return nil, fmt.Errorf("creating circonus api client: %w", err) } apiClient = client } @@ -180,7 +184,7 @@ func New(apiClient API) (*Check, error) { b, err := bundle.New(c.client) if err != nil { - return nil, err + return nil, fmt.Errorf("new bundle: %w", err) } c.checkBundle = b @@ -196,7 +200,7 @@ func New(apiClient API) (*Check, error) { if isReverse { err := c.setReverseConfigs() if err != nil { - return nil, errors.Wrap(err, "setting up reverse configuration") + return nil, fmt.Errorf("setting up reverse configuration: %w", err) } c.reverse = true } @@ -204,13 +208,13 @@ func New(apiClient API) (*Check, error) { return &c, nil } -// CheckMeta returns check id, check bundle id, and check uuid +// CheckMeta returns check id, check bundle id, and check uuid. func (c *Check) CheckMeta() (*Meta, error) { c.Lock() defer c.Unlock() if c.checkConfig == nil { - return nil, errors.New("check uninitialized") + return nil, errCheckNotInitialized } return &Meta{ @@ -220,38 +224,43 @@ func (c *Check) CheckMeta() (*Meta, error) { }, nil } -// SubmissionURL returns the URL to submit metrics to as well as the tls config for https +// SubmissionURL returns the URL to submit metrics to as well as the tls config for https. func (c *Check) SubmissionURL() (string, *tls.Config, error) { surl, err := c.checkBundle.SubmissionURL() if err != nil { - return "", nil, err + return "", nil, fmt.Errorf("submission url: %w", err) } u, err := url.Parse(surl) if err != nil { - return "", nil, errors.Wrap(err, "parsing submission url") + return "", nil, fmt.Errorf("parsing submission url: %w", err) } tlsConfig, _, err := c.brokerTLSConfig(u) if err != nil { - return "", nil, errors.Wrapf(err, "creating TLS config for (%s - %s)", c.broker.CID, surl) + return "", nil, fmt.Errorf("creating TLS config for (%s - %s): %w", c.broker.CID, surl, err) } return surl, tlsConfig, nil } -// CheckPeriod returns check bundle period (intetrval between when broker should make request) +// CheckPeriod returns check bundle period (intetrval between when broker should make request). func (c *Check) CheckPeriod() (uint, error) { c.Lock() defer c.Unlock() if c.checkBundle == nil { - return 0, errors.New("check bundle uninitialized") + return 0, errCheckNotInitialized } - return c.checkBundle.Period() + period, err := c.checkBundle.Period() + if err != nil { + return 0, fmt.Errorf("check period: %w", err) + } + + return period, nil } -// RefreshReverseConfig refreshes the check, broker and broker tls configurations +// RefreshReverseConfig refreshes the check, broker and broker tls configurations. func (c *Check) RefreshReverseConfig() error { if err := c.FetchCheckConfig(); err != nil { return err @@ -265,39 +274,39 @@ func (c *Check) RefreshReverseConfig() error { return nil } -// GetReverseConfigs returns the reverse connection configuration(s) to use for the check +// GetReverseConfigs returns the reverse connection configuration(s) to use for the check. func (c *Check) GetReverseConfigs() (*ReverseConfigs, error) { c.Lock() defer c.Unlock() if !c.reverse { - return nil, errors.New("agent not in reverse mode") + return nil, fmt.Errorf("agent not in reverse mode") //nolint:goerr113 } if c.revConfigs == nil { - return nil, errors.New("invalid reverse config (nil)") + return nil, fmt.Errorf("invalid reverse config (nil)") //nolint:goerr113 } return c.revConfigs, nil } -// FetchCheckConfig re-loads the check using the API +// FetchCheckConfig re-loads the check using the API. func (c *Check) FetchCheckConfig() error { c.Lock() defer c.Unlock() if c.checkBundle == nil { - return errors.New("check bundle uninitialized") + return errCheckNotInitialized } checkCID, err := c.checkBundle.CheckCID(PrimaryCheckIndex) if err != nil { - return err + return fmt.Errorf("check cid: %w", err) } check, err := c.client.FetchCheck(apiclient.CIDType(&checkCID)) if err != nil { - return errors.Wrapf(err, "unable to fetch check (%s)", checkCID) + return fmt.Errorf("unable to fetch check (%s): %w", checkCID, err) } if !check.Active { @@ -314,18 +323,18 @@ func (c *Check) FetchCheckConfig() error { return nil } -// FetchBrokerConfig re-loads the broker using the API +// FetchBrokerConfig re-loads the broker using the API. func (c *Check) FetchBrokerConfig() error { c.Lock() defer c.Unlock() if c.checkConfig == nil { - return errors.New("check uninitialized") + return errCheckNotInitialized } broker, err := c.client.FetchBroker(apiclient.CIDType(&c.checkConfig.BrokerCID)) if err != nil { - return errors.Wrapf(err, "unable to fetch broker (%s)", c.checkConfig.BrokerCID) + return fmt.Errorf("unable to fetch broker (%s): %w", c.checkConfig.BrokerCID, err) } c.broker = broker diff --git a/internal/check/reverse.go b/internal/check/reverse.go index c0c355f3..f337fe47 100644 --- a/internal/check/reverse.go +++ b/internal/check/reverse.go @@ -7,26 +7,25 @@ package check import ( "context" + "fmt" "net" "net/http" "net/url" "strings" "time" - - "github.com/pkg/errors" ) func (c *Check) setReverseConfigs() error { c.revConfigs = nil if c.broker == nil { - return errors.New("broker is uninitialized") + return errBrokerNotInitialized } if c.checkConfig == nil { - return errors.New("check is uninitialized") + return errCheckNotInitialized } if len(c.checkConfig.ReverseURLs) == 0 { - return errors.New("no reverse URLs found in check") + return fmt.Errorf("no reverse URLs found in check") //nolint:goerr113 } cfgs := make(ReverseConfigs) @@ -37,17 +36,17 @@ func (c *Check) setReverseConfigs() error { // Using raw tls connections, the url protocol is not germane. reverseURL, err := url.Parse(strings.ReplaceAll(rURL, "mtev_reverse", "https")) if err != nil { - return errors.Wrapf(err, "parsing check reverse URL (%s)", rURL) + return fmt.Errorf("parsing check reverse URL (%s): %w", rURL, err) } brokerAddr, err := net.ResolveTCPAddr("tcp", reverseURL.Host) if err != nil { - return errors.Wrapf(err, "invalid reverse service address (%s)", rURL) + return fmt.Errorf("invalid reverse service address (%s): %w", rURL, err) } tlsConfig, cn, err := c.brokerTLSConfig(reverseURL) if err != nil { - return errors.Wrapf(err, "creating TLS config for (%s - %s)", c.broker.CID, rURL) + return fmt.Errorf("creating TLS config for (%s - %s): %w", c.broker.CID, rURL, err) } cfgs[cn] = ReverseConfig{ @@ -115,7 +114,7 @@ func (c *Check) FindPrimaryBrokerInstance(ctx context.Context, cfgs *ReverseConf req, err := http.NewRequestWithContext(ctx, "GET", ownerReqURL, nil) if err != nil { c.logger.Warn().Err(err).Str("url", ownerReqURL).Msg("creating check owner request") - return "", err + return "", fmt.Errorf("new request: %w", err) } req.Header.Add("Accept", "application/json") @@ -127,7 +126,7 @@ func (c *Check) FindPrimaryBrokerInstance(ctx context.Context, cfgs *ReverseConf continue } } - return "", err + return "", fmt.Errorf("do request: %w", err) } resp.Body.Close() // we only care about headers diff --git a/internal/check/reverse_test.go b/internal/check/reverse_test.go index f8dd729e..b29b839e 100644 --- a/internal/check/reverse_test.go +++ b/internal/check/reverse_test.go @@ -34,7 +34,7 @@ func TestCheck_setReverseConfigs(t *testing.T) { fields fields wantErr bool }{ - // TODO: Add test cases. + // Add test cases. } for _, tt := range tests { tt := tt @@ -83,7 +83,7 @@ func TestCheck_FindPrimaryBrokerInstance(t *testing.T) { fields fields wantErr bool }{ - // TODO: Add test cases. + // Add test cases. } for _, tt := range tests { tt := tt diff --git a/internal/config/address.go b/internal/config/address.go index 4e04e140..d048b392 100644 --- a/internal/config/address.go +++ b/internal/config/address.go @@ -5,17 +5,17 @@ package config -// ParseListen parses and fixes listen spec +// ParseListen parses and fixes listen spec. import ( + "fmt" "net" "regexp" "strings" "github.com/circonus-labs/circonus-agent/internal/config/defaults" - "github.com/pkg/errors" ) -// ParseListen verifies and parses a listen address spec +// ParseListen verifies and parses a listen address spec. func ParseListen(spec string) (*net.TCPAddr, error) { // empty, default if spec == "" { @@ -36,12 +36,12 @@ func ParseListen(spec string) (*net.TCPAddr, error) { host, port, err := net.SplitHostPort(spec) if err != nil { - return nil, errors.Wrap(err, "parsing listen") + return nil, fmt.Errorf("parsing listen: %w", err) } addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(host, port)) if err != nil { - return nil, errors.Wrap(err, "resolving listen") + return nil, fmt.Errorf("resolving listen: %w", err) } return addr, nil diff --git a/internal/config/api.go b/internal/config/api.go index 3ab9b704..6ec18fff 100644 --- a/internal/config/api.go +++ b/internal/config/api.go @@ -6,15 +6,21 @@ package config import ( + "fmt" "net/url" "strings" "github.com/circonus-labs/circonus-agent/internal/config/defaults" - "github.com/pkg/errors" "github.com/spf13/viper" ) -// apiRequired checks to see if any options are set which would *require* accessing the API +var ( + errAPIKeyRequired = fmt.Errorf("API key is required") + errAPIAppRequired = fmt.Errorf("API app is required") + errAPIURLRequired = fmt.Errorf("API URL is required") +) + +// apiRequired checks to see if any options are set which would *require* accessing the API. func apiRequired() bool { // reverse connections require API access if viper.GetBool(KeyReverse) { @@ -50,24 +56,24 @@ func validateAPIOptions() error { // API is required for reverse and/or statsd if apiKey == "" { - return errors.New("API key is required") + return errAPIKeyRequired } if apiApp == "" { - return errors.New("API app is required") + return errAPIAppRequired } if apiURL == "" { - return errors.New("API URL is required") + return errAPIURLRequired } if apiURL != defaults.APIURL { parsedURL, err := url.Parse(apiURL) if err != nil { - return errors.Wrap(err, "Invalid API URL") + return fmt.Errorf("invalid API URL: %w", err) } if parsedURL.Scheme == "" || parsedURL.Host == "" || parsedURL.Path == "" { - return errors.Errorf("Invalid API URL (%s)", apiURL) + return fmt.Errorf("invalid API URL (%s)", apiURL) //nolint:goerr113 } } diff --git a/internal/config/api_test.go b/internal/config/api_test.go index ddd8f0ff..cfa2bae9 100644 --- a/internal/config/api_test.go +++ b/internal/config/api_test.go @@ -6,7 +6,7 @@ package config import ( - "errors" + "fmt" "strings" "testing" @@ -48,7 +48,7 @@ func TestValidateAPIOptions(t *testing.T) { t.Log("No key/app/url") { - expectedError := errors.New("API key is required") + expectedError := fmt.Errorf("API key is required") //nolint:goerr113 err := validateAPIOptions() if err == nil { t.Fatal("Expected error") @@ -74,7 +74,7 @@ func TestValidateAPIOptions(t *testing.T) { t.Log("No app") { viper.Set(KeyAPITokenKey, "foo") - expectedError := errors.New("API app is required") + expectedError := fmt.Errorf("API app is required") //nolint:goerr113 err := validateAPIOptions() if err == nil { t.Fatal("Expected error") @@ -88,7 +88,7 @@ func TestValidateAPIOptions(t *testing.T) { { viper.Set(KeyAPITokenKey, "foo") viper.Set(KeyAPITokenApp, "foo") - expectedError := errors.New("API URL is required") + expectedError := fmt.Errorf("API URL is required") //nolint:goerr113 err := validateAPIOptions() if err == nil { t.Fatal("Expected error") @@ -103,7 +103,7 @@ func TestValidateAPIOptions(t *testing.T) { viper.Set(KeyAPITokenKey, "foo") viper.Set(KeyAPITokenApp, "foo") viper.Set(KeyAPIURL, "foo") - expectedError := errors.New("Invalid API URL (foo)") + expectedError := fmt.Errorf("invalid API URL (foo)") //nolint:goerr113 err := validateAPIOptions() if err == nil { t.Fatal("Expected error") @@ -118,7 +118,7 @@ func TestValidateAPIOptions(t *testing.T) { viper.Set(KeyAPITokenKey, "foo") viper.Set(KeyAPITokenApp, "foo") viper.Set(KeyAPIURL, "foo_bar://herp/derp") - expectedError := errors.New(`Invalid API URL: parse "foo_bar://herp/derp": first path segment in URL cannot contain colon`) + expectedError := fmt.Errorf(`invalid API URL: parse "foo_bar://herp/derp": first path segment in URL cannot contain colon`) //nolint:goerr113 err := validateAPIOptions() if err == nil { t.Fatal("Expected error") diff --git a/internal/config/config.go b/internal/config/config.go index c9d070af..a2339ede 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,18 +14,17 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config/defaults" toml "github.com/pelletier/go-toml" - "github.com/pkg/errors" "github.com/spf13/viper" yaml "gopkg.in/yaml.v2" ) -// Log defines the running config.log structure +// Log defines the running config.log structure. type Log struct { Level string `json:"level" yaml:"level" toml:"level"` Pretty bool `json:"pretty" yaml:"pretty" toml:"pretty"` } -// API defines the running config.api structure +// API defines the running config.api structure. type API struct { App string `json:"app" yaml:"app" toml:"app"` CAFile string `mapstructure:"ca_file" json:"ca_file" yaml:"ca_file" toml:"ca_file"` @@ -33,14 +32,14 @@ type API struct { URL string `json:"url" yaml:"url" toml:"url"` } -// ReverseCreateCheckOptions defines the running config.reverse.check structure +// ReverseCreateCheckOptions defines the running config.reverse.check structure. type ReverseCreateCheckOptions struct { Broker string `json:"broker" yaml:"broker" toml:"broker"` Tags string `json:"tags" yaml:"tags" toml:"tags"` Title string `json:"title" yaml:"title" toml:"title"` } -// Check defines the check parameters +// Check defines the check parameters. type Check struct { Broker string `json:"broker" yaml:"broker" toml:"broker"` BundleID string `mapstructure:"bundle_id" json:"bundle_id" yaml:"bundle_id" toml:"bundle_id"` @@ -60,21 +59,21 @@ type Check struct { // EnableNewMetrics bool `json:"-" yaml:"-" toml:"-"` // deprecated, hidden } -// MultiAgent defines the running config.multi_agent structure +// MultiAgent defines the running config.multi_agent structure. type MultiAgent struct { Interval string `json:"interval" toml:"interval" yaml:"interval"` Enabled bool `json:"enabled" toml:"enabled" yaml:"enabled"` Accumulate bool `json:"accumulate" toml:"accumulate" yaml:"accumulate"` } -// Reverse defines the running config.reverse structure +// Reverse defines the running config.reverse structure. type Reverse struct { BrokerCAFile string `mapstructure:"broker_ca_file" json:"broker_ca_file" yaml:"broker_ca_file" toml:"broker_ca_file"` Enabled bool `json:"enabled" yaml:"enabled" toml:"enabled"` MaxConnRetry int `mapstructure:"max_conn_retry" json:"max_conn_retry" yaml:"max_conn_retry" toml:"max_conn_retry"` } -// SSL defines the running config.ssl structure +// SSL defines the running config.ssl structure. type SSL struct { CertFile string `mapstructure:"cert_file" json:"cert_file" yaml:"cert_file" toml:"cert_file"` KeyFile string `mapstructure:"key_file" json:"key_file" yaml:"key_file" toml:"key_file"` @@ -82,13 +81,13 @@ type SSL struct { Verify bool `json:"verify" yaml:"verify" toml:"verify"` } -// StatsDHost defines the running config.statsd.host structure +// StatsDHost defines the running config.statsd.host structure. type StatsDHost struct { Category string `json:"category" yaml:"category" toml:"category"` MetricPrefix string `mapstructure:"metric_prefix" json:"metric_prefix" yaml:"metric_prefix" toml:"metric_prefix"` } -// StatsDGroup defines the running config.statsd.group structure +// StatsDGroup defines the running config.statsd.group structure. type StatsDGroup struct { CheckID string `mapstructure:"check_id" json:"check_id" yaml:"check_id" toml:"check_id"` Counters string `json:"counters" yaml:"counters" toml:"counters"` @@ -97,7 +96,7 @@ type StatsDGroup struct { Sets string `json:"sets" yaml:"sets" toml:"sets"` } -// StatsD defines the running config.statsd structure +// StatsD defines the running config.statsd structure. type StatsD struct { Group StatsDGroup `json:"group" yaml:"group" toml:"group"` Host StatsDHost `json:"host" yaml:"host" toml:"host"` @@ -108,13 +107,13 @@ type StatsD struct { Disabled bool `json:"disabled" yaml:"disabled" toml:"disabled"` } -// Thresholds defines triggers used to include metrics +// Thresholds defines triggers used to include metrics. type Thresholds struct { HighCPU float32 `mapstructure:"high_cpu" json:"high_cpu" toml:"high_cpu" yaml:"high_cpu"` HighMemory float32 `mapstructure:"high_memory" json:"high_memory" toml:"high_memory" yaml:"high_memory"` } -// Config defines the running config structure +// Config defines the running config structure. type Config struct { DebugDumpMetrics string `mapstructure:"debug_dump_metrics" json:"debug_dump_metrics" yaml:"debug_dump_metrics" toml:"debug_dump_metrics"` PluginDir string `mapstructure:"plugin_dir" json:"plugin_dir" yaml:"plugin_dir" toml:"plugin_dir"` @@ -142,28 +141,28 @@ type Config struct { } // -// NOTE: adding a Key* MUST be reflected in the Config structures above +// NOTE: adding a Key* MUST be reflected in the Config structures above. // const ( - // KeyAPICAFile custom ca for circonus api (e.g. inside) + // KeyAPICAFile custom ca for circonus api (e.g. inside). KeyAPICAFile = "api.ca_file" - // KeyAPITokenApp circonus api token key application name + // KeyAPITokenApp circonus api token key application name. KeyAPITokenApp = "api.app" - // KeyAPITokenKey circonus api token key + // KeyAPITokenKey circonus api token key. KeyAPITokenKey = "api.key" - // KeyAPIURL custom circonus api url (e.g. inside) + // KeyAPIURL custom circonus api url (e.g. inside). KeyAPIURL = "api.url" - // KeyDebug enables debug messages + // KeyDebug enables debug messages. KeyDebug = "debug" - // KeyDebugCGM enables debug messages for circonus-gometrics + // KeyDebugCGM enables debug messages for circonus-gometrics. KeyDebugCGM = "debug_cgm" - // KeyDebugAPI enables debug messages for circonus API calls + // KeyDebugAPI enables debug messages for circonus API calls. KeyDebugAPI = "debug_api" // KeyDebugDumpMetrics enables dumping metrics to a file as they are submitted to circonus @@ -172,130 +171,130 @@ const ( KeyDebugDumpMetrics = "debug_dump_metrics" // Process metrics will be included if EITHER cpu or mem utilization percentages are above these thresholds - // KeyCPUThreshold high cpu utilization percentage to include process metrics + // KeyCPUThreshold high cpu utilization percentage to include process metrics. KeyCPUThreshold = "thresholds.high_cpu" - // KeyMemThreshold high memory utilization percentage to include process metrics + // KeyMemThreshold high memory utilization percentage to include process metrics. KeyMemThreshold = "thresholds.high_memory" - // KeyListen primary address and port to listen on + // KeyListen primary address and port to listen on. KeyListen = "listen" - // KeyListenSocket identifies one or more unix socket files to create + // KeyListenSocket identifies one or more unix socket files to create. KeyListenSocket = "listen_socket" - // KeyLogLevel logging level (panic, fatal, error, warn, info, debug, disabled) + // KeyLogLevel logging level (panic, fatal, error, warn, info, debug, disabled). KeyLogLevel = "log.level" - // KeyLogPretty output formatted log lines (for running in foreground) + // KeyLogPretty output formatted log lines (for running in foreground). KeyLogPretty = "log.pretty" - // KeyPluginDir plugin directory + // KeyPluginDir plugin directory. KeyPluginDir = "plugin_dir" - // KeyPluginList is a list of explicit commands to run as plugins + // KeyPluginList is a list of explicit commands to run as plugins. KeyPluginList = "plugin_list" - // KeyPluginTTLUnits plugin run ttl units + // KeyPluginTTLUnits plugin run ttl units. KeyPluginTTLUnits = "plugin_ttl_units" - // KeyMultiAgent indicates whether multiple agents will be sending metrics to a single check (requires enterprise brokers) + // KeyMultiAgent indicates whether multiple agents will be sending metrics to a single check (requires enterprise brokers). KeyMultiAgent = "multi_agent.enabled" - // KeyMultiAgentInterval indicates how frequently metrics should be sent + // KeyMultiAgentInterval indicates how frequently metrics should be sent. KeyMultiAgentInterval = "multi_agent.interval" - // KeyMultiAgentAccumulate determines if metrics are accumulated on the broker + // KeyMultiAgentAccumulate determines if metrics are accumulated on the broker. KeyMultiAgentAccumulate = "multi_agent.accumulate" - // KeyReverse indicates whether to use reverse connections + // KeyReverse indicates whether to use reverse connections. KeyReverse = "reverse.enabled" - // KeyReverseBrokerCAFile custom broker ca file + // KeyReverseBrokerCAFile custom broker ca file. KeyReverseBrokerCAFile = "reverse.broker_ca_file" - // KeyReverseMaxConnRetry how many times to retry a persistently failing broker connection. default 10, -1 = indefinitely + // KeyReverseMaxConnRetry how many times to retry a persistently failing broker connection. default 10, -1 = indefinitely. KeyReverseMaxConnRetry = "reverse.max_conn_retry" - // KeyShowConfig - show configuration and exit + // KeyShowConfig - show configuration and exit. KeyShowConfig = "show-config" - // KeyShowVersion - show version information and exit + // KeyShowVersion - show version information and exit. KeyShowVersion = "version" - // KeySSLCertFile pem certificate file for SSL + // KeySSLCertFile pem certificate file for SSL. KeySSLCertFile = "ssl.cert_file" - // KeySSLKeyFile key for ssl.cert_file + // KeySSLKeyFile key for ssl.cert_file. KeySSLKeyFile = "ssl.key_file" - // KeySSLListen ssl address and prot to listen on + // KeySSLListen ssl address and prot to listen on. KeySSLListen = "ssl.listen" - // KeySSLVerify controls verification for ssl connections + // KeySSLVerify controls verification for ssl connections. KeySSLVerify = "ssl.verify" - // KeyStatsdDisabled disables the default statsd listener + // KeyStatsdDisabled disables the default statsd listener. KeyStatsdDisabled = "statsd.disabled" - // KeyStatsdGroupCID circonus check id for "group" metrics sent to statsd + // KeyStatsdGroupCID circonus check id for "group" metrics sent to statsd. KeyStatsdGroupCID = "statsd.group.check_id" - // KeyStatsdGroupCounters operator for group counters (sum|average) + // KeyStatsdGroupCounters operator for group counters (sum|average). KeyStatsdGroupCounters = "statsd.group.counters" - // KeyStatsdGroupGauges operator for group gauges (sum|average) + // KeyStatsdGroupGauges operator for group gauges (sum|average). KeyStatsdGroupGauges = "statsd.group.gauges" - // KeyStatsdGroupPrefix metrics prefixed with this string are considered "group" metrics + // KeyStatsdGroupPrefix metrics prefixed with this string are considered "group" metrics. KeyStatsdGroupPrefix = "statsd.group.metric_prefix" - // KeyStatsdGroupSets operator for group sets (sum|average) + // KeyStatsdGroupSets operator for group sets (sum|average). KeyStatsdGroupSets = "statsd.group.sets" - // KeyStatsdHostCategory "plugin" name to put metrics sent to host + // KeyStatsdHostCategory "plugin" name to put metrics sent to host. KeyStatsdHostCategory = "statsd.host.category" - // KeyStatsdHostPrefix metrics prefixed with this string are considered "host" metrics + // KeyStatsdHostPrefix metrics prefixed with this string are considered "host" metrics. KeyStatsdHostPrefix = "statsd.host.metric_prefix" - // KeyStatsdAddr address for statsd listener (default address will always be 'localhost') + // KeyStatsdAddr address for statsd listener (default address will always be 'localhost'). KeyStatsdAddr = "statsd.addr" - // KeyStatsdPort port for statsd listener + // KeyStatsdPort port for statsd listener. KeyStatsdPort = "statsd.port" - // KeyStatsdEnableTCP enables statsd tcp listener + // KeyStatsdEnableTCP enables statsd tcp listener. KeyStatsdEnableTCP = "statsd.enable_tcp" - // KeyStatsdMaxTCPConns set max statsd tcp connections + // KeyStatsdMaxTCPConns set max statsd tcp connections. KeyStatsdMaxTCPConns = "statsd.max_tcp_connections" - // KeyStatsdNPP sets number of packet processors to run concurrently + // KeyStatsdNPP sets number of packet processors to run concurrently. KeyStatsdNPP = "statsd.npp" - // KeyStatsdPQS sets packet queue size + // KeyStatsdPQS sets packet queue size. KeyStatsdPQS = "statsd.pqs" - // KeyCollectors defines the builtin collectors to enable + // KeyCollectors defines the builtin collectors to enable. KeyCollectors = "collectors" - // KeyHostProc defines path builtins will use + // KeyHostProc defines path builtins will use. KeyHostProc = "host_proc" - // KeyHostSys defines path builtins will use, if needed + // KeyHostSys defines path builtins will use, if needed. KeyHostSys = "host_sys" - // KeyHostEtc defines path builtins will use, if needed + // KeyHostEtc defines path builtins will use, if needed. KeyHostEtc = "host_etc" - // KeyHostVar defines path builtins will use, if needed + // KeyHostVar defines path builtins will use, if needed. KeyHostVar = "host_var" - // KeyHostRun defines path builtins will use, if needed + // KeyHostRun defines path builtins will use, if needed. KeyHostRun = "host_run" - // KeyDisableGzip disables gzip on http responses + // KeyDisableGzip disables gzip on http responses. KeyDisableGzip = "server.disable_gzip" - // KeyCheckBundleID the check bundle id to use + // KeyCheckBundleID the check bundle id to use. KeyCheckBundleID = "check.bundle_id" // KeyCheckTarget the check bundle target to use to search for or create a check bundle - // note: if not using reverse, this must be an IP address reachable by the broker + // note: if not using reverse, this must be an IP address reachable by the broker. KeyCheckTarget = "check.target" // KeyCheckEnableNewMetrics toggles automatically enabling new metrics @@ -324,60 +323,60 @@ const ( // TOML configuration file: // `metric_filters = '''[["deny","$^",""],["allow","^.+$",""]]'''` KeyCheckMetricFilters = "check.metric_filters" - // KeyCheckMetricFilterFile an external JSON file to use (see etc/example_metric_filters.json) + // KeyCheckMetricFilterFile an external JSON file to use (see etc/example_metric_filters.json). KeyCheckMetricFilterFile = "check.metric_filter_file" - // KeyCheckUpdateMetricFIlters force update of check with configured metric filters on start + // KeyCheckUpdateMetricFIlters force update of check with configured metric filters on start. KeyCheckUpdateMetricFilters = "check.update_metric_filters" - // KeyCheckPeriod when broker requests metrics + // KeyCheckPeriod when broker requests metrics. KeyCheckPeriod = "check.period" - // KeyCheckTimeout broker timeout when requesting metrics + // KeyCheckTimeout broker timeout when requesting metrics. KeyCheckTimeout = "check.timeout" - // KeyCheckCreate toggles creating a new check bundle when a check bundle id is not supplied + // KeyCheckCreate toggles creating a new check bundle when a check bundle id is not supplied. KeyCheckCreate = "check.create" - // KeyCheckUpdate forces updating all configurable check bundle attributes + // KeyCheckUpdate forces updating all configurable check bundle attributes. KeyCheckUpdate = "check.update" - // KeyCheckBroker a specific broker ID to use when creating a new check bundle + // KeyCheckBroker a specific broker ID to use when creating a new check bundle. KeyCheckBroker = "check.broker" - // KeyCheckTitle a specific title to use when creating a new check bundle + // KeyCheckTitle a specific title to use when creating a new check bundle. KeyCheckTitle = "check.title" - // KeyCheckTags a specific set of tags to use when creating a new check bundle + // KeyCheckTags a specific set of tags to use when creating a new check bundle. KeyCheckTags = "check.tags" - // KeyCheckMetricStreamtags specifies whether to use stream tags (if stream tags are enabled, check tags are added to all metrics by default) + // KeyCheckMetricStreamtags specifies whether to use stream tags (if stream tags are enabled, check tags are added to all metrics by default). KeyCheckMetricStreamtags = "check.metric_streamtags" - // Cluster mode + // Cluster mode. KeyCluster = "cluster" - // Cluster mode enabled + // Cluster mode enabled. KeyClusterEnabled = "cluster.enabled" // Cluster mode enable builtins (host filesystems must be mounted in container and corresponding - // `HOST_*`` environment variables must be set) + // `HOST_*`` environment variables must be set). KeyClusterEnableBuiltins = "cluster.enable_builtins" - // Cluster mode represent statsd gauges as histogram samples, so that _one_ sample will be collected for each node + // Cluster mode represent statsd gauges as histogram samples, so that _one_ sample will be collected for each node. KeyClusterStatsdHistogramGauges = "cluster.statsd_histogram_gauges" cosiName = "cosi" ) var ( - // MetricNameSeparator defines character used to delimit metric name parts + // MetricNameSeparator defines character used to delimit metric name parts. MetricNameSeparator = defaults.MetricNameSeparator // var, TBD whether it will become configurable ) -// Validate verifies the required portions of the configuration +// Validate verifies the required portions of the configuration. func Validate() error { if apiRequired() { err := validateAPIOptions() if err != nil { - return errors.Wrap(err, "API config") + return fmt.Errorf("API config: %w", err) } } @@ -385,24 +384,24 @@ func Validate() error { isMultiAgent := viper.GetBool(KeyMultiAgent) if isReverse && isMultiAgent { - return errors.New("cannot enable reverse AND multi agent simultaneously") + return fmt.Errorf("cannot enable reverse AND multi agent simultaneously") //nolint:goerr113 } if isReverse { err := validateReverseOptions() if err != nil { - return errors.Wrap(err, "reverse config") + return fmt.Errorf("reverse config: %w", err) } } if viper.GetString(KeyCheckBundleID) != "" && viper.GetBool(KeyCheckCreate) { - return errors.New("use --check-create OR --check-id, they are mutually exclusive") + return fmt.Errorf("use --check-create OR --check-id, they are mutually exclusive") //nolint:goerr113 } return nil } -// StatConfig adds the running config to the app stats +// StatConfig adds the running config to the app stats. func StatConfig() error { cfg, err := getConfig() if err != nil { @@ -419,18 +418,18 @@ func StatConfig() error { return nil } -// getConfig dumps the current configuration and returns it +// getConfig dumps the current configuration and returns it. func getConfig() (*Config, error) { var cfg *Config if err := viper.Unmarshal(&cfg); err != nil { - return nil, errors.Wrap(err, "parsing config") + return nil, fmt.Errorf("parsing config: %w", err) } return cfg, nil } -// ShowConfig prints the running configuration +// ShowConfig prints the running configuration. func ShowConfig(w io.Writer) error { var cfg *Config var err error @@ -453,11 +452,11 @@ func ShowConfig(w io.Writer) error { case "toml": data, err = toml.Marshal(*cfg) default: - return errors.Errorf("unknown config format '%s'", format) + return fmt.Errorf("unknown config format '%s'", format) //nolint:goerr113 } if err != nil { - return errors.Wrapf(err, "formatting config (%s)", format) + return fmt.Errorf("formatting config (%s): %w", format, err) } fmt.Fprintln(w, string(data)) diff --git a/internal/config/cosi.go b/internal/config/cosi.go index e435857b..15a3c88f 100644 --- a/internal/config/cosi.go +++ b/internal/config/cosi.go @@ -13,59 +13,64 @@ import ( "regexp" "github.com/circonus-labs/circonus-agent/internal/config/defaults" - "github.com/pkg/errors" ) -// APIConfig defines the api configuration settings +// APIConfig defines the api configuration settings. type APIConfig struct { Key string App string URL string } -// checkConfig defines the portion of check configuration to extract +// checkConfig defines the portion of check configuration to extract. type checkConfig struct { CID string `json:"_cid"` } -// cosiV1Config defines the api portion of the cosi configuration +// cosiV1Config defines the api portion of the cosi configuration. type cosiV1Config struct { APIKey string `json:"api_key"` APIApp string `json:"api_app"` APIURL string `json:"api_url"` } -// cosiV2API defines the api portion of the cosi v2 configuration +// cosiV2API defines the api portion of the cosi v2 configuration. type cosiV2API struct { Key string `json:"key"` App string `json:"app"` URL string `json:"url"` } -// cosiV2Config defines the cosi v2 configuration +// cosiV2Config defines the cosi v2 configuration. type cosiV2Config struct { API cosiV2API `json:"api"` } -// LoadCosiCheckID reads a cosi configuration to obtain the _cid +var ( + errMissingAPIKey = fmt.Errorf("missing API key") + errMissingAPIApp = fmt.Errorf("missing API app") + errMissingAPIURL = fmt.Errorf("missing API URL") +) + +// LoadCosiCheckID reads a cosi configuration to obtain the _cid. func LoadCosiCheckID(checkType string) (string, error) { if checkType != "system" && checkType != "group" { - return "", errors.Errorf("unknown cosi check type (%s)", checkType) + return "", fmt.Errorf("unknown cosi check type (%s)", checkType) //nolint:goerr113 } return loadCheckConfig(filepath.Join(defaults.BasePath, "..", cosiName, "registration", fmt.Sprintf("registration-check-%s.json", checkType))) } -// IsValidCheckID validates a check bundle id +// IsValidCheckID validates a check bundle id. func IsValidCheckID(cid string) (bool, error) { ok, err := regexp.MatchString("^(/check_bundle/)?[0-9]+$", cid) if err != nil { - return false, errors.Wrapf(err, "regex issue validating Check ID (%s)", cid) + return false, fmt.Errorf("regex issue validating Check ID (%s): %w", cid, err) } return ok, nil } -// loadCOSIAPIConfig loads the Circonus API configuration used by cosi +// loadCOSIAPIConfig loads the Circonus API configuration used by cosi. func loadCosiAPIConfig() (*APIConfig, error) { var cfg *APIConfig var err error @@ -82,26 +87,26 @@ func loadCosiAPIConfig() (*APIConfig, error) { return cfg, nil } -// loadCosiV1Config loads (currently, only api) portion of cosi configuration +// loadCosiV1Config loads (currently, only api) portion of cosi configuration. func loadCosiV1Config(cfgFile string) (*APIConfig, error) { data, err := ioutil.ReadFile(cfgFile) if err != nil { - return nil, errors.Wrap(err, "unable to access cosi config") + return nil, fmt.Errorf("unable to access cosi config: %w", err) } var cfg cosiV1Config if err := json.Unmarshal(data, &cfg); err != nil { - return nil, errors.Wrapf(err, "unable to parse cosi config (%s)", cfgFile) + return nil, fmt.Errorf("json parse - cosi config (%s): %w", cfgFile, err) } if cfg.APIKey == "" { - return nil, errors.Errorf("missing API key, invalid cosi config (%s)", cfgFile) + return nil, fmt.Errorf("invalid cosi config (%s): %w", cfgFile, errMissingAPIKey) } if cfg.APIApp == "" { - return nil, errors.Errorf("missing API app, invalid cosi config (%s)", cfgFile) + return nil, fmt.Errorf("invalid cosi config (%s): %w", cfgFile, errMissingAPIApp) } if cfg.APIURL == "" { - return nil, errors.Errorf("missing API URL, invalid cosi config (%s)", cfgFile) + return nil, fmt.Errorf("invalid cosi config (%s): %w", cfgFile, errMissingAPIURL) } return &APIConfig{ @@ -111,22 +116,22 @@ func loadCosiV1Config(cfgFile string) (*APIConfig, error) { }, nil } -// loadCosiV2Config loads (currently, only api) portion of cosi v2 configuration +// loadCosiV2Config loads (currently, only api) portion of cosi v2 configuration. func loadCosiV2Config(cfgFile string) (*APIConfig, error) { var cfg cosiV2Config err := LoadConfigFile(cfgFile, &cfg) if err != nil { - return nil, errors.Wrap(err, "unable to load cosi config") + return nil, fmt.Errorf("unable to load cosi config: %w", err) } if cfg.API.Key == "" { - return nil, errors.Errorf("missing API key, invalid cosi config (%s)", cfgFile) + return nil, fmt.Errorf("invalid cosi config (%s): %w", cfgFile, errMissingAPIKey) } if cfg.API.App == "" { - return nil, errors.Errorf("missing API app, invalid cosi config (%s)", cfgFile) + return nil, fmt.Errorf("invalid cosi config (%s): %w", cfgFile, errMissingAPIApp) } if cfg.API.URL == "" { - return nil, errors.Errorf("missing API URL, invalid cosi config (%s)", cfgFile) + return nil, fmt.Errorf("invalid cosi config (%s): %w", cfgFile, errMissingAPIURL) } return &APIConfig{ @@ -136,20 +141,20 @@ func loadCosiV2Config(cfgFile string) (*APIConfig, error) { }, nil } -// loadChecKConfig loads (currently, only cid) portion of a cosi check config +// loadChecKConfig loads (currently, only cid) portion of a cosi check config. func loadCheckConfig(cfgFile string) (string, error) { data, err := ioutil.ReadFile(cfgFile) if err != nil { - return "", errors.Wrap(err, "unable to access cosi check config") + return "", fmt.Errorf("unable to access cosi check config: %w", err) } var cfg checkConfig err = json.Unmarshal(data, &cfg) if err != nil { - return "", errors.Wrapf(err, "unable to parse cosi check cosi config (%s)", cfgFile) + return "", fmt.Errorf("json parse - cosi check cosi config (%s): %w", cfgFile, err) } if cfg.CID == "" { - return "", errors.Errorf("missing CID key, invalid cosi check config (%s)", cfgFile) + return "", fmt.Errorf("missing CID key, invalid cosi check config (%s)", cfgFile) //nolint:goerr113 } ok, err := IsValidCheckID(cfg.CID) @@ -157,7 +162,7 @@ func loadCheckConfig(cfgFile string) (string, error) { return "", err } if !ok { - return "", errors.Errorf("invalid Check ID (%s)", cfg.CID) + return "", fmt.Errorf("invalid Check ID (%s)", cfg.CID) //nolint:goerr113 } return cfg.CID, nil diff --git a/internal/config/cosi_test.go b/internal/config/cosi_test.go index f19be429..7eba8dc9 100644 --- a/internal/config/cosi_test.go +++ b/internal/config/cosi_test.go @@ -6,10 +6,10 @@ package config import ( + "errors" + "fmt" "path/filepath" "testing" - - "github.com/pkg/errors" ) func TestIsValidCheckID(t *testing.T) { @@ -53,17 +53,18 @@ func TestLoadCosiV1Config(t *testing.T) { t.Log("Testing loadCosiV1Config") tests := []struct { - name string - file string - expectedErr string - shouldFail bool + name string + file string + expectedErr error + expectedErrStr string + shouldFail bool }{ - {"invalid (missing)", filepath.Join("testdata", "cosi_missing.json"), "unable to access cosi config: open testdata/cosi_missing.json: no such file or directory", true}, - {"invalid (bad)", filepath.Join("testdata", "cosi_bad.json"), "unable to parse cosi config (testdata/cosi_bad.json): invalid character '#' looking for beginning of value", true}, - {"invalid (missing key)", filepath.Join("testdata", "cosiv1_invalid_key.json"), "missing API key, invalid cosi config (testdata/cosiv1_invalid_key.json)", true}, - {"invalid (missing app)", filepath.Join("testdata", "cosiv1_invalid_app.json"), "missing API app, invalid cosi config (testdata/cosiv1_invalid_app.json)", true}, - {"invalid (missing url)", filepath.Join("testdata", "cosiv1_invalid_url.json"), "missing API URL, invalid cosi config (testdata/cosiv1_invalid_url.json)", true}, - {"valid", filepath.Join("testdata", "cosiv1.json"), "", false}, + {"invalid (missing)", filepath.Join("testdata", "cosi_missing.json"), nil, "unable to access cosi config: open testdata/cosi_missing.json: no such file or directory", true}, + {"invalid (bad)", filepath.Join("testdata", "cosi_bad.json"), nil, "json parse - cosi config (testdata/cosi_bad.json): invalid character '#' looking for beginning of value", true}, + {"invalid (missing key)", filepath.Join("testdata", "cosiv1_invalid_key.json"), errMissingAPIKey, "", true}, + {"invalid (missing app)", filepath.Join("testdata", "cosiv1_invalid_app.json"), errMissingAPIApp, "", true}, + {"invalid (missing url)", filepath.Join("testdata", "cosiv1_invalid_url.json"), errMissingAPIURL, "", true}, + {"valid", filepath.Join("testdata", "cosiv1.json"), nil, "", false}, } for _, test := range tests { @@ -72,15 +73,20 @@ func TestLoadCosiV1Config(t *testing.T) { t.Parallel() _, err := loadCosiV1Config(tst.file) if tst.shouldFail { - if err == nil { + switch { + case err == nil: t.Fatal("expected error") - } else if err.Error() != tst.expectedErr { - t.Fatalf("unexpected error (%s)", err) - } - } else { - if err != nil { - t.Fatalf("unexpected error (%s)", err) + case tst.expectedErr != nil: + if !errors.Is(err, tst.expectedErr) { + t.Fatalf("unexpected error (%s)", err) + } + case tst.expectedErrStr != "": + if err.Error() != tst.expectedErrStr { + t.Fatalf("unexpected error (%s)", err) + } } + } else if err != nil { + t.Fatalf("unexpected error (%s)", err) } }) } @@ -90,17 +96,18 @@ func TestLoadCosiV2Config(t *testing.T) { t.Log("Testing loadCosiV1Config") tests := []struct { - name string - file string - expectedErr string - shouldFail bool + name string + file string + expectedErr error + expectedErrStr string + shouldFail bool }{ - {"invalid (missing)", filepath.Join("testdata", "cosi_missing"), "unable to load cosi config: no config found matching (testdata/cosi_missing.json|.toml|.yaml): file does not exist", true}, - {"invalid (bad)", filepath.Join("testdata", "cosi_bad"), "unable to load cosi config: parsing configuration file (testdata/cosi_bad.json): invalid character '#' looking for beginning of value", true}, - {"invalid (missing key)", filepath.Join("testdata", "cosiv2_invalid_key"), "missing API key, invalid cosi config (testdata/cosiv2_invalid_key)", true}, - {"invalid (missing app)", filepath.Join("testdata", "cosiv2_invalid_app"), "missing API app, invalid cosi config (testdata/cosiv2_invalid_app)", true}, - {"invalid (missing url)", filepath.Join("testdata", "cosiv2_invalid_url"), "missing API URL, invalid cosi config (testdata/cosiv2_invalid_url)", true}, - {"valid", filepath.Join("testdata", "cosiv2"), "", false}, + {"invalid (missing)", filepath.Join("testdata", "cosi_missing"), nil, "unable to load cosi config: no config found matching (testdata/cosi_missing.json|.toml|.yaml): file does not exist", true}, + {"invalid (bad)", filepath.Join("testdata", "cosi_bad"), nil, "unable to load cosi config: parsing configuration file (testdata/cosi_bad.json): invalid character '#' looking for beginning of value", true}, + {"invalid (missing key)", filepath.Join("testdata", "cosiv2_invalid_key"), errMissingAPIKey, "", true}, + {"invalid (missing app)", filepath.Join("testdata", "cosiv2_invalid_app"), errMissingAPIApp, "", true}, + {"invalid (missing url)", filepath.Join("testdata", "cosiv2_invalid_url"), errMissingAPIURL, "", true}, + {"valid", filepath.Join("testdata", "cosiv2"), nil, "", false}, } for _, test := range tests { @@ -109,15 +116,20 @@ func TestLoadCosiV2Config(t *testing.T) { t.Parallel() _, err := loadCosiV2Config(tst.file) if tst.shouldFail { - if err == nil { + switch { + case err == nil: t.Fatal("expected error") - } else if err.Error() != tst.expectedErr { - t.Fatalf("unexpected error (%s)", err) - } - } else { - if err != nil { - t.Fatalf("unexpected error (%s)", err) + case tst.expectedErr != nil: + if !errors.Is(err, tst.expectedErr) { + t.Fatalf("unexpected error (%s)", err) + } + case tst.expectedErrStr != "": + if err.Error() != tst.expectedErrStr { + t.Fatalf("unexpected error (%s)", err) + } } + } else if err != nil { + t.Fatalf("unexpected error (%s)", err) } }) } @@ -129,7 +141,7 @@ func TestLoadCheckConfig(t *testing.T) { t.Log("No cosi config") { cfgFile := filepath.Join("testdata", "cosi_check_missing.json") - expectedErr := errors.Errorf("unable to access cosi check config: open %s: no such file or directory", cfgFile) + expectedErr := fmt.Errorf("unable to access cosi check config: open %s: no such file or directory", cfgFile) //nolint:goerr113 cid, err := loadCheckConfig(cfgFile) if err == nil { t.Fatal("Expected error") @@ -145,7 +157,7 @@ func TestLoadCheckConfig(t *testing.T) { t.Log("Invalid cosi config (json)") { cfgFile := filepath.Join("testdata", "cosi_bad.json") - expectedErr := errors.Errorf("unable to parse cosi check cosi config (%s): invalid character '#' looking for beginning of value", cfgFile) + expectedErr := fmt.Errorf("json parse - cosi check cosi config (%s): invalid character '#' looking for beginning of value", cfgFile) //nolint:goerr113 cid, err := loadCheckConfig(cfgFile) if err == nil { t.Fatal("Expected error") @@ -161,7 +173,7 @@ func TestLoadCheckConfig(t *testing.T) { t.Log("Invalid cosi config (missing cid)") { cfgFile := filepath.Join("testdata", "cosi_check_invalid_cid.json") - expectedErr := errors.Errorf("missing CID key, invalid cosi check config (%s)", cfgFile) + expectedErr := fmt.Errorf("missing CID key, invalid cosi check config (%s)", cfgFile) //nolint:goerr113 cid, err := loadCheckConfig(cfgFile) if err == nil { t.Fatal("Expected error") diff --git a/internal/config/defaults/defaults.go b/internal/config/defaults/defaults.go index 26e50ef8..dc569cce 100644 --- a/internal/config/defaults/defaults.go +++ b/internal/config/defaults/defaults.go @@ -22,101 +22,101 @@ const ( HostVar = "/var" HostRun = "/run" - // ListenPort is the default agent tcp listening port + // ListenPort is the default agent tcp listening port. ListenPort = 2609 - // APIURL for circonus + // APIURL for circonus. APIURL = "https://api.circonus.com/v2/" - // APIApp defines the api app name associated with the api token key + // APIApp defines the api app name associated with the api token key. APIApp = release.NAME - // Reverse is false by default + // Reverse is false by default. Reverse = false - // SSLVerify enabled by default + // SSLVerify enabled by default. SSLVerify = true - // NoStatsd enabled by default + // NoStatsd enabled by default. NoStatsd = false - // Debug is false by default + // Debug is false by default. Debug = false - // LogLevel set to info by default + // LogLevel set to info by default. LogLevel = "info" - // LogPretty colored/formatted output to stderr + // LogPretty colored/formatted output to stderr. LogPretty = false - // UID to drop privileges to on start + // UID to drop privileges to on start. UID = "nobody" - // Watch plugins for changes + // Watch plugins for changes. Watch = false - // MultiAgent + // MultiAgent. MultiAgent = false MultiAgentInterval = "60s" MultiAgentAccumulate = true - // ReverseMaxConnRetry - how many times to retry persistently failing broker connection + // ReverseMaxConnRetry - how many times to retry persistently failing broker connection. ReverseMaxConnRetry = -1 - // StatsdAddr to listen on + // StatsdAddr to listen on. StatsdAddr = "localhost" - // StatsdPort to listen + // StatsdPort to listen. StatsdPort = "8125" // StatsdHostPrefix defines that metrics received through StatsD inteface - // which are prefixed with this string plus a period go to the host check + // which are prefixed with this string plus a period go to the host check. StatsdHostPrefix = "" // "host." - // StatsdHostCategory defines the "plugin" in which the host metrics will be namepspaced + // StatsdHostCategory defines the "plugin" in which the host metrics will be namepspaced. StatsdHostCategory = "statsd" // StatsdGroupPrefix defines that metrics received through StatsD inteface - // which are prefixed with this string plus a period go to the group check, if enabled + // which are prefixed with this string plus a period go to the group check, if enabled. StatsdGroupPrefix = "group." - // StatsdGroupCounters defines how group counter metrics will be handled (average or sum) + // StatsdGroupCounters defines how group counter metrics will be handled (average or sum). StatsdGroupCounters = "sum" - // StatsdGroupGauges defines how group counter metrics will be handled (average or sum) + // StatsdGroupGauges defines how group counter metrics will be handled (average or sum). StatsdGroupGauges = "average" - // StatsdGroupSets defines how group counter metrics will be handled (average or sum) + // StatsdGroupSets defines how group counter metrics will be handled (average or sum). StatsdGroupSets = "sum" - // StatsdEnableTCP defines if the statsd tcp listener is enabled + // StatsdEnableTCP defines if the statsd tcp listener is enabled. StatsdEnableTCP = false - // StatsdMaxTCPConns defines the max statsd tcp client connections + // StatsdMaxTCPConns defines the max statsd tcp client connections. StatsdMaxTCPConns = uint(250) - // StatsdNPP sets the number of concurrent packet processors to run + // StatsdNPP sets the number of concurrent packet processors to run. StatsdNPP = uint(1) - // StastdPQS sets the packet queue size + // StastdPQS sets the packet queue size. StatsdPQS = uint(1000) - // MetricNameSeparator defines character used to delimit metric name parts + // MetricNameSeparator defines character used to delimit metric name parts. MetricNameSeparator = "`" // PluginTTLUnits defines the default TTL units for plugins with TTLs - // e.g. plugin_ttl30s.sh (30s ttl) plugin_ttl45.sh (would get default ttl units, e.g. 45s) + // e.g. plugin_ttl30s.sh (30s ttl) plugin_ttl45.sh (would get default ttl units, e.g. 45s). PluginTTLUnits = "s" // seconds - // DisableGzip disables gzip compression on responses + // DisableGzip disables gzip compression on responses. DisableGzip = false - // CheckEnableNewMetrics toggles enabling new metrics + // CheckEnableNewMetrics toggles enabling new metrics. CheckEnableNewMetrics = false - // CheckMetricRefreshTTL determines how often to refresh check bundle metrics from API + // CheckMetricRefreshTTL determines how often to refresh check bundle metrics from API. CheckMetricRefreshTTL = "5m" - // CheckCreate toggles creating a check if a check bundle id is not supplied + // CheckCreate toggles creating a check if a check bundle id is not supplied. CheckCreate = false // CheckBroker to use if creating a check, 'select' or '' will @@ -124,21 +124,22 @@ const ( // 1. Active status // 2. Supports the required check type // 3. Responds within reverse.brokerMaxResponseTime + // Enterprise brokers take precedence. CheckBroker = "select" - // CheckTags to use if creating a check (comma separated list) + // CheckTags to use if creating a check (comma separated list). CheckTags = "" - // Cluster mode enabled + // Cluster mode enabled. ClusterEnabled = false // Cluster mode enable builtins (host filesystems must be mounted in container and corresponding - // `HOST_*`` environment variables must be set) + // `HOST_*`` environment variables must be set). ClusterEnableBuiltins = false - // Cluster mode represent statsd gauges as histogram samples, so that _one_ sample will be collected for each node + // Cluster mode represent statsd gauges as histogram samples, so that _one_ sample will be collected for each node. ClusterStatsdHistogramGauges = false // Utilization thresholds for memory and cpu to trigger sending process metric (if a given process is higher for EITHER) - // -1 disables the feature + // -1 disables the feature. CPUThreshold = float32(-1) MemThreshold = float32(-1) ) @@ -163,19 +164,19 @@ var ( BasePath = "" // Collectors defines the default builtin collectors to enable - // OS specific - see init() below + // OS specific - see init() below. Collectors = []string{} - // EtcPath returns the default etc directory within base directory + // EtcPath returns the default etc directory within base directory. EtcPath = "" // (e.g. /opt/circonus/agent/etc) - // PluginPath returns the default plugin path + // PluginPath returns the default plugin path. PluginPath = "" // (e.g. /opt/circonus/agent/plugins) - // CheckTarget defaults to return from os.Hostname() + // CheckTarget defaults to return from os.Hostname(). CheckTarget = "" - // CheckTitle defaults to ' /agent' + // CheckTitle defaults to ' /agent'. CheckTitle = "" // CheckMetricStatePath returns the default state directory. In order for @@ -183,29 +184,29 @@ var ( // and be owned by the user running circonus-agentd (i.e. 'nobody'). CheckMetricStatePath = "" // (e.g. /opt/circonus/agent/state) - // CheckMetricFilters defines default filter to be used with new check creation + // CheckMetricFilters defines default filter to be used with new check creation. CheckMetricFilters = [][]string{{"deny", "^$", ""}, {"allow", "^.+$", ""}} - // CheckMetricFilterFile defines an external file (json) with metric filter definitions + // CheckMetricFilterFile defines an external file (json) with metric filter definitions. CheckMetricFilterFile = "" // CheckUpdateMetricFilters will overwrite filters on the check every time the agent starts - // with whatever rules are in the agent configuration (or external metric filters file) + // with whatever rules are in the agent configuration (or external metric filters file). CheckUpdateMetricFilters = false - // CheckPeriod how often broker requests metrics + // CheckPeriod how often broker requests metrics. CheckPeriod = uint(60) - // CheckTimeout broker timeout when requesting metrics + // CheckTimeout broker timeout when requesting metrics. CheckTimeout = float64(10) - // CheckUpdate forces updating all configurable check attributes + // CheckUpdate forces updating all configurable check attributes. CheckUpdate = false - // SSLCertFile returns the deefault ssl cert file name + // SSLCertFile returns the deefault ssl cert file name. SSLCertFile = "" // (e.g. /opt/circonus/agent/etc/agent.pem) - // SSLKeyFile returns the deefault ssl key file name + // SSLKeyFile returns the deefault ssl key file name. SSLKeyFile = "" // (e.g. /opt/circonus/agent/etc/agent.key) - // StatsdConf returns the default statsd config file + // StatsdConf returns the default statsd config file. StatsdConf = "" // (e.g. /opt/circonus/agent/etc/statsd.json) CheckType = "" diff --git a/internal/config/load_config.go b/internal/config/load_config.go index 5ea449b2..f8fb98e2 100644 --- a/internal/config/load_config.go +++ b/internal/config/load_config.go @@ -13,7 +13,6 @@ import ( "strings" toml "github.com/pelletier/go-toml" - "github.com/pkg/errors" yaml "gopkg.in/yaml.v2" ) @@ -33,7 +32,7 @@ func (e *FileNotFoundErr) Error() string { func LoadConfigFile(base string, target interface{}) error { if base == "" { - return errors.Errorf("invalid config file (empty)") + return fmt.Errorf("invalid config file (empty)") //nolint:goerr113 } extensions := []string{".json", ".toml", ".yaml"} @@ -46,30 +45,29 @@ func LoadConfigFile(base string, target interface{}) error { } data, err := ioutil.ReadFile(cfg) if err != nil { - return errors.Wrapf(err, "reading configuration file (%s)", cfg) + return fmt.Errorf("reading configuration file (%s): %w", cfg, err) } - parseErrMsg := fmt.Sprintf("parsing configuration file (%s)", cfg) switch ext { case ".json": if err := json.Unmarshal(data, target); err != nil { - return errors.Wrap(err, parseErrMsg) + return fmt.Errorf("parsing configuration file (%s): %w", cfg, err) } loaded = true case ".toml": if err := toml.Unmarshal(data, target); err != nil { - return errors.Wrap(err, parseErrMsg) + return fmt.Errorf("parsing configuration file (%s): %w", cfg, err) } loaded = true case ".yaml": if err := yaml.Unmarshal(data, target); err != nil { - return errors.Wrap(err, parseErrMsg) + return fmt.Errorf("parsing configuration file (%s): %w", cfg, err) } loaded = true } } if !loaded { - return errors.Wrapf(os.ErrNotExist, "no config found matching (%s%s)", base, strings.Join(extensions, "|")) + return fmt.Errorf("no config found matching (%s%s): %w", base, strings.Join(extensions, "|"), os.ErrNotExist) } return nil diff --git a/internal/config/reverse.go b/internal/config/reverse.go index badb9d0e..79a0f860 100644 --- a/internal/config/reverse.go +++ b/internal/config/reverse.go @@ -6,13 +6,17 @@ package config import ( + "fmt" "strings" - "github.com/pkg/errors" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) +var ( + errInvalidReverseCID = fmt.Errorf("invalid reverse check cid") +) + func validateReverseOptions() error { cid := viper.GetString(KeyCheckBundleID) @@ -34,10 +38,10 @@ func validateReverseOptions() error { // or, long form: with '/check_bundle/' prefix (e.g. --cid "/check_bundle/123") ok, err := IsValidCheckID(cid) if err != nil { - return errors.Wrap(err, "reverse Check ID") + return fmt.Errorf("reverse Check ID: %w", err) } if !ok { - return errors.Errorf("invalid Reverse Check ID (%s)", cid) + return fmt.Errorf("(%s): %w", cid, errInvalidReverseCID) } log.Debug().Str("cid", cid).Msg("reverse, specified cid") } diff --git a/internal/config/reverse_test.go b/internal/config/reverse_test.go index 4baa23d7..21f9012e 100644 --- a/internal/config/reverse_test.go +++ b/internal/config/reverse_test.go @@ -26,27 +26,25 @@ func TestValidateReverseOptions(t *testing.T) { t.Log("Reverse, (invalid, abc)") { - expectedErr := errors.New("invalid Reverse Check ID (abc)") viper.Set(KeyCheckBundleID, "abc") err := validateReverseOptions() if err == nil { t.Fatal("Expected error") } - if err.Error() != expectedErr.Error() { - t.Fatalf("Expected (%s) got (%s)", expectedErr, err) + if !errors.Is(err, errInvalidReverseCID) { + t.Fatalf("Expected (%s) got (%s)", errInvalidReverseCID, err) } } t.Log("Reverse, (invalid, /check_bundle/abc)") { - expectedErr := errors.New("invalid Reverse Check ID (/check_bundle/abc)") viper.Set(KeyCheckBundleID, "/check_bundle/abc") err := validateReverseOptions() if err == nil { t.Fatal("Expected error") } - if err.Error() != expectedErr.Error() { - t.Fatalf("Expected (%s) got (%s)", expectedErr, err) + if !errors.Is(err, errInvalidReverseCID) { + t.Fatalf("Expected (%s) got (%s)", errInvalidReverseCID, err) } } diff --git a/internal/config/verifyfile.go b/internal/config/verifyfile.go index b40e351d..df29415b 100644 --- a/internal/config/verifyfile.go +++ b/internal/config/verifyfile.go @@ -6,15 +6,19 @@ package config import ( + "fmt" "os" "path/filepath" +) - "github.com/pkg/errors" +var ( + errEmptyFileName = fmt.Errorf("invalid file name (empty)") + errNotRegularFile = fmt.Errorf("not a regular file") ) func verifyFile(fileName string) (string, error) { if fileName == "" { - return "", errors.New("invalid file name (empty)") + return "", errEmptyFileName } var absFileName string @@ -23,25 +27,25 @@ func verifyFile(fileName string) (string, error) { absFileName, err = filepath.Abs(fileName) if err != nil { - return "", err + return "", fmt.Errorf("abs path: %w", err) } fileName = absFileName fi, err = os.Stat(fileName) if err != nil { - return "", err + return "", fmt.Errorf("stat file: %w", err) } if !fi.Mode().IsRegular() { - return "", errors.Errorf("%s: not a regular file", fileName) + return "", fmt.Errorf("%s: %w", fileName, errNotRegularFile) } // also try opening, to verify permissions // if last directory on path is not accessible to user, stat doesn't return EPERM f, err := os.Open(fileName) if err != nil { - return "", err + return "", fmt.Errorf("open file %w", err) } f.Close() diff --git a/internal/multiagent/multiagent.go b/internal/multiagent/multiagent.go index 81597b96..1f5cc892 100644 --- a/internal/multiagent/multiagent.go +++ b/internal/multiagent/multiagent.go @@ -6,6 +6,7 @@ import ( "context" "crypto/tls" "encoding/json" + "fmt" "io/ioutil" "net" "net/http" @@ -22,7 +23,6 @@ import ( "github.com/circonus-labs/circonus-agent/internal/server" "github.com/google/uuid" "github.com/hashicorp/go-retryablehttp" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/spf13/viper" ) @@ -58,7 +58,7 @@ type Submitter struct { interval time.Duration } -// submitLogshim is used to satisfy submission use of retryable-http Logger interface (avoiding ptr receiver issue) +// submitLogshim is used to satisfy submission use of retryable-http Logger interface (avoiding ptr receiver issue). type submitLogshim struct { logh zerolog.Logger } @@ -68,12 +68,18 @@ const ( traceTSFormat = "20060102_150405.000000000" ) +var ( + errInvalidCheck = fmt.Errorf("invalid check (nil)") + errInvalidServer = fmt.Errorf("invalid server (nil)") + errInvalidMetrics = fmt.Errorf("invalid metrics (nil)") +) + func New(parentLogger zerolog.Logger, chk *check.Check, svr *server.Server) (*Submitter, error) { if chk == nil { - return nil, errors.New("invalid check (nil") + return nil, errInvalidCheck } if svr == nil { - return nil, errors.New("invalid server (nil)") + return nil, errInvalidServer } s := &Submitter{ @@ -92,7 +98,7 @@ func New(parentLogger zerolog.Logger, chk *check.Check, svr *server.Server) (*Su cm, err := chk.CheckMeta() if err != nil { - return nil, err + return nil, fmt.Errorf("check meta: %w", err) } s.checkUUID = cm.CheckUUID @@ -100,14 +106,14 @@ func New(parentLogger zerolog.Logger, chk *check.Check, svr *server.Server) (*Su interval := viper.GetString(config.KeyMultiAgentInterval) i, err := time.ParseDuration(interval) if err != nil { - return nil, errors.Wrapf(err, "invalid submission interval (%s)", interval) + return nil, fmt.Errorf("parse submission interval (%s): %w", interval, err) } s.interval = i surl, tlsConfig, err := chk.SubmissionURL() if err != nil { - return nil, errors.Wrap(err, "getting submission url") + return nil, fmt.Errorf("submission url: %w", err) } s.submissionURL = surl @@ -175,7 +181,7 @@ func (s *Submitter) Start(ctx context.Context) error { func (s *Submitter) sendMetrics(ctx context.Context) error { metrics := s.getMetrics() if metrics == nil { - return errors.New("invalid metrics (nil)") + return errInvalidMetrics } if len(metrics) == 0 { return nil @@ -184,7 +190,7 @@ func (s *Submitter) sendMetrics(ctx context.Context) error { rawData, err := json.Marshal(metrics) if err != nil { s.logger.Error().Err(err).Msg("json encoding metrics") - return errors.Wrap(err, "marshaling metrics") + return fmt.Errorf("encode json: %w", err) } start := time.Now() @@ -192,7 +198,7 @@ func (s *Submitter) sendMetrics(ctx context.Context) error { submitUUID, err := uuid.NewRandom() if err != nil { s.logger.Error().Err(err).Msg("creating new submit ID") - return errors.Wrap(err, "creating new submit ID") + return fmt.Errorf("create submission id: %w", err) } payloadIsCompressed := false @@ -204,15 +210,15 @@ func (s *Submitter) sendMetrics(ctx context.Context) error { n, e1 := zw.Write(rawData) if e1 != nil { s.logger.Error().Err(e1).Msg("compressing metrics") - return errors.Wrap(e1, "compressing metrics") + return fmt.Errorf("compressing metrics: %w", e1) } if n != len(rawData) { s.logger.Error().Int("data_len", len(rawData)).Int("written", n).Msg("gzip write length mismatch") - return errors.Errorf("write length mismatch data length %d != written length %d", len(rawData), n) + return fmt.Errorf("write length mismatch data length %d != written length %d", len(rawData), n) //nolint:goerr113 } if e2 := zw.Close(); e2 != nil { s.logger.Error().Err(e2).Msg("closing gzip writer") - return errors.Wrap(e2, "closing gzip writer") + return fmt.Errorf("closing gzip writer: %w", e2) } payloadIsCompressed = true } else { @@ -244,7 +250,7 @@ func (s *Submitter) sendMetrics(ctx context.Context) error { req, err := retryablehttp.NewRequest("PUT", s.submissionURL, subData) if err != nil { s.logger.Error().Err(err).Msg("creating submission request") - return err + return fmt.Errorf("new req: %w", err) } req = req.WithContext(ctx) req.Header.Set("User-Agent", release.NAME+"/"+release.VERSION) @@ -283,24 +289,24 @@ func (s *Submitter) sendMetrics(ctx context.Context) error { } if err != nil { s.logger.Error().Err(err).Msg("making request") - return err + return fmt.Errorf("http do: %w", err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { s.logger.Error().Err(err).Msg("reading body") - return err + return fmt.Errorf("read response: %w", err) } if resp.StatusCode != http.StatusOK { s.logger.Error().Str("url", s.submissionURL).Str("status", resp.Status).Str("body", string(body)).Msg("submitting telemetry") - return errors.Errorf("submitting metrics (%s %s)", s.submissionURL, resp.Status) + return fmt.Errorf("submitting metrics (%s %s)", s.submissionURL, resp.Status) //nolint:goerr113 } var result TrapResult if err := json.Unmarshal(body, &result); err != nil { s.logger.Error().Err(err).Str("body", string(body)).Msg("parsing response") - return errors.Wrapf(err, "parsing response (%s)", string(body)) + return fmt.Errorf("json parse - response (%s): %w", string(body), err) } result.CheckUUID = s.checkUUID diff --git a/internal/plugins/plugin.go b/internal/plugins/plugin.go index 7018d185..e1290dbc 100644 --- a/internal/plugins/plugin.go +++ b/internal/plugins/plugin.go @@ -19,10 +19,9 @@ import ( "github.com/circonus-labs/circonus-agent/internal/release" "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" ) -// drain returns and resets plugin's current metrics +// drain returns and resets plugin's current metrics. func (p *plugin) drain() *cgm.Metrics { p.Lock() defer p.Unlock() @@ -43,7 +42,7 @@ func (p *plugin) drain() *cgm.Metrics { return metrics } -// baseTagList returns the base tags for the plugin +// baseTagList returns the base tags for the plugin. func (p *plugin) baseTagList() []string { tagList := []string{ "source:" + release.NAME, @@ -64,7 +63,7 @@ func (p *plugin) parsePluginOutput(output []string) error { if len(output) == 0 { p.metrics = &cgm.Metrics{} - return errors.Errorf("zero lines of output") + return fmt.Errorf("zero lines of output") //nolint:goerr113 } parseStart := time.Now() @@ -81,7 +80,7 @@ func (p *plugin) parsePluginOutput(output []string) error { Str("output", strings.Join(output, "\n")). Msg("parsing json") p.metrics = &cgm.Metrics{} - return errors.Wrap(err, "parsing json") + return fmt.Errorf("json parse: %w", err) } for mn, md := range jm { // add stream tags to metric name @@ -253,7 +252,7 @@ func (p *plugin) parsePluginOutput(output []string) error { return nil } -// exec runs a specific plugin and saves plugin output +// exec runs a specific plugin and saves plugin output. func (p *plugin) exec() error { // NOTE: !! IMPORTANT !! // locks are handled manually so that long running plugins @@ -267,7 +266,7 @@ func (p *plugin) exec() error { msg := "TTL not expired" plog.Debug().Msg(msg) p.Unlock() - return errors.New(msg) + return fmt.Errorf(msg) //nolint:goerr113 } } @@ -313,25 +312,23 @@ func (p *plugin) exec() error { stdout, err := p.cmd.StdoutPipe() if err != nil { - msg := "stdout pipe" plog.Error(). Err(err). - Msg(msg) + Msg("stdout pipe") resetStatus(err) - return errors.Wrap(err, msg) + return fmt.Errorf("stdout pipe: %w", err) } lines := []string{} scanner := bufio.NewScanner(stdout) if err := p.cmd.Start(); err != nil { - msg := "cmd start" plog.Error(). Err(err). Str("cmd", p.command). - Msg(msg) + Msg("cmd start") resetStatus(err) - return errors.Wrap(err, msg) + return fmt.Errorf("cmd start: %w", err) } for scanner.Scan() { @@ -358,7 +355,7 @@ func (p *plugin) exec() error { Err(err). Msg("reading stdio") - runErr = errors.Wrap(err, "scanner, reading stdio") + runErr = fmt.Errorf("scanner - reading stdio: %w", err) } // parse lines if there are any in the buffer @@ -380,9 +377,9 @@ func (p *plugin) exec() error { Str("cmd", p.command). Msg("exited non-zero") if runErr != nil { - runErr = errors.Wrapf(exiterr, "cmd err (%s) and %s", errMsg, runErr) + runErr = fmt.Errorf("cmd err (%s) and %s: %w", errMsg, runErr.Error(), exiterr) //nolint:errorlint } else { - runErr = errors.Wrapf(exiterr, "cmd err (%s)", errMsg) + runErr = fmt.Errorf("cmd err (%s): %w", errMsg, exiterr) } } else { plog.Error(). @@ -391,13 +388,13 @@ func (p *plugin) exec() error { Str("stderr", stderr). Msg("exited non-zero (not exiterr)") if runErr != nil { - runErr = errors.Wrapf(err, "cmd err (%s) and %s", stderr, runErr) + runErr = fmt.Errorf("cmd err (%s) and %s: %w", stderr, runErr.Error(), err) } else { - runErr = errors.Wrapf(err, "cmd err (%s)", stderr) + runErr = fmt.Errorf("cmd err (%s): %w", stderr, err) } } } resetStatus(runErr) - return runErr + return runErr //nolint:wrapcheck } diff --git a/internal/plugins/plugin_test.go b/internal/plugins/plugin_test.go index 085c538e..f5566a3a 100644 --- a/internal/plugins/plugin_test.go +++ b/internal/plugins/plugin_test.go @@ -7,6 +7,7 @@ package plugins import ( "context" + "fmt" "os" "path" "runtime" @@ -16,7 +17,6 @@ import ( "github.com/circonus-labs/circonus-agent/internal/tags" cgm "github.com/circonus-labs/circonus-gometrics/v3" - "github.com/pkg/errors" "github.com/rs/zerolog" ) @@ -69,7 +69,7 @@ func TestParsePluginOutput(t *testing.T) { t.Log("blank") { p.metrics = nil - expectedErr := errors.Errorf("zero lines of output") + expectedErr := fmt.Errorf("zero lines of output") //nolint:goerr113 err := p.parsePluginOutput([]string{}) if err == nil { t.Fatalf("expected error") @@ -84,7 +84,7 @@ func TestParsePluginOutput(t *testing.T) { t.Log("invalid json metric") { - expectedErr := errors.Errorf("parsing json: unexpected end of JSON input") + expectedErr := fmt.Errorf("json parse: unexpected end of JSON input") //nolint:goerr113 err := p.parsePluginOutput([]string{"{"}) if err == nil { t.Fatalf("expected error") @@ -175,15 +175,10 @@ func TestExec(t *testing.T) { t.Log("already running") { p.running = true - // this error has been removed to declutter log - // expectedErr := errors.Errorf("already running") err := p.exec() if err != nil { t.Fatalf("expected NO error, got (%v)", err) } - // if err.Error() != expectedErr.Error() { - // t.Fatalf("expected (%s) got (%s)", expectedErr, err) - // } p.running = false } @@ -191,7 +186,7 @@ func TestExec(t *testing.T) { { p.lastEnd = time.Now() p.runTTL = 5 * time.Minute - expectedErr := errors.Errorf("TTL not expired") + expectedErr := fmt.Errorf("TTL not expired") //nolint:goerr113 err := p.exec() if err == nil { t.Fatalf("expected error") diff --git a/internal/plugins/plugins.go b/internal/plugins/plugins.go index c545b483..a912c7c7 100644 --- a/internal/plugins/plugins.go +++ b/internal/plugins/plugins.go @@ -8,6 +8,7 @@ package plugins import ( "context" "encoding/json" + "fmt" "os" "os/exec" "path/filepath" @@ -20,13 +21,12 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config/defaults" cgm "github.com/circonus-labs/circonus-gometrics/v3" "github.com/maier/go-appstats" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) -// Plugins defines plugin manager +// Plugins defines plugin manager. type Plugins struct { active map[string]*plugin plugList []string @@ -38,7 +38,7 @@ type Plugins struct { sync.RWMutex } -// Plugin defines a specific plugin +// Plugin defines a specific plugin. type plugin struct { cmd *exec.Cmd command string @@ -67,7 +67,7 @@ const ( nullMetricValue = "[[null]]" ) -// New returns a new instance of the plugins manager +// New returns a new instance of the plugins manager. func New(ctx context.Context, defaultPluginPath string) (*Plugins, error) { p := Plugins{ ctx: ctx, @@ -86,7 +86,7 @@ func New(ctx context.Context, defaultPluginPath string) (*Plugins, error) { } if pluginDir != "" && len(pluginList) > 0 { - return nil, errors.New("invalid configuration cannot specify plugin-dir AND plugin-list") + return nil, fmt.Errorf("invalid configuration cannot specify plugin-dir AND plugin-list") //nolint:goerr113 } if pluginDir == "" { @@ -98,10 +98,9 @@ func New(ctx context.Context, defaultPluginPath string) (*Plugins, error) { return &p, nil } - errMsg := "Invalid plugin directory" absDir, err := filepath.Abs(pluginDir) if err != nil { - return nil, errors.Wrap(err, errMsg) + return nil, fmt.Errorf("invalid plugin directory: %w", err) } pluginDir = absDir @@ -113,18 +112,18 @@ func New(ctx context.Context, defaultPluginPath string) (*Plugins, error) { p.pluginDir = "" return &p, nil } - return nil, errors.Wrap(err, errMsg) + return nil, fmt.Errorf("invalid plugin directory: %w", err) } if !fi.Mode().IsDir() { - return nil, errors.Errorf(errMsg+" (%s) not a directory", pluginDir) + return nil, fmt.Errorf("invalid plugin directory: %s not a directory", pluginDir) //nolint:goerr113 } // also try opening, to verify permissions // if last dir on path is not accessible to user, stat doesn't return EPERM f, err := os.Open(pluginDir) if err != nil { - return nil, errors.Wrap(err, errMsg) + return nil, fmt.Errorf("invalid plugin directory: %w", err) } f.Close() @@ -133,7 +132,7 @@ func New(ctx context.Context, defaultPluginPath string) (*Plugins, error) { return &p, nil } -// Flush plugin metrics +// Flush plugin metrics. func (p *Plugins) Flush(pluginName string) *cgm.Metrics { p.RLock() defer p.RUnlock() @@ -158,13 +157,13 @@ func (p *Plugins) Flush(pluginName string) *cgm.Metrics { return &metrics } -// Stop any long running plugins +// Stop any long running plugins. func (p *Plugins) Stop() error { p.logger.Info().Msg("stopping") return nil } -// Run one or all plugins +// Run one or all plugins. func (p *Plugins) Run(pluginName string) error { p.Lock() @@ -218,7 +217,7 @@ func (p *Plugins) Run(pluginName string) error { if numFound == 0 { p.logger.Error().Str("id", pluginName).Msg("invalid/unknown") p.running = false - return errors.Errorf("invalid plugin (%s)", pluginName) + return fmt.Errorf("invalid plugin (%s)", pluginName) //nolint:goerr113 } } else { p.logger.Debug().Str("plugin(s)", strings.Join(p.plugList, ",")).Msg("running") @@ -247,7 +246,7 @@ func (p *Plugins) Run(pluginName string) error { return nil } -// IsValid determines if a specific plugin is valid +// IsValid determines if a specific plugin is valid. func (p *Plugins) IsValid(pluginName string) bool { if pluginName == "" { return false @@ -266,7 +265,7 @@ func (p *Plugins) IsValid(pluginName string) bool { return false } -// IsInternal checks to see if the plugin is one of the internal plugins (write|statsd) +// IsInternal checks to see if the plugin is one of the internal plugins (write|statsd). func (p *Plugins) IsInternal(pluginName string) bool { if pluginName == "" { return false @@ -276,7 +275,7 @@ func (p *Plugins) IsInternal(pluginName string) bool { return reserved } -// Inventory returns list of active plugins +// Inventory returns list of active plugins. func (p *Plugins) Inventory() []byte { p.Lock() defer p.Unlock() diff --git a/internal/plugins/plugins_test.go b/internal/plugins/plugins_test.go index 99848ca3..3726e030 100644 --- a/internal/plugins/plugins_test.go +++ b/internal/plugins/plugins_test.go @@ -36,7 +36,7 @@ func TestNew(t *testing.T) { errMsg string }{ {"invalid - both dir/list specified", "testdata", "testdata", []string{path.Join("testdata", "test.sh")}, true, "invalid configuration cannot specify plugin-dir AND plugin-list"}, - {"invalid - not a dir", "testdata", path.Join("testdata", "test.sh"), []string{}, true, "Invalid plugin directory"}, + {"invalid - not a dir", "testdata", path.Join("testdata", "test.sh"), []string{}, true, "invalid plugin directory:"}, {"valid - no dir/list, default to dir", "testdata", "", []string{}, false, ""}, {"valid - dir", "", "testdata", []string{}, false, ""}, {"valid - list", "", "", []string{path.Join("testdata", "test.sh")}, false, ""}, @@ -158,6 +158,7 @@ func TestFlush(t *testing.T) { data := p.Flush("invalid") if data == nil { t.Fatal("expected data") + return } if len(*data) != 0 { t.Fatalf("expected no metrics, got (%#v)", data) @@ -173,6 +174,7 @@ func TestFlush(t *testing.T) { data := p.Flush(id) if data == nil { t.Fatal("expected not nil") + return } if len(*data) == 0 { t.Fatalf("expected metrics got none (%#v)", data) @@ -329,6 +331,7 @@ func TestInventory(t *testing.T) { data := p.Inventory() if data == nil { t.Fatalf("expected not nil") + return } expect := []byte(`{"id":"test","name":"test","instance":"","command":"testdata/test.sh"`) diff --git a/internal/plugins/scan.go b/internal/plugins/scan.go index 1c7eefc0..29307bcc 100644 --- a/internal/plugins/scan.go +++ b/internal/plugins/scan.go @@ -21,11 +21,10 @@ import ( "github.com/circonus-labs/circonus-agent/internal/config/defaults" "github.com/circonus-labs/circonus-agent/internal/tags" "github.com/maier/go-appstats" - "github.com/pkg/errors" "github.com/spf13/viper" ) -// Scan the plugin directory for new/updated plugins +// Scan the plugin directory for new/updated plugins. func (p *Plugins) Scan(b *builtins.Builtins) error { p.Lock() defer p.Unlock() @@ -53,11 +52,11 @@ func (p *Plugins) Scan(b *builtins.Builtins) error { if p.pluginDir != "" { if err := p.scanPluginDirectory(b); err != nil { - return errors.Wrap(err, "plugin directory scan") + return fmt.Errorf("plugin directory scan: %w", err) } } else if len(pluginList) > 0 { if err := p.verifyPluginList(pluginList); err != nil { - return errors.Wrap(err, "verifying plugin list") + return fmt.Errorf("verifying plugin list: %w", err) } } @@ -70,10 +69,10 @@ func (p *Plugins) Scan(b *builtins.Builtins) error { return nil } -// verifyPluginList checks supplied list of plugin commands +// verifyPluginList checks supplied list of plugin commands. func (p *Plugins) verifyPluginList(l []string) error { if len(l) == 0 { - return errors.New("invalid plugin list (empty)") + return fmt.Errorf("invalid plugin list (empty)") //nolint:goerr113 } ttlRx := regexp.MustCompile(`_ttl(.+)$`) @@ -172,24 +171,24 @@ func (p *Plugins) verifyPluginList(l []string) error { return nil } -// scanPluginDirectory finds and loads plugins +// scanPluginDirectory finds and loads plugins. func (p *Plugins) scanPluginDirectory(b *builtins.Builtins) error { if p.pluginDir == "" { - return errors.New("invalid plugin directory (none)") + return fmt.Errorf("invalid plugin directory (none)") //nolint:goerr113 } p.logger.Info().Str("dir", p.pluginDir).Msg("scanning") f, err := os.Open(p.pluginDir) if err != nil { - return errors.Wrap(err, "open plugin directory") + return fmt.Errorf("open plugin directory: %w", err) } defer f.Close() files, err := f.Readdir(-1) if err != nil { - return errors.Wrap(err, "reading plugin directory") + return fmt.Errorf("reading plugin directory: %w", err) } ttlRx := regexp.MustCompile(`_ttl(.+)$`) diff --git a/internal/release/main.go b/internal/release/main.go index 41eb613c..145cb280 100644 --- a/internal/release/main.go +++ b/internal/release/main.go @@ -10,25 +10,25 @@ import ( ) const ( - // NAME is the name of this application + // NAME is the name of this application. NAME = "circonus-agent" - // ENVPREFIX is the environment variable prefix + // ENVPREFIX is the environment variable prefix. ENVPREFIX = "CA" ) -// defined during build (e.g. goreleaser, see .goreleaser.yml) +// defined during build (e.g. goreleaser, see .goreleaser.yml). var ( - // COMMIT of relase in git repo + // COMMIT of relase in git repo. COMMIT = "undef" - // DATE of release + // DATE of release. DATE = "undef" - // TAG of release + // TAG of release. TAG = "none" - // VERSION of the release + // VERSION of the release. VERSION = "Dev" ) -// Info contains release information +// Info contains release information. type Info struct { Name string Version string diff --git a/internal/reverse/connection/command_processor.go b/internal/reverse/connection/command_processor.go index 0e865018..d5795d46 100644 --- a/internal/reverse/connection/command_processor.go +++ b/internal/reverse/connection/command_processor.go @@ -7,8 +7,7 @@ package connection import ( "context" - - "github.com/pkg/errors" + "fmt" ) func (c *Connection) newCommandProcessor(ctx context.Context, cmds <-chan command) <-chan command { @@ -34,7 +33,7 @@ func (c *Connection) processCommand(cmd command) command { } if cmd.name == CommandReset { - cmd.err = errors.Errorf("received %s command from broker", cmd.name) + cmd.err = fmt.Errorf("received %s command from broker", cmd.name) //nolint:goerr113 cmd.ignore = false cmd.reset = true return cmd @@ -42,18 +41,18 @@ func (c *Connection) processCommand(cmd command) command { if cmd.name != CommandConnect { cmd.ignore = true - cmd.err = errors.Errorf("unused/empty command (%s)", cmd.name) + cmd.err = fmt.Errorf("unused/empty command (%s)", cmd.name) //nolint:goerr113 return cmd } if len(cmd.request) == 0 { - cmd.err = errors.New("invalid connect command, 0 length request") + cmd.err = fmt.Errorf("invalid connect command, 0 length request") //nolint:goerr113 return cmd } metrics, err := c.fetchMetricData(&cmd.request, cmd.channelID) if err != nil { - cmd.err = errors.Wrap(err, "fetching metrics") + cmd.err = fmt.Errorf("fetching metrics: %w", err) return cmd } diff --git a/internal/reverse/connection/command_reader.go b/internal/reverse/connection/command_reader.go index ce17c7c7..756d37a9 100644 --- a/internal/reverse/connection/command_reader.go +++ b/internal/reverse/connection/command_reader.go @@ -11,8 +11,6 @@ import ( "io" "net" "time" - - "github.com/pkg/errors" ) func (c *Connection) newCommandReader(ctx context.Context, r io.Reader) <-chan command { @@ -51,7 +49,7 @@ func (c *Connection) readCommand(r io.Reader) command { c.Unlock() } } - return command{err: errors.Wrap(err, "reading command"), reset: reset, ignore: ignore} + return command{err: fmt.Errorf("reading command: %w", err), reset: reset, ignore: ignore} } c.Lock() @@ -63,7 +61,7 @@ func (c *Connection) readCommand(r io.Reader) command { Str("cmd_header", fmt.Sprintf("%#v", cmdPkt.header)). Str("cmd_payload", string(cmdPkt.payload)). Msg("expected command") - return command{err: errors.New("expected command")} + return command{err: fmt.Errorf("expected command")} //nolint:goerr113 } cmd := command{ @@ -92,7 +90,7 @@ func (c *Connection) readCommand(r io.Reader) command { c.Unlock() } } - return command{err: errors.Wrap(err, "reading command payload"), reset: reset, ignore: ignore} + return command{err: fmt.Errorf("reading command payload: %w", err), reset: reset, ignore: ignore} } c.Lock() @@ -106,7 +104,7 @@ func (c *Connection) readCommand(r io.Reader) command { Str("req_header", fmt.Sprintf("%#v", reqPkt.header)). Str("req_payload", string(reqPkt.payload)). Msg("expected request") - cmd.err = errors.New("expected request") + cmd.err = fmt.Errorf("expected request") //nolint:goerr113 return cmd } diff --git a/internal/reverse/connection/connection.go b/internal/reverse/connection/connection.go index d3ad2f45..3884b5d2 100644 --- a/internal/reverse/connection/connection.go +++ b/internal/reverse/connection/connection.go @@ -19,7 +19,6 @@ import ( "github.com/circonus-labs/circonus-agent/internal/check" "github.com/circonus-labs/circonus-agent/internal/config" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/spf13/viper" ) @@ -37,7 +36,7 @@ type Connection struct { sync.Mutex } -// command contains details of the command received from the broker +// command contains details of the command received from the broker. type command struct { start time.Time metrics *[]byte @@ -50,20 +49,20 @@ type command struct { reset bool } -// noitHeader defines the header received from the noit/broker +// noitHeader defines the header received from the noit/broker. type noitHeader struct { channelID uint16 isCommand bool payloadLen uint32 } -// noitFrame defines the header + the payload (described by the header) received from the noit/broker +// noitFrame defines the header + the payload (described by the header) received from the noit/broker. type noitFrame struct { header *noitHeader payload []byte } -// connError returned from connect(), adds flag indicating whether to retry +// connError returned from connect(), adds flag indicating whether to retry. type connError struct { err error retry bool @@ -94,7 +93,7 @@ const ( CommandConnect = "CONNECT" // Connect command, must be followed by a request payload CommandReset = "RESET" // Reset command, resets the connection - // NOTE: TBD, make some of these user-configurable + // NOTE: TBD, make some of these user-configurable. CommTimeoutSeconds = 10 // seconds, when communicating with noit DialerTimeoutSeconds = 15 // seconds, establishing connection MetricTimeoutSeconds = 50 // seconds, when communicating with agent @@ -109,10 +108,10 @@ const ( func New(parentLogger zerolog.Logger, agentAddress string, cfg *check.ReverseConfig) (*Connection, error) { if agentAddress == "" { - return nil, errors.Errorf("invalid agent address (empty)") + return nil, fmt.Errorf("invalid agent address (empty)") //nolint:goerr113 } if cfg == nil { - return nil, errors.Errorf("invalid config (nil)") + return nil, fmt.Errorf("invalid config (nil)") //nolint:goerr113 } if n, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)); err != nil { @@ -134,7 +133,7 @@ func New(parentLogger zerolog.Logger, agentAddress string, cfg *check.ReverseCon return &c, nil } -// Start the reverse connection to the broker +// Start the reverse connection to the broker. func (c *Connection) Start(ctx context.Context) error { for { conn, cerr := c.connect(ctx) @@ -224,13 +223,13 @@ func (c *Connection) Start(ctx context.Context) error { } // connect to broker w/tls and send initial introduction -// NOTE: all reverse connections require tls +// NOTE: all reverse connections require tls. func (c *Connection) connect(ctx context.Context) (*tls.Conn, *connError) { c.Lock() if c.connAttempts > 0 { if c.maxConnRetry != -1 && c.connAttempts >= c.maxConnRetry { c.Unlock() - return nil, &connError{retry: false, err: errors.Errorf("max broker connection attempts reached (%d of %d)", c.connAttempts, c.maxConnRetry)} + return nil, &connError{retry: false, err: fmt.Errorf("max broker connection attempts reached (%d of %d)", c.connAttempts, c.maxConnRetry)} //nolint:goerr113 } c.logger.Info(). @@ -262,7 +261,7 @@ func (c *Connection) connect(ctx context.Context) (*tls.Conn, *connError) { if c.connAttempts%ConfigRetryLimit == 0 { // Check configuration refresh -- TBD on if check refresh really needed or just find owner again for clustered c.Unlock() - return nil, &connError{retry: false, err: errors.Errorf("max connection attempts (%d), check refresh", c.connAttempts)} + return nil, &connError{retry: false, err: fmt.Errorf("max connection attempts (%d), check refresh", c.connAttempts)} //nolint:goerr113 } } c.Unlock() @@ -277,10 +276,10 @@ func (c *Connection) connect(ctx context.Context) (*tls.Conn, *connError) { if err != nil { if ne, ok := err.(*net.OpError); ok { //nolint:errorlint if ne.Timeout() { - return nil, &connError{retry: ne.Temporary(), err: errors.Wrapf(err, "timeout connecting to %s", revHost)} + return nil, &connError{retry: ne.Temporary(), err: fmt.Errorf("timeout connecting to %s: %w", revHost, err)} } } - return nil, &connError{retry: true, err: errors.Wrapf(err, "connecting to %s", revHost)} + return nil, &connError{retry: true, err: fmt.Errorf("connecting to %s: %w", revHost, err)} } c.logger.Info().Str("host", revHost).Msg("connected") @@ -294,7 +293,7 @@ func (c *Connection) connect(ctx context.Context) (*tls.Conn, *connError) { c.logger.Debug().Msg(fmt.Sprintf("sending intro '%s'", introReq)) if _, err := fmt.Fprintf(conn, "%s HTTP/1.1\r\n\r\n", introReq); err != nil { c.logger.Error().Err(err).Msg("sending intro") - return nil, &connError{retry: true, err: errors.Wrapf(err, "unable to write intro to %s", revHost)} + return nil, &connError{retry: true, err: fmt.Errorf("unable to write intro to %s: %w", revHost, err)} } c.Lock() @@ -306,7 +305,7 @@ func (c *Connection) connect(ctx context.Context) (*tls.Conn, *connError) { return conn, nil } -// getNextDelay for failed connection attempts +// getNextDelay for failed connection attempts. func (c *Connection) getNextDelay(currDelay time.Duration) time.Duration { maxDelay := MaxDelaySeconds * time.Second @@ -328,7 +327,7 @@ func (c *Connection) getNextDelay(currDelay time.Duration) time.Duration { return delay } -// resetConnectionAttempts on successful send/receive +// resetConnectionAttempts on successful send/receive. func (c *Connection) resetConnectionAttempts() { c.Lock() if c.connAttempts > 0 { @@ -338,7 +337,7 @@ func (c *Connection) resetConnectionAttempts() { c.Unlock() } -// Error returns string representation of a connError +// Error returns string representation of a connError. func (e *connError) Error() string { return e.err.Error() } diff --git a/internal/reverse/connection/connection_test.go b/internal/reverse/connection/connection_test.go index c5fc40fb..9a143c02 100644 --- a/internal/reverse/connection/connection_test.go +++ b/internal/reverse/connection/connection_test.go @@ -19,7 +19,6 @@ package connection // "github.com/circonus-labs/circonus-agent/internal/check" // "github.com/circonus-labs/circonus-agent/internal/config" // "github.com/circonus-labs/circonus-agent/internal/config/defaults" -// "github.com/pkg/errors" // "github.com/rs/zerolog" // "github.com/spf13/viper" // ) diff --git a/internal/reverse/connection/frame.go b/internal/reverse/connection/frame.go index eaa896dd..cc141e97 100644 --- a/internal/reverse/connection/frame.go +++ b/internal/reverse/connection/frame.go @@ -8,10 +8,9 @@ package connection import ( "crypto/tls" "encoding/binary" + "fmt" "io" "time" - - "github.com/pkg/errors" ) // buildFrame creates a frame to send to broker. @@ -19,7 +18,7 @@ import ( // bytes 1-6 header // 2 bytes channel id and command flag // 4 bytes length of data -// bytes 7-n are data, where 0 < n <= maxPayloadLen +// bytes 7-n are data, where 0 < n <= maxPayloadLen. func buildFrame(channelID uint16, isCommand bool, payload []byte) []byte { frame := make([]byte, len(payload)+6) @@ -35,7 +34,7 @@ func buildFrame(channelID uint16, isCommand bool, payload []byte) []byte { return frame } -// readFrameFromBroker reads a frame(header + payload) from broker +// readFrameFromBroker reads a frame(header + payload) from broker. func (c *Connection) readFrameFromBroker(r io.Reader) (*noitFrame, error) { if conn, ok := r.(*tls.Conn); ok { if err := conn.SetDeadline(time.Now().Add(CommTimeoutSeconds * time.Second)); err != nil { @@ -48,7 +47,7 @@ func (c *Connection) readFrameFromBroker(r io.Reader) (*noitFrame, error) { } if hdr.payloadLen > MaxPayloadLen { - return nil, errors.Errorf("received oversized frame (%d len)", hdr.payloadLen) // restart the connection + return nil, fmt.Errorf("received oversized frame (%d len)", hdr.payloadLen) //nolint:goerr113 // restart the connection } if conn, ok := r.(*tls.Conn); ok { @@ -74,7 +73,7 @@ func (c *Connection) readFrameFromBroker(r io.Reader) (*noitFrame, error) { }, nil } -// readFrameHeader reads 6 bytes from the broker connection +// readFrameHeader reads 6 bytes from the broker connection. func readFrameHeader(r io.Reader) (*noitHeader, error) { hdrSize := 6 @@ -93,7 +92,7 @@ func readFrameHeader(r io.Reader) (*noitHeader, error) { return hdr, nil } -// readFramePayload consumes n bytes from the broker connection +// readFramePayload consumes n bytes from the broker connection. func readFramePayload(r io.Reader, size uint32) ([]byte, error) { data, err := readBytes(r, int64(size)) if err != nil { @@ -112,7 +111,7 @@ func readBytes(r io.Reader, size int64) ([]byte, error) { n, err := lr.Read(buff[:cap(buff)]) if n == 0 && err != nil { - return nil, err + return nil, fmt.Errorf("read: %w", err) } // dealing with expected sizes @@ -121,7 +120,7 @@ func readBytes(r io.Reader, size int64) ([]byte, error) { if n < sz { sz = n } - return nil, errors.Errorf("invalid read, expected bytes %d got %d (%#v = %s)", size, n, buff[0:sz], string(buff[0:sz])) + return nil, fmt.Errorf("invalid read, expected bytes %d got %d (%#v = %s)", size, n, buff[0:sz], string(buff[0:sz])) //nolint:goerr113 } return buff[:n], nil diff --git a/internal/reverse/connection/metrics.go b/internal/reverse/connection/metrics.go index e824fd76..cd6e09d5 100644 --- a/internal/reverse/connection/metrics.go +++ b/internal/reverse/connection/metrics.go @@ -13,11 +13,9 @@ import ( "math" "net" "time" - - "github.com/pkg/errors" ) -// sendMetricData frames and sends data (in chunks <= maxPayloadLen) to broker +// sendMetricData frames and sends data (in chunks <= maxPayloadLen) to broker. func (c *Connection) sendMetricData(r io.Writer, channelID uint16, data *[]byte, cmdStart time.Time) error { sendStart := time.Now() empty := []byte("{}") @@ -46,7 +44,7 @@ func (c *Connection) sendMetricData(r io.Writer, channelID uint16, data *[]byte, sent, err := r.Write(frame) if err != nil { - return errors.Wrap(err, "writing metric data") + return fmt.Errorf("writing metric data: %w", err) } offset += sent sentBytes = offset @@ -64,12 +62,12 @@ func (c *Connection) sendMetricData(r io.Writer, channelID uint16, data *[]byte, return nil } -// fetchMetricData sends the command arguments to the local agent +// fetchMetricData sends the command arguments to the local agent. func (c *Connection) fetchMetricData(request *[]byte, channelID uint16) (*[]byte, error) { fetchStart := time.Now() conn, err := net.DialTimeout("tcp", c.agentAddress, DialerTimeoutSeconds*time.Second) if err != nil { - return nil, errors.Wrap(err, "connecting to agent for metrics") + return nil, fmt.Errorf("connecting to agent for metrics: %w", err) } defer conn.Close() @@ -85,7 +83,7 @@ func (c *Connection) fetchMetricData(request *[]byte, channelID uint16) (*[]byte numBytes, err := conn.Write(*request) if err != nil { - return nil, errors.Wrap(err, "writing metric request") + return nil, fmt.Errorf("writing metric request: %w", err) } if numBytes != len(*request) { c.logger.Warn(). @@ -96,7 +94,7 @@ func (c *Connection) fetchMetricData(request *[]byte, channelID uint16) (*[]byte data, err := ioutil.ReadAll(conn) if err != nil { - return nil, errors.Wrap(err, "reading metric data") + return nil, fmt.Errorf("reading metric data: %w", err) } c.logger.Debug().Uint16("channel_id", channelID).Str("duration", time.Since(fetchStart).String()).Int("bytes", len(data)).Msg("fetched metrics") diff --git a/internal/reverse/reverse.go b/internal/reverse/reverse.go index f72d8e9c..5c9e83e5 100644 --- a/internal/reverse/reverse.go +++ b/internal/reverse/reverse.go @@ -8,13 +8,14 @@ package reverse import ( "context" + "errors" + "fmt" "sync" "time" "github.com/circonus-labs/circonus-agent/internal/check" "github.com/circonus-labs/circonus-agent/internal/config" "github.com/circonus-labs/circonus-agent/internal/reverse/connection" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/spf13/viper" ) @@ -29,10 +30,10 @@ type Reverse struct { func New(parentLogger zerolog.Logger, chk *check.Check, agentAddress string) (*Reverse, error) { if chk == nil { - return nil, errors.New("invalid check (nil") + return nil, fmt.Errorf("invalid check (nil") //nolint:goerr113 } if agentAddress == "" { - return nil, errors.New("invalid agent address (empty)") + return nil, fmt.Errorf("invalid agent address (empty)") //nolint:goerr113 } r := &Reverse{ @@ -47,13 +48,13 @@ func New(parentLogger zerolog.Logger, chk *check.Check, agentAddress string) (*R cfgs, err := r.chk.GetReverseConfigs() if err != nil { - return nil, errors.Wrap(err, "getting reverse configurations") + return nil, fmt.Errorf("getting reverse configurations: %w", err) } r.configs = cfgs cm, err := chk.CheckMeta() if err != nil { - return nil, errors.Wrap(err, "setting up reverse") + return nil, fmt.Errorf("setting up reverse: %w", err) } r.logger = parentLogger.With(). Str("pkg", "reverse"). @@ -65,17 +66,17 @@ func New(parentLogger zerolog.Logger, chk *check.Check, agentAddress string) (*R return r, nil } -// Start reverse connection(s) to the broker(s) +// Start reverse connection(s) to the broker(s). func (r *Reverse) Start(ctx context.Context) error { if !r.enabled { r.logger.Info().Msg("disabled, not starting") return nil } if r.configs == nil { - return errors.New("invalid reverse configurations (nil)") + return fmt.Errorf("invalid reverse configurations (nil)") //nolint:goerr113 } if len(*r.configs) == 0 { - return errors.New("invalid reverse configurations (zero)") + return fmt.Errorf("invalid reverse configurations (zero)") //nolint:goerr113 } lastRefresh := time.Now() @@ -98,12 +99,12 @@ func (r *Reverse) Start(ctx context.Context) error { if err := r.chk.RefreshReverseConfig(); err != nil { r.logger.Error().Err(err).Msg("refreshing reverse configuration") cancel() - return err + return fmt.Errorf("refresh reverse config: %w", err) } cfgs, err := r.chk.GetReverseConfigs() if err != nil { cancel() - return errors.Wrap(err, "getting reverse configurations") + return fmt.Errorf("get reverse configurations: %w", err) } r.configs = cfgs refreshCheck = false @@ -123,7 +124,7 @@ func (r *Reverse) Start(ctx context.Context) error { // refreshCheck = true // continue // } - return err + return fmt.Errorf("find primary broker: %w", err) } r.logger.Debug().Msg("set broker config") @@ -143,7 +144,7 @@ func (r *Reverse) Start(ctx context.Context) error { rc, err := connection.New(r.logger, r.agentAddress, &cfg) if err != nil { cancel() - return err + return fmt.Errorf("new conn: %w", err) } var wg sync.WaitGroup diff --git a/internal/reverse/reverse_test.go b/internal/reverse/reverse_test.go index 02c026ba..5abea074 100644 --- a/internal/reverse/reverse_test.go +++ b/internal/reverse/reverse_test.go @@ -27,7 +27,6 @@ package reverse // "github.com/circonus-labs/circonus-agent/internal/config" // "github.com/circonus-labs/circonus-agent/internal/config/defaults" // "github.com/circonus-labs/go-apiclient" -// "github.com/pkg/errors" // "github.com/rs/zerolog" // "github.com/rs/zerolog/log" // "github.com/spf13/viper" diff --git a/internal/server/agent_host_stats.go b/internal/server/agent_host_stats.go index 40e5c51b..f3a74281 100644 --- a/internal/server/agent_host_stats.go +++ b/internal/server/agent_host_stats.go @@ -21,7 +21,7 @@ import ( "github.com/spf13/viper" ) -// agentHostStats produces the internal agent host metrics +// agentHostStats produces the internal agent host metrics. func (s *Server) agentHostStats(metrics cgm.Metrics, mtags []string) { // uptime @@ -83,7 +83,7 @@ func (s *Server) agentHostStats(metrics cgm.Metrics, mtags []string) { // processes { memLimit := float32(viper.GetFloat64(config.KeyMemThreshold)) - cpuLimit := float64(viper.GetFloat64(config.KeyCPUThreshold)) + cpuLimit := viper.GetFloat64(config.KeyCPUThreshold) // only do this if someone actually turns it on the default, -1=disabled if memLimit < 0 && cpuLimit < 0 { diff --git a/internal/server/agent_host_stats_openbsd.go b/internal/server/agent_host_stats_openbsd.go index c8c5aa0b..177c06d3 100644 --- a/internal/server/agent_host_stats_openbsd.go +++ b/internal/server/agent_host_stats_openbsd.go @@ -14,7 +14,7 @@ import ( "github.com/shirou/gopsutil/mem" ) -// agentHostStats produces the internal agent host metrics +// agentHostStats produces the internal agent host metrics. func (s *Server) agentHostStats(metrics cgm.Metrics, mtags []string) { /// // NOTE: host/process packages have an error on openbsd at the moment diff --git a/internal/server/agent_mem_stats.go b/internal/server/agent_mem_stats.go index 637419c9..749c685f 100644 --- a/internal/server/agent_mem_stats.go +++ b/internal/server/agent_mem_stats.go @@ -14,7 +14,7 @@ import ( cgm "github.com/circonus-labs/circonus-gometrics/v3" ) -// agentMemoryStats produces the internal agent metrics +// agentMemoryStats produces the internal agent metrics. func (s *Server) agentMemoryStats(metrics cgm.Metrics, mtags []string) { var mem syscall.Rusage if err := syscall.Getrusage(syscall.RUSAGE_SELF, &mem); err == nil { diff --git a/internal/server/agent_mem_stats_solaris.go b/internal/server/agent_mem_stats_solaris.go index 6c57c02d..310568cc 100644 --- a/internal/server/agent_mem_stats_solaris.go +++ b/internal/server/agent_mem_stats_solaris.go @@ -11,7 +11,7 @@ import ( cgm "github.com/circonus-labs/circonus-gometrics/v3" ) -// agentMemoryStats produces the internal agent metrics +// agentMemoryStats produces the internal agent metrics. func (s *Server) agentMemoryStats(metrics cgm.Metrics, mtags []string) { // var mem syscall.Rusage // if err := syscall.Getrusage(syscall.RUSAGE_SELF, &mem); err == nil { diff --git a/internal/server/agent_mem_stats_windows.go b/internal/server/agent_mem_stats_windows.go index 71428645..32faf11f 100644 --- a/internal/server/agent_mem_stats_windows.go +++ b/internal/server/agent_mem_stats_windows.go @@ -11,7 +11,7 @@ import ( cgm "github.com/circonus-labs/circonus-gometrics/v3" ) -// agentMemoryStats produces the internal agent metrics +// agentMemoryStats produces the internal agent metrics. func (s *Server) agentMemoryStats(metrics cgm.Metrics, mtags []string) { // var mem syscall.Rusage // if err := syscall.Getrusage(syscall.RUSAGE_SELF, &mem); err == nil { diff --git a/internal/server/agent_stats.go b/internal/server/agent_stats.go index 3d11ff9a..5deb68a0 100644 --- a/internal/server/agent_stats.go +++ b/internal/server/agent_stats.go @@ -13,7 +13,7 @@ import ( cgm "github.com/circonus-labs/circonus-gometrics/v3" ) -// agentStats produces the internal agent metrics +// agentStats produces the internal agent metrics. func (s *Server) agentStats(metrics cgm.Metrics, mtags []string) { s.agentHostStats(metrics, mtags) diff --git a/internal/server/handlers.go b/internal/server/handlers.go index a46a9de2..12966fbe 100644 --- a/internal/server/handlers.go +++ b/internal/server/handlers.go @@ -38,7 +38,7 @@ const ( ) // run handles requests to execute plugins and return metrics emitted -// handles /, /run, or /run/plugin_name +// handles /, /run, or /run/plugin_name. func (s *Server) run(w http.ResponseWriter, r *http.Request) { runStart := time.Now() id := "" @@ -106,7 +106,7 @@ func (s *Server) run(w http.ResponseWriter, r *http.Request) { s.encodeResponse(&metrics, w, r, runStart) } -// GetMetrics collects metrics from the various conduits and returns them for disposition +// GetMetrics collects metrics from the various conduits and returns them for disposition. func (s *Server) GetMetrics(conduits []string, id string) cgm.Metrics { includeAgentMetrics := false // default to all conduits if list is empty @@ -323,7 +323,7 @@ func (s *Server) encodeResponse(m *cgm.Metrics, w http.ResponseWriter, r *http.R } } -// inventory returns the current, active plugin inventory +// inventory returns the current, active plugin inventory. func (s *Server) inventory(w http.ResponseWriter) { inventory := s.plugins.Inventory() if inventory == nil { @@ -335,7 +335,7 @@ func (s *Server) inventory(w http.ResponseWriter) { _, _ = w.Write(inventory) } -// socketHandler gates /write for the socket server only +// socketHandler gates /write for the socket server only. func (s *Server) socketHandler(w http.ResponseWriter, r *http.Request) { if !writePathRx.MatchString(r.URL.Path) { _ = appstats.IncrementInt("requests_bad") @@ -411,7 +411,7 @@ func (s *Server) promReceiver(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } -// promOutput returns the last metrics in prom format +// promOutput returns the last metrics in prom format. func (s *Server) promOutput(w http.ResponseWriter) { s.logger.Debug().Str("in", "prom output").Msg("start") diff --git a/internal/server/promrecv/promrecv.go b/internal/server/promrecv/promrecv.go index 4a44917d..68dd8e60 100644 --- a/internal/server/promrecv/promrecv.go +++ b/internal/server/promrecv/promrecv.go @@ -34,7 +34,7 @@ var ( logger = log.With().Str("pkg", "promrecv").Logger() ) -// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue) +// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue). type logshim struct { logh zerolog.Logger } @@ -78,14 +78,14 @@ func initCGM() error { return nil } -// Flush returns current metrics +// Flush returns current metrics. func Flush() *cgm.Metrics { _ = initCGM() return metrics.FlushMetrics() } -// Parse handles incoming PUT/POST requests +// Parse handles incoming PUT/POST requests. func Parse(data io.Reader) error { if err := initCGM(); err != nil { return err @@ -97,7 +97,7 @@ func Parse(data io.Reader) error { metricFamilies, err := parser.TextToMetricFamilies(data) if err != nil { - return err + return fmt.Errorf("parse - text to metric families: %w", err) } for mn, mf := range metricFamilies { @@ -107,13 +107,13 @@ func Parse(data io.Reader) error { switch { case mf.GetType() == dto.MetricType_SUMMARY: metrics.Gauge(metricName+"_count", float64(m.GetSummary().GetSampleCount())) - metrics.Gauge(metricName+"_sum", float64(m.GetSummary().GetSampleSum())) + metrics.Gauge(metricName+"_sum", m.GetSummary().GetSampleSum()) for qn, qv := range getQuantiles(m) { metrics.GaugeWithTags(metricName+"_"+qn, tags, qv) } case mf.GetType() == dto.MetricType_HISTOGRAM: metrics.Gauge(metricName+"_count", float64(m.GetHistogram().GetSampleCount())) - metrics.Gauge(metricName+"_sum", float64(m.GetHistogram().GetSampleSum())) + metrics.Gauge(metricName+"_sum", m.GetHistogram().GetSampleSum()) for bn, bv := range getBuckets(m) { metrics.GaugeWithTags(metricName+"_"+bn, tags, bv) } diff --git a/internal/server/receiver/receiver.go b/internal/server/receiver/receiver.go index a5f7abe6..e241339a 100644 --- a/internal/server/receiver/receiver.go +++ b/internal/server/receiver/receiver.go @@ -38,7 +38,7 @@ func init() { histogramRxNames = histogramRx.SubexpNames() } -// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue) +// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue). type logshim struct { logh zerolog.Logger } @@ -79,13 +79,13 @@ func initCGM() error { return nil } -// Flush returns current metrics +// Flush returns current metrics. func Flush() *cgm.Metrics { _ = initCGM() return metrics.FlushMetrics() } -// Parse handles incoming PUT/POST requests +// Parse handles incoming PUT/POST requests. func Parse(id string, data io.Reader) error { if err := initCGM(); err != nil { return err @@ -219,7 +219,7 @@ func parseInt64(metricName string, metric tags.JSONMetric) *int64 { case string: v, err := strconv.ParseInt(metric.Value.(string), 10, 64) if err == nil { - v2 := int64(v) + v2 := v return &v2 } logger.Error(). @@ -245,7 +245,7 @@ func parseUint64(metricName string, metric tags.JSONMetric) *uint64 { case string: v, err := strconv.ParseUint(metric.Value.(string), 10, 64) if err == nil { - v2 := uint64(v) + v2 := v return &v2 } logger.Error(). @@ -273,7 +273,7 @@ func parseFloat(metricName string, metric tags.JSONMetric) (*float64, bool) { case string: v, err := strconv.ParseFloat(metric.Value.(string), 64) if err == nil { - v2 := float64(v) + v2 := v return &v2, false } logger.Error(). @@ -318,7 +318,7 @@ func parseHistogram(metricName string, metric tags.JSONMetric) *[]histSample { Msg("parsing histogram sample") continue } - ret = append(ret, histSample{bucket: false, value: float64(v2)}) + ret = append(ret, histSample{bucket: false, value: v2}) continue } diff --git a/internal/server/receiver/receiver_test.go b/internal/server/receiver/receiver_test.go index 3b72e832..4209eeb8 100644 --- a/internal/server/receiver/receiver_test.go +++ b/internal/server/receiver/receiver_test.go @@ -8,7 +8,6 @@ package receiver import ( "bytes" "encoding/json" - "errors" "fmt" "io/ioutil" "strings" @@ -60,7 +59,7 @@ func TestParse(t *testing.T) { { data := []byte{} r := ioutil.NopCloser(bytes.NewReader(data)) - expectedErr := errors.New("parsing json for test: EOF") + expectedErr := fmt.Errorf("parsing json for test: EOF") //nolint:goerr113 err := Parse("test", r) if err == nil { t.Fatal("expected error") @@ -74,7 +73,7 @@ func TestParse(t *testing.T) { { data := []byte("") r := ioutil.NopCloser(bytes.NewReader(data)) - expectedErr := errors.New("parsing json for test: EOF") + expectedErr := fmt.Errorf("parsing json for test: EOF") //nolint:goerr113 err := Parse("test", r) if err == nil { t.Fatal("expected error") @@ -88,7 +87,7 @@ func TestParse(t *testing.T) { { data := []byte("{") r := ioutil.NopCloser(bytes.NewReader(data)) - expectedErr := errors.New("parsing json for test: unexpected EOF") + expectedErr := fmt.Errorf("parsing json for test: unexpected EOF") //nolint:goerr113 err := Parse("test", r) if err == nil { t.Fatal("expected error") @@ -102,7 +101,7 @@ func TestParse(t *testing.T) { { data := []byte(`{"test": }`) r := ioutil.NopCloser(bytes.NewReader(data)) - expectedErr := errors.New("id:test - offset 10 -- invalid character '}' looking for beginning of value") + expectedErr := fmt.Errorf("id:test - offset 10 -- invalid character '}' looking for beginning of value") //nolint:goerr113 err := Parse("test", r) if err == nil { t.Fatal("expected error") @@ -432,6 +431,7 @@ func TestParseInt32(t *testing.T) { } else { if v == nil { t.Fatal("expected value") + return } if *v != test.Expect { t.Fatalf("expected (%#v) got (%#v)", test.Expect, *v) @@ -468,6 +468,7 @@ func TestParseUint32(t *testing.T) { } else { if v == nil { t.Fatal("expected value") + return } if *v != test.Expect { t.Fatalf("expected (%#v) got (%#v)", test.Expect, *v) @@ -504,6 +505,7 @@ func TestParseInt64(t *testing.T) { } else { if v == nil { t.Fatal("expected value") + return } if *v != test.Expect { t.Fatalf("expected (%#v) got (%#v)", test.Expect, *v) @@ -540,6 +542,7 @@ func TestParseUint64(t *testing.T) { } else { if v == nil { t.Fatal("expected value") + return } if *v != test.Expect { t.Fatalf("expected (%#v) got (%#v)", test.Expect, *v) @@ -581,6 +584,7 @@ func TestParseFloat(t *testing.T) { } else { if v == nil { t.Fatal("expected value") + return } if *v != test.Expect { t.Fatalf("expected (%#v) got (%#v)", test.Expect, *v) @@ -623,6 +627,7 @@ func TestParseHistogram(t *testing.T) { } else { if v == nil { t.Fatal("expected value") + return } if fmt.Sprintf("%v", *v) != fmt.Sprintf("%v", test.Expect) { t.Fatalf("expected (%#v) got (%#v)", test.Expect, *v) diff --git a/internal/server/server.go b/internal/server/server.go index d1d5631a..32bd5f4a 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -48,7 +48,7 @@ type sslServer struct { keyFile string } -// Server defines the listening servers +// Server defines the listening servers. type Server struct { check *check.Check group *errgroup.Group @@ -77,7 +77,7 @@ var ( lastMetricsmu sync.Mutex ) -// New creates a new instance of the listening servers +// New creates a new instance of the listening servers. func New(ctx context.Context, c *check.Check, b *builtins.Builtins, p *plugins.Plugins, ss *statsd.Server) (*Server, error) { g, gctx := errgroup.WithContext(ctx) s := Server{ @@ -163,7 +163,7 @@ func New(ctx context.Context, c *check.Check, b *builtins.Builtins, p *plugins.P if _, serr := os.Stat(ua.String()); serr == nil || !os.IsNotExist(serr) { s.logger.Error().Int("id", idx).Str("socket_file", ua.String()).Msg("already exists") - return nil, fmt.Errorf("Socket server file (%s) exists", ua.String()) + return nil, fmt.Errorf("socket server file (%s) exists", ua.String()) //nolint:goerr113 } ul, err := net.ListenUnix(ua.Network(), ua) @@ -187,15 +187,15 @@ func New(ctx context.Context, c *check.Check, b *builtins.Builtins, p *plugins.P // Initially, this is the first server address. func (s *Server) GetReverseAgentAddress() (string, error) { if len(s.svrHTTP) == 0 { - return "", fmt.Errorf("No listen servers defined") + return "", fmt.Errorf("no listen servers defined") //nolint:goerr113 } return s.svrHTTP[0].address.String(), nil } -// Start main listening server(s) +// Start main listening server(s). func (s *Server) Start() error { if len(s.svrHTTP) == 0 && s.svrHTTPS == nil && len(s.svrSockets) > 0 { - return fmt.Errorf("No servers defined") + return fmt.Errorf("no servers defined") //nolint:goerr113 } s.group.Go(s.startHTTPS) @@ -219,10 +219,10 @@ func (s *Server) Start() error { s.Stop() }() - return s.group.Wait() + return s.group.Wait() //nolint:wrapcheck } -// Stop the servers in an orderly, graceful fashion +// Stop the servers in an orderly, graceful fashion. func (s *Server) Stop() { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() diff --git a/internal/server/server_test.go b/internal/server/server_test.go index e947deca..e34ba478 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -7,7 +7,7 @@ package server import ( "context" - "errors" + "fmt" "path" "regexp" "runtime" @@ -502,7 +502,7 @@ func TestStart(t *testing.T) { if serr == nil { t.Fatal("expected error") } - expected := errors.New("SSL server: tls: failed to find any PEM data in certificate input") + expected := fmt.Errorf("SSL server: tls: failed to find any PEM data in certificate input") //nolint:goerr113 if serr.Error() != expected.Error() { t.Fatalf("expected (%s) got (%s)", expected, serr) } diff --git a/internal/statsd/metrics.go b/internal/statsd/metrics.go index 51c0623c..43d927a1 100644 --- a/internal/statsd/metrics.go +++ b/internal/statsd/metrics.go @@ -19,7 +19,7 @@ import ( "github.com/spf13/viper" ) -// processPacket parses a packet for metrics +// processPacket parses a packet for metrics. func (s *Server) processPacket(pkt []byte) { if len(pkt) == 0 { return @@ -36,7 +36,7 @@ func (s *Server) processPacket(pkt []byte) { } // getMetricDestination determines "where" a metric should be sent (host or group) -// and cleans up the metric name if it matches a host|group prefix +// and cleans up the metric name if it matches a host|group prefix. func (s *Server) getMetricDestination(metricName string) (string, string) { if s.hostPrefix == "" && s.groupPrefix == "" { // no host/group prefixes - send all metrics to host return destHost, metricName @@ -85,7 +85,7 @@ func (s *Server) parseMetric(metric string) error { metricTagSpec := "" if !s.metricRegex.MatchString(metric) { - return fmt.Errorf("invalid metric format '%s', ignoring", metric) + return fmt.Errorf("invalid metric format '%s', ignoring", metric) //nolint:goerr113 } for _, match := range s.metricRegex.FindAllStringSubmatch(metric, -1) { @@ -108,7 +108,7 @@ func (s *Server) parseMetric(metric string) error { } if metricName == "" || metricValue == "" { - return fmt.Errorf("empty metric name (%s) or metric value (%s) - metricRegex failed, check", metricName, metricValue) + return fmt.Errorf("empty metric name (%s) or metric value (%s) - metricRegex failed, check", metricName, metricValue) //nolint:goerr113 } if metricRate != "" { @@ -118,7 +118,7 @@ func (s *Server) parseMetric(metric string) error { } sampleRate = r if sampleRate == 0.0 { - return fmt.Errorf("invalid sample rate %f", sampleRate) + return fmt.Errorf("invalid sample rate %f", sampleRate) //nolint:goerr113 } } @@ -136,7 +136,7 @@ func (s *Server) parseMetric(metric string) error { } if dest == nil { - return fmt.Errorf("invalid metric destination (%s)->(%s)", metric, metricDest) + return fmt.Errorf("invalid metric destination (%s)->(%s)", metric, metricDest) //nolint:goerr113 } // add stream tags to metric name @@ -237,7 +237,7 @@ func (s *Server) parseMetric(metric string) error { case "t": // text (circonus) dest.SetTextWithTags(metricName, metricTags, metricValue) default: - return fmt.Errorf("invalid metric type (%s)", metricType) + return fmt.Errorf("invalid metric type (%s)", metricType) //nolint:goerr113 } return nil diff --git a/internal/statsd/metrics_test.go b/internal/statsd/metrics_test.go index 910d7598..e3ed6fea 100644 --- a/internal/statsd/metrics_test.go +++ b/internal/statsd/metrics_test.go @@ -7,7 +7,7 @@ package statsd import ( "context" - "errors" + "fmt" "testing" "github.com/circonus-labs/circonus-agent/internal/config" @@ -235,11 +235,11 @@ func TestParseMetric(t *testing.T) { {"test:1|ms", nil}, {"test:foo|s", nil}, {"test:bar|t", nil}, - {"invalid-format", errors.New("invalid metric format 'invalid-format', ignoring")}, - {":invalid-no-name|t", errors.New("invalid metric format ':invalid-no-name|t', ignoring")}, - {"invalid-no-value:|t", errors.New("invalid metric format 'invalid-no-value:|t', ignoring")}, - {"invalid-rate:1|c|@t", errors.New("invalid metric format 'invalid-rate:1|c|@t', ignoring")}, - {"test:1.2|c", errors.New(`invalid counter value: strconv.ParseUint: parsing "1.2": invalid syntax`)}, + {"invalid-format", fmt.Errorf("invalid metric format 'invalid-format', ignoring")}, //nolint:goerr113 + {":invalid-no-name|t", fmt.Errorf("invalid metric format ':invalid-no-name|t', ignoring")}, //nolint:goerr113 + {"invalid-no-value:|t", fmt.Errorf("invalid metric format 'invalid-no-value:|t', ignoring")}, //nolint:goerr113 + {"invalid-rate:1|c|@t", fmt.Errorf("invalid metric format 'invalid-rate:1|c|@t', ignoring")}, //nolint:goerr113 + {"test:1.2|c", fmt.Errorf(`invalid counter value: strconv.ParseUint: parsing "1.2": invalid syntax`)}, //nolint:goerr113 {"test:0|c", nil}, {"test:1|c|@.1", nil}, {"test:0|g", nil}, @@ -248,9 +248,9 @@ func TestParseMetric(t *testing.T) { {"test:1.0|g", nil}, {"test:-1.0|g", nil}, {"test:-1|g", nil}, - {"test:1.0.0|g", errors.New(`invalid gauge value: strconv.ParseFloat: parsing "1.0.0": invalid syntax`)}, - {"test:-1-|g", errors.New(`invalid gauge value: strconv.ParseInt: parsing "-1-": invalid syntax`)}, - {"test:1a|g", errors.New(`invalid gauge value: strconv.ParseUint: parsing "1a": invalid syntax`)}, + {"test:1.0.0|g", fmt.Errorf(`invalid gauge value: strconv.ParseFloat: parsing "1.0.0": invalid syntax`)}, //nolint:goerr113 + {"test:-1-|g", fmt.Errorf(`invalid gauge value: strconv.ParseInt: parsing "-1-": invalid syntax`)}, //nolint:goerr113 + {"test:1a|g", fmt.Errorf(`invalid gauge value: strconv.ParseUint: parsing "1a": invalid syntax`)}, //nolint:goerr113 {"test:1|h", nil}, {"test:1|ms", nil}, {"test:1.0|h", nil}, @@ -262,11 +262,11 @@ func TestParseMetric(t *testing.T) { {"test:1|c|#c:v", nil}, {"test:1|c|@.1|#c:v", nil}, {"test:1|c|#c1:v1,c2:v2", nil}, - {"invalid-rate-format:1|c|x", errors.New(`invalid metric format 'invalid-rate-format:1|c|x', ignoring`)}, - {"invalid-tag-format:1|c|c:v", errors.New(`invalid metric format 'invalid-tag-format:1|c|c:v', ignoring`)}, - {"test:1.0a|h", errors.New(`invalid histogram value: strconv.ParseFloat: parsing "1.0a": invalid syntax`)}, - {"test:1.0a|ms", errors.New(`invalid histogram value: strconv.ParseFloat: parsing "1.0a": invalid syntax`)}, - {"test:1|q", errors.New("invalid metric type (q)")}, + {"invalid-rate-format:1|c|x", fmt.Errorf(`invalid metric format 'invalid-rate-format:1|c|x', ignoring`)}, //nolint:goerr113 + {"invalid-tag-format:1|c|c:v", fmt.Errorf(`invalid metric format 'invalid-tag-format:1|c|c:v', ignoring`)}, //nolint:goerr113 + {"test:1.0a|h", fmt.Errorf(`invalid histogram value: strconv.ParseFloat: parsing "1.0a": invalid syntax`)}, //nolint:goerr113 + {"test:1.0a|ms", fmt.Errorf(`invalid histogram value: strconv.ParseFloat: parsing "1.0a": invalid syntax`)}, //nolint:goerr113 + {"test:1|q", fmt.Errorf("invalid metric type (q)")}, //nolint:goerr113 } for _, mt := range mtests { diff --git a/internal/statsd/statsd.go b/internal/statsd/statsd.go index c4fc4fd1..4a833ed5 100644 --- a/internal/statsd/statsd.go +++ b/internal/statsd/statsd.go @@ -30,7 +30,7 @@ import ( "golang.org/x/sync/errgroup" ) -// Server defines a statsd server +// Server defines a statsd server. type Server struct { tcpConnections map[string]*net.TCPConn group *errgroup.Group @@ -71,13 +71,13 @@ type Server struct { const ( maxPacketSize = 1472 - // packetQueueSize = 20000 + // packetQueueSize = 20000. destHost = "host" destGroup = "group" destIgnore = "ignore" ) -// New returns a statsd server definition +// New returns a statsd server definition. func New(ctx context.Context) (*Server, error) { s := Server{ disabled: viper.GetBool(config.KeyStatsdDisabled), @@ -181,7 +181,7 @@ func New(ctx context.Context) (*Server, error) { return &s, nil } -// Start the StatsD service +// Start the StatsD service. func (s *Server) Start() error { if s.disabled { s.logger.Info().Msg("disabled, not starting listener") @@ -236,11 +236,11 @@ func (s *Server) Start() error { } }() - return s.group.Wait() + return s.group.Wait() //nolint:wrapcheck } // Flush *host* metrics only -// NOTE: group metrics flush independently to a different check via circonus-gometrics +// NOTE: group metrics flush independently to a different check via circonus-gometrics. func (s *Server) Flush() *cgm.Metrics { if s.disabled { return nil @@ -256,7 +256,7 @@ func (s *Server) Flush() *cgm.Metrics { return s.hostMetrics.FlushMetrics() } -// startUDP the StatsD UDP listener +// startUDP the StatsD UDP listener. func (s *Server) startUDP() error { if !s.enableUDPListener { return nil @@ -272,7 +272,7 @@ func (s *Server) startUDP() error { return nil } -// startTCP the StatsD TCP listener +// startTCP the StatsD TCP listener. func (s *Server) startTCP() error { if !s.enableTCPListener { return nil @@ -288,7 +288,7 @@ func (s *Server) startTCP() error { return nil } -// initHostMetrics initializes the host metrics circonus-gometrics instance +// initHostMetrics initializes the host metrics circonus-gometrics instance. func (s *Server) initHostMetrics() error { s.hostMetricsmu.Lock() defer s.hostMetricsmu.Unlock() @@ -310,7 +310,7 @@ func (s *Server) initHostMetrics() error { return nil } -// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue) +// logshim is used to satisfy apiclient Logger interface (avoiding ptr receiver issue). type logshim struct { logh zerolog.Logger } @@ -345,12 +345,12 @@ func (s *Server) initGroupMetrics() error { if s.apiCAFile != "" { cert, err := ioutil.ReadFile(s.apiCAFile) if err != nil { - return err + return fmt.Errorf("read file: %w", err) } cp := x509.NewCertPool() if !cp.AppendCertsFromPEM(cert) { - return fmt.Errorf("using api CA cert %#v", cert) + return fmt.Errorf("using api CA cert %#v", cert) //nolint:goerr113 } cmc.CheckManager.API.CACert = cp @@ -367,7 +367,7 @@ func (s *Server) initGroupMetrics() error { return nil } -// udpReader reads packets from the statsd udp listener, adds packets recevied to the queue +// udpReader reads packets from the statsd udp listener, adds packets recevied to the queue. func (s *Server) udpReader(packetCh chan<- []byte) error { for { if s.done() { @@ -388,7 +388,7 @@ func (s *Server) udpReader(packetCh chan<- []byte) error { } } -// tcpHandler reads packets from the statsd tcp listener, adds packets recevied to the queue +// tcpHandler reads packets from the statsd tcp listener, adds packets recevied to the queue. func (s *Server) tcpHandler(packetCh chan<- []byte) error { for { if s.done() { @@ -418,7 +418,7 @@ func (s *Server) tcpHandler(packetCh chan<- []byte) error { } } -// tcpReader reads packets from the statsd tcp listener, adds packets recevied to the queue +// tcpReader reads packets from the statsd tcp listener, adds packets recevied to the queue. func (s *Server) tcpReader(conn *net.TCPConn, packetCh chan<- []byte) error { addr := conn.RemoteAddr().String() defer func() { @@ -446,37 +446,37 @@ func (s *Server) tcpReader(conn *net.TCPConn, packetCh chan<- []byte) error { if errors.As(err, &nerr) && nerr.Timeout() { s.logger.Debug().Err(nerr).Str("remote", addr).Msg("resetting deadline") if derr := conn.SetDeadline(time.Now().Add(10 * time.Second)); derr != nil { - return derr + return fmt.Errorf("set deadline: %w", derr) } continue } - return err + return fmt.Errorf("scanner: %w", err) } } } -// tcpRefuseConnection refuses a tcp client connection and logs the event +// tcpRefuseConnection refuses a tcp client connection and logs the event. func (s *Server) tcpRefuseConnection(conn *net.TCPConn) { conn.Close() s.logger.Warn().Str("remote", conn.RemoteAddr().String()).Msg("max tcp client connections reached, refusing new connection attempt") } -// tcpAddConnection tracks tcp client connections +// tcpAddConnection tracks tcp client connections. func (s *Server) tcpAddConnection(conn *net.TCPConn) { s.Lock() s.tcpConnections[conn.RemoteAddr().String()] = conn s.Unlock() } -// tcpRemoveConnection removes a tracked tcp client connection from tracking list +// tcpRemoveConnection removes a tracked tcp client connection from tracking list. func (s *Server) tcpRemoveConnection(id string) { s.Lock() delete(s.tcpConnections, id) s.Unlock() } -// processor reads the packet queue and processes each packet +// processor reads the packet queue and processes each packet. func (s *Server) processor(packetCh <-chan []byte) error { for { select { @@ -508,7 +508,7 @@ func (s *Server) processor(packetCh <-chan []byte) error { } } -// done checks whether context is done +// done checks whether context is done. func (s *Server) done() bool { select { case <-s.groupCtx.Done(): @@ -525,17 +525,17 @@ func validateStatsdOptions() error { port := viper.GetString(config.KeyStatsdPort) if port == "" { - return fmt.Errorf("invalid StatsD port (empty)") + return fmt.Errorf("invalid StatsD port (empty)") //nolint:goerr113 } if ok, err := regexp.MatchString("^[0-9]+$", port); err != nil { return fmt.Errorf("invalid StatsD port (%s): %w", port, err) } else if !ok { - return fmt.Errorf("invalid StatsD port (%s)", port) + return fmt.Errorf("invalid StatsD port (%s)", port) //nolint:goerr113 } if pnum, err := strconv.ParseUint(port, 10, 32); err != nil { return fmt.Errorf("invalid StatsD port: %w", err) } else if pnum < 1024 || pnum > 65535 { - return fmt.Errorf("invalid StatsD port 1024>%s<65535", port) + return fmt.Errorf("invalid StatsD port 1024>%s<65535", port) //nolint:goerr113 } // can be empty (all metrics go to host) @@ -544,7 +544,7 @@ func validateStatsdOptions() error { hostCat := viper.GetString(config.KeyStatsdHostCategory) if hostCat == "" { - return fmt.Errorf("invalid StatsD host category (empty)") + return fmt.Errorf("invalid StatsD host category (empty)") //nolint:goerr113 } groupCID := viper.GetString(config.KeyStatsdGroupCID) @@ -555,7 +555,7 @@ func validateStatsdOptions() error { if groupCID == "cosi" { cid, err := config.LoadCosiCheckID("group") if err != nil { - return err + return fmt.Errorf("load cosi cid for group: %w", err) } groupCID = cid viper.Set(config.KeyStatsdGroupCID, groupCID) @@ -566,46 +566,46 @@ func validateStatsdOptions() error { return fmt.Errorf("validating StatsD Group Check ID: %w", err) } if !ok { - return fmt.Errorf("invalid StatsD Group Check ID (%s)", groupCID) + return fmt.Errorf("invalid StatsD Group Check ID (%s)", groupCID) //nolint:goerr113 } groupPrefix := viper.GetString(config.KeyStatsdGroupPrefix) if hostPrefix == "" && groupPrefix == "" { - return fmt.Errorf("invalid StatsD host/group prefix (both empty)") + return fmt.Errorf("invalid StatsD host/group prefix (both empty)") //nolint:goerr113 } if hostPrefix == groupPrefix { - return fmt.Errorf("invalid StatsD host/group prefix (same)") + return fmt.Errorf("invalid StatsD host/group prefix (same)") //nolint:goerr113 } counterOp := viper.GetString(config.KeyStatsdGroupCounters) if counterOp == "" { - return fmt.Errorf("invalid StatsD counter operator (empty)") + return fmt.Errorf("invalid StatsD counter operator (empty)") //nolint:goerr113 } if ok, err := regexp.MatchString("^(average|sum)$", counterOp); err != nil { return fmt.Errorf("invalid StatsD counter operator (%s): %w", counterOp, err) } else if !ok { - return fmt.Errorf("invalid StatsD counter operator (%s)", counterOp) + return fmt.Errorf("invalid StatsD counter operator (%s)", counterOp) //nolint:goerr113 } gaugeOp := viper.GetString(config.KeyStatsdGroupGauges) if gaugeOp == "" { - return fmt.Errorf("invalid StatsD gauge operator (empty)") + return fmt.Errorf("invalid StatsD gauge operator (empty)") //nolint:goerr113 } if ok, err := regexp.MatchString("^(average|sum)$", gaugeOp); err != nil { return fmt.Errorf("invalid StatsD gauge operator (%s): %w", gaugeOp, err) } else if !ok { - return fmt.Errorf("invalid StatsD gauge operator (%s)", gaugeOp) + return fmt.Errorf("invalid StatsD gauge operator (%s)", gaugeOp) //nolint:goerr113 } setOp := viper.GetString(config.KeyStatsdGroupSets) if setOp == "" { - return fmt.Errorf("invalid StatsD set operator (empty)") + return fmt.Errorf("invalid StatsD set operator (empty)") //nolint:goerr113 } if ok, err := regexp.MatchString("^(average|sum)$", setOp); err != nil { return fmt.Errorf("invalid StatsD set operator (%s): %w", setOp, err) } else if !ok { - return fmt.Errorf("invalid StatsD set operator (%s)", setOp) + return fmt.Errorf("invalid StatsD set operator (%s)", setOp) //nolint:goerr113 } return nil diff --git a/internal/statsd/statsd_test.go b/internal/statsd/statsd_test.go index 86ec8b01..fc429208 100644 --- a/internal/statsd/statsd_test.go +++ b/internal/statsd/statsd_test.go @@ -7,7 +7,7 @@ package statsd import ( "context" - "errors" + "fmt" "strings" "testing" "time" @@ -39,7 +39,7 @@ func TestNew(t *testing.T) { t.Log("Enabled - no port") { viper.Set(config.KeyStatsdDisabled, false) - expect := errors.New("invalid StatsD port (empty)") + expect := fmt.Errorf("invalid StatsD port (empty)") //nolint:goerr113 _, err := New(context.Background()) if err == nil { t.Fatal("expect error") @@ -54,7 +54,7 @@ func TestNew(t *testing.T) { { viper.Set(config.KeyStatsdDisabled, false) viper.Set(config.KeyStatsdPort, "65125") - expect := errors.New("invalid StatsD host category (empty)") + expect := fmt.Errorf("invalid StatsD host category (empty)") //nolint:goerr113 _, err := New(context.Background()) if err == nil { t.Fatal("expect error") @@ -153,6 +153,7 @@ func TestFlush(t *testing.T) { metrics := s.Flush() if metrics == nil { t.Fatal("expected not nil") + return } if len(*metrics) != 0 { t.Fatalf("expected empty metrics, got (%#v)", metrics) @@ -173,6 +174,7 @@ func TestFlush(t *testing.T) { metrics := s.Flush() if metrics == nil { t.Fatal("expected not nil") + return } if len(*metrics) != 0 { t.Fatalf("expected empty metrics, got (%#v)", metrics) @@ -200,7 +202,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdPort, "") - expectedErr := errors.New("invalid StatsD port (empty)") + expectedErr := fmt.Errorf("invalid StatsD port (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -214,7 +216,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdPort, "abc") - expectedErr := errors.New("invalid StatsD port (abc)") + expectedErr := fmt.Errorf("invalid StatsD port (abc)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -228,7 +230,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdPort, "10") - expectedErr := errors.New("invalid StatsD port 1024>10<65535") + expectedErr := fmt.Errorf("invalid StatsD port 1024>10<65535") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -242,7 +244,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdPort, "70000") - expectedErr := errors.New("invalid StatsD port 1024>70000<65535") + expectedErr := fmt.Errorf("invalid StatsD port 1024>70000<65535") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -258,7 +260,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdHostCategory, "") - expectedErr := errors.New("invalid StatsD host category (empty)") + expectedErr := fmt.Errorf("invalid StatsD host category (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -287,7 +289,7 @@ func TestValidateStatsdOptions(t *testing.T) { if err == nil { t.Fatal("Expected error") } - if !strings.HasPrefix(err.Error(), "unable to access cosi check config: open") { + if !strings.HasPrefix(err.Error(), "load cosi cid for group:") { t.Errorf("unexpected error (%s)", err) } } @@ -296,7 +298,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupCID, "abc") - expectedErr := errors.New("invalid StatsD Group Check ID (abc)") + expectedErr := fmt.Errorf("invalid StatsD Group Check ID (abc)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -309,7 +311,7 @@ func TestValidateStatsdOptions(t *testing.T) { t.Log("Group CID, valid - 123") { viper.Set(config.KeyStatsdGroupCID, "123") - expectedErr := errors.New("invalid StatsD host/group prefix (both empty)") + expectedErr := fmt.Errorf("invalid StatsD host/group prefix (both empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -322,7 +324,7 @@ func TestValidateStatsdOptions(t *testing.T) { t.Log("Group CID, valid - /check_bundle/123") { viper.Set(config.KeyStatsdGroupCID, "/check_bundle/123") - expectedErr := errors.New("invalid StatsD host/group prefix (both empty)") + expectedErr := fmt.Errorf("invalid StatsD host/group prefix (both empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -339,7 +341,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupPrefix, "host.") - expectedErr := errors.New("invalid StatsD host/group prefix (same)") + expectedErr := fmt.Errorf("invalid StatsD host/group prefix (same)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -355,7 +357,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupCounters, "") - expectedErr := errors.New("invalid StatsD counter operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD counter operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -369,7 +371,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupCounters, "multiply") - expectedErr := errors.New("invalid StatsD counter operator (multiply)") + expectedErr := fmt.Errorf("invalid StatsD counter operator (multiply)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -383,7 +385,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupCounters, "sum") - expectedErr := errors.New("invalid StatsD gauge operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD gauge operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -397,7 +399,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupCounters, "average") - expectedErr := errors.New("invalid StatsD gauge operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD gauge operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -411,7 +413,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupGauges, "") - expectedErr := errors.New("invalid StatsD gauge operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD gauge operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -425,7 +427,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupGauges, "multiply") - expectedErr := errors.New("invalid StatsD gauge operator (multiply)") + expectedErr := fmt.Errorf("invalid StatsD gauge operator (multiply)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -439,7 +441,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupGauges, "sum") - expectedErr := errors.New("invalid StatsD set operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD set operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -453,7 +455,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupGauges, "average") - expectedErr := errors.New("invalid StatsD set operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD set operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -467,7 +469,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupSets, "") - expectedErr := errors.New("invalid StatsD set operator (empty)") + expectedErr := fmt.Errorf("invalid StatsD set operator (empty)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") @@ -481,7 +483,7 @@ func TestValidateStatsdOptions(t *testing.T) { { viper.Set(config.KeyStatsdGroupSets, "multiply") - expectedErr := errors.New("invalid StatsD set operator (multiply)") + expectedErr := fmt.Errorf("invalid StatsD set operator (multiply)") //nolint:goerr113 err := validateStatsdOptions() if err == nil { t.Fatal("Expected error") diff --git a/internal/tags/tags.go b/internal/tags/tags.go index 76d2658d..6f648a2a 100644 --- a/internal/tags/tags.go +++ b/internal/tags/tags.go @@ -19,36 +19,36 @@ import ( "github.com/spf13/viper" ) -// Tag aliases cgm's Tag to centralize definition +// Tag aliases cgm's Tag to centralize definition. type Tag = cgm.Tag -// Tags aliases cgm's Tags to centralize definition +// Tags aliases cgm's Tags to centralize definition. type Tags = cgm.Tags -// TaggedMetric definefs a tagged metric +// TaggedMetric definefs a tagged metric. type TaggedMetric struct { Value interface{} `json:"_value"` Tags *Tags `json:"_tags"` Type string `json:"_type"` } -// TaggedMetrics is a list of metrics with tags +// TaggedMetrics is a list of metrics with tags. type TaggedMetrics map[string]TaggedMetric -// JSONMetric defines an individual metric received in JSON +// JSONMetric defines an individual metric received in JSON. type JSONMetric struct { Value interface{} `json:"_value"` Type string `json:"_type"` Tags []string `json:"_tags"` } -// JSONMetrics holds list of JSON metrics received at /write receiver interface +// JSONMetrics holds list of JSON metrics received at /write receiver interface. type JSONMetrics map[string]JSONMetric const ( - // Delimiter defines character separating category from value in a tag e.g. location:london + // Delimiter defines character separating category from value in a tag e.g. location:london. Delimiter = ":" - // Separator defines character separating tags in a list e.g. os:centos,location:sfo + // Separator defines character separating tags in a list e.g. os:centos,location:sfo. Separator = "," replacementChar = "_" @@ -57,13 +57,14 @@ const ( ) var ( - valid = regexp.MustCompile(`^[^:,]+:[^:,]+(,[^:,]+:[^:,]+)*$`) - cleaner = regexp.MustCompile(`[\[\]'"` + "`]") - baseTags *[]string + valid = regexp.MustCompile(`^[^:,]+:[^:,]+(,[^:,]+:[^:,]+)*$`) + cleaner = regexp.MustCompile(`[\[\]'"` + "`]") + baseTags *[]string + errInvalidTagFormat = fmt.Errorf("invalid tag format") ) // GetBaseTags returns the check.tags as a list if check.metric_streamtags is true -// ensuring that all metrics have, at a minimum, the same base set of tags +// ensuring that all metrics have, at a minimum, the same base set of tags. func GetBaseTags() []string { if baseTags != nil { return *baseTags @@ -107,7 +108,7 @@ func GetBaseTags() []string { return *baseTags } -// FromString convert old style tag string spec "cat:val,cat:val,..." into a Tags structure +// FromString convert old style tag string spec "cat:val,cat:val,..." into a Tags structure. func FromString(tags string) Tags { if tags == "" || !valid.MatchString(tags) { return Tags{} @@ -116,7 +117,7 @@ func FromString(tags string) Tags { return FromList(tagList) } -// FromList convert old style list of tags []string{"cat:val","cat:val",...} into a Tags structure +// FromList convert old style list of tags []string{"cat:val","cat:val",...} into a Tags structure. func FromList(tagList []string) Tags { if len(tagList) == 0 { return Tags{} @@ -144,7 +145,7 @@ func PrepStreamTags(tagList string) (string, error) { } if !valid.MatchString(tagList) { - return "", fmt.Errorf("invalid tag format") + return "", errInvalidTagFormat } t := strings.Split(cleaner.ReplaceAllString(tagList, replacementChar), Separator) diff --git a/main.go b/main.go index 8100a256..b85a3dd7 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // -// +build go1.15 +// +build go1.16 package main From 5b821c1c0bef6fa1e0c4fa688fec303fefb8ec90 Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 29 Apr 2021 06:45:57 -0400 Subject: [PATCH 2/7] add: `--check-delete` option add: check bundle config caching --- cmd/root.go | 15 ++ internal/check/api.go | 1 + internal/check/api_mock_test.go | 231 ++++++++++++++++++++++++++- internal/check/bundle/bundle.go | 57 ++++++- internal/check/check.go | 55 +++++++ internal/config/config.go | 4 + internal/config/defaults/defaults.go | 6 + 7 files changed, 363 insertions(+), 6 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 472397be..e04ca214 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1343,6 +1343,21 @@ func init() { } } + { + const ( + key = config.KeyCheckDelete + longOpt = "check-delete" + description = "If agent had write access to etc/ when it created its check, it can delete it with the saved check" + defaultValue = defaults.CheckDelete + ) + + RootCmd.Flags().Bool(longOpt, defaultValue, description) + if err := viper.BindPFlag(key, RootCmd.Flags().Lookup(longOpt)); err != nil { + bindFlagError(longOpt, err) + } + viper.SetDefault(key, defaultValue) + } + // // Hidden, deprecated flags so old configs don't break - the flags are just ignored // diff --git a/internal/check/api.go b/internal/check/api.go index 054443c7..3a90416b 100644 --- a/internal/check/api.go +++ b/internal/check/api.go @@ -21,4 +21,5 @@ type API interface { SearchCheckBundles(searchCriteria *apiclient.SearchQueryType, filterCriteria *apiclient.SearchFilterType) (*[]apiclient.CheckBundle, error) UpdateCheckBundle(cfg *apiclient.CheckBundle) (*apiclient.CheckBundle, error) UpdateCheckBundleMetrics(cfg *apiclient.CheckBundleMetrics) (*apiclient.CheckBundleMetrics, error) + DeleteCheckBundleByCID(cid apiclient.CIDType) (bool, error) } diff --git a/internal/check/api_mock_test.go b/internal/check/api_mock_test.go index 3852d8ba..cf604cdd 100644 --- a/internal/check/api_mock_test.go +++ b/internal/check/api_mock_test.go @@ -1,7 +1,6 @@ -//nolint package check -// Code generated by http://github.com/gojuno/minimock (3.0.6). DO NOT EDIT. +// Code generated by http://github.com/gojuno/minimock (3.0.8). DO NOT EDIT. //go:generate minimock -i github.com/circonus-labs/circonus-agent/internal/check.API -o ./api_mock_test.go @@ -24,6 +23,12 @@ type APIMock struct { beforeCreateCheckBundleCounter uint64 CreateCheckBundleMock mAPIMockCreateCheckBundle + funcDeleteCheckBundleByCID func(cid apiclient.CIDType) (b1 bool, err error) + inspectFuncDeleteCheckBundleByCID func(cid apiclient.CIDType) + afterDeleteCheckBundleByCIDCounter uint64 + beforeDeleteCheckBundleByCIDCounter uint64 + DeleteCheckBundleByCIDMock mAPIMockDeleteCheckBundleByCID + funcFetchBroker func(cid apiclient.CIDType) (bp1 *apiclient.Broker, err error) inspectFuncFetchBroker func(cid apiclient.CIDType) afterFetchBrokerCounter uint64 @@ -89,6 +94,9 @@ func NewAPIMock(t minimock.Tester) *APIMock { m.CreateCheckBundleMock = mAPIMockCreateCheckBundle{mock: m} m.CreateCheckBundleMock.callArgs = []*APIMockCreateCheckBundleParams{} + m.DeleteCheckBundleByCIDMock = mAPIMockDeleteCheckBundleByCID{mock: m} + m.DeleteCheckBundleByCIDMock.callArgs = []*APIMockDeleteCheckBundleByCIDParams{} + m.FetchBrokerMock = mAPIMockFetchBroker{mock: m} m.FetchBrokerMock.callArgs = []*APIMockFetchBrokerParams{} @@ -334,6 +342,222 @@ func (m *APIMock) MinimockCreateCheckBundleInspect() { } } +type mAPIMockDeleteCheckBundleByCID struct { + mock *APIMock + defaultExpectation *APIMockDeleteCheckBundleByCIDExpectation + expectations []*APIMockDeleteCheckBundleByCIDExpectation + + callArgs []*APIMockDeleteCheckBundleByCIDParams + mutex sync.RWMutex +} + +// APIMockDeleteCheckBundleByCIDExpectation specifies expectation struct of the API.DeleteCheckBundleByCID +type APIMockDeleteCheckBundleByCIDExpectation struct { + mock *APIMock + params *APIMockDeleteCheckBundleByCIDParams + results *APIMockDeleteCheckBundleByCIDResults + Counter uint64 +} + +// APIMockDeleteCheckBundleByCIDParams contains parameters of the API.DeleteCheckBundleByCID +type APIMockDeleteCheckBundleByCIDParams struct { + cid apiclient.CIDType +} + +// APIMockDeleteCheckBundleByCIDResults contains results of the API.DeleteCheckBundleByCID +type APIMockDeleteCheckBundleByCIDResults struct { + b1 bool + err error +} + +// Expect sets up expected params for API.DeleteCheckBundleByCID +func (mmDeleteCheckBundleByCID *mAPIMockDeleteCheckBundleByCID) Expect(cid apiclient.CIDType) *mAPIMockDeleteCheckBundleByCID { + if mmDeleteCheckBundleByCID.mock.funcDeleteCheckBundleByCID != nil { + mmDeleteCheckBundleByCID.mock.t.Fatalf("APIMock.DeleteCheckBundleByCID mock is already set by Set") + } + + if mmDeleteCheckBundleByCID.defaultExpectation == nil { + mmDeleteCheckBundleByCID.defaultExpectation = &APIMockDeleteCheckBundleByCIDExpectation{} + } + + mmDeleteCheckBundleByCID.defaultExpectation.params = &APIMockDeleteCheckBundleByCIDParams{cid} + for _, e := range mmDeleteCheckBundleByCID.expectations { + if minimock.Equal(e.params, mmDeleteCheckBundleByCID.defaultExpectation.params) { + mmDeleteCheckBundleByCID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDeleteCheckBundleByCID.defaultExpectation.params) + } + } + + return mmDeleteCheckBundleByCID +} + +// Inspect accepts an inspector function that has same arguments as the API.DeleteCheckBundleByCID +func (mmDeleteCheckBundleByCID *mAPIMockDeleteCheckBundleByCID) Inspect(f func(cid apiclient.CIDType)) *mAPIMockDeleteCheckBundleByCID { + if mmDeleteCheckBundleByCID.mock.inspectFuncDeleteCheckBundleByCID != nil { + mmDeleteCheckBundleByCID.mock.t.Fatalf("Inspect function is already set for APIMock.DeleteCheckBundleByCID") + } + + mmDeleteCheckBundleByCID.mock.inspectFuncDeleteCheckBundleByCID = f + + return mmDeleteCheckBundleByCID +} + +// Return sets up results that will be returned by API.DeleteCheckBundleByCID +func (mmDeleteCheckBundleByCID *mAPIMockDeleteCheckBundleByCID) Return(b1 bool, err error) *APIMock { + if mmDeleteCheckBundleByCID.mock.funcDeleteCheckBundleByCID != nil { + mmDeleteCheckBundleByCID.mock.t.Fatalf("APIMock.DeleteCheckBundleByCID mock is already set by Set") + } + + if mmDeleteCheckBundleByCID.defaultExpectation == nil { + mmDeleteCheckBundleByCID.defaultExpectation = &APIMockDeleteCheckBundleByCIDExpectation{mock: mmDeleteCheckBundleByCID.mock} + } + mmDeleteCheckBundleByCID.defaultExpectation.results = &APIMockDeleteCheckBundleByCIDResults{b1, err} + return mmDeleteCheckBundleByCID.mock +} + +//Set uses given function f to mock the API.DeleteCheckBundleByCID method +func (mmDeleteCheckBundleByCID *mAPIMockDeleteCheckBundleByCID) Set(f func(cid apiclient.CIDType) (b1 bool, err error)) *APIMock { + if mmDeleteCheckBundleByCID.defaultExpectation != nil { + mmDeleteCheckBundleByCID.mock.t.Fatalf("Default expectation is already set for the API.DeleteCheckBundleByCID method") + } + + if len(mmDeleteCheckBundleByCID.expectations) > 0 { + mmDeleteCheckBundleByCID.mock.t.Fatalf("Some expectations are already set for the API.DeleteCheckBundleByCID method") + } + + mmDeleteCheckBundleByCID.mock.funcDeleteCheckBundleByCID = f + return mmDeleteCheckBundleByCID.mock +} + +// When sets expectation for the API.DeleteCheckBundleByCID which will trigger the result defined by the following +// Then helper +func (mmDeleteCheckBundleByCID *mAPIMockDeleteCheckBundleByCID) When(cid apiclient.CIDType) *APIMockDeleteCheckBundleByCIDExpectation { + if mmDeleteCheckBundleByCID.mock.funcDeleteCheckBundleByCID != nil { + mmDeleteCheckBundleByCID.mock.t.Fatalf("APIMock.DeleteCheckBundleByCID mock is already set by Set") + } + + expectation := &APIMockDeleteCheckBundleByCIDExpectation{ + mock: mmDeleteCheckBundleByCID.mock, + params: &APIMockDeleteCheckBundleByCIDParams{cid}, + } + mmDeleteCheckBundleByCID.expectations = append(mmDeleteCheckBundleByCID.expectations, expectation) + return expectation +} + +// Then sets up API.DeleteCheckBundleByCID return parameters for the expectation previously defined by the When method +func (e *APIMockDeleteCheckBundleByCIDExpectation) Then(b1 bool, err error) *APIMock { + e.results = &APIMockDeleteCheckBundleByCIDResults{b1, err} + return e.mock +} + +// DeleteCheckBundleByCID implements API +func (mmDeleteCheckBundleByCID *APIMock) DeleteCheckBundleByCID(cid apiclient.CIDType) (b1 bool, err error) { + mm_atomic.AddUint64(&mmDeleteCheckBundleByCID.beforeDeleteCheckBundleByCIDCounter, 1) + defer mm_atomic.AddUint64(&mmDeleteCheckBundleByCID.afterDeleteCheckBundleByCIDCounter, 1) + + if mmDeleteCheckBundleByCID.inspectFuncDeleteCheckBundleByCID != nil { + mmDeleteCheckBundleByCID.inspectFuncDeleteCheckBundleByCID(cid) + } + + mm_params := &APIMockDeleteCheckBundleByCIDParams{cid} + + // Record call args + mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.mutex.Lock() + mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.callArgs = append(mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.callArgs, mm_params) + mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.mutex.Unlock() + + for _, e := range mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.b1, e.results.err + } + } + + if mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.defaultExpectation.Counter, 1) + mm_want := mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.defaultExpectation.params + mm_got := APIMockDeleteCheckBundleByCIDParams{cid} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmDeleteCheckBundleByCID.t.Errorf("APIMock.DeleteCheckBundleByCID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmDeleteCheckBundleByCID.DeleteCheckBundleByCIDMock.defaultExpectation.results + if mm_results == nil { + mmDeleteCheckBundleByCID.t.Fatal("No results are set for the APIMock.DeleteCheckBundleByCID") + } + return (*mm_results).b1, (*mm_results).err + } + if mmDeleteCheckBundleByCID.funcDeleteCheckBundleByCID != nil { + return mmDeleteCheckBundleByCID.funcDeleteCheckBundleByCID(cid) + } + mmDeleteCheckBundleByCID.t.Fatalf("Unexpected call to APIMock.DeleteCheckBundleByCID. %v", cid) + return +} + +// DeleteCheckBundleByCIDAfterCounter returns a count of finished APIMock.DeleteCheckBundleByCID invocations +func (mmDeleteCheckBundleByCID *APIMock) DeleteCheckBundleByCIDAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmDeleteCheckBundleByCID.afterDeleteCheckBundleByCIDCounter) +} + +// DeleteCheckBundleByCIDBeforeCounter returns a count of APIMock.DeleteCheckBundleByCID invocations +func (mmDeleteCheckBundleByCID *APIMock) DeleteCheckBundleByCIDBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmDeleteCheckBundleByCID.beforeDeleteCheckBundleByCIDCounter) +} + +// Calls returns a list of arguments used in each call to APIMock.DeleteCheckBundleByCID. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmDeleteCheckBundleByCID *mAPIMockDeleteCheckBundleByCID) Calls() []*APIMockDeleteCheckBundleByCIDParams { + mmDeleteCheckBundleByCID.mutex.RLock() + + argCopy := make([]*APIMockDeleteCheckBundleByCIDParams, len(mmDeleteCheckBundleByCID.callArgs)) + copy(argCopy, mmDeleteCheckBundleByCID.callArgs) + + mmDeleteCheckBundleByCID.mutex.RUnlock() + + return argCopy +} + +// MinimockDeleteCheckBundleByCIDDone returns true if the count of the DeleteCheckBundleByCID invocations corresponds +// the number of defined expectations +func (m *APIMock) MinimockDeleteCheckBundleByCIDDone() bool { + for _, e := range m.DeleteCheckBundleByCIDMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.DeleteCheckBundleByCIDMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterDeleteCheckBundleByCIDCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcDeleteCheckBundleByCID != nil && mm_atomic.LoadUint64(&m.afterDeleteCheckBundleByCIDCounter) < 1 { + return false + } + return true +} + +// MinimockDeleteCheckBundleByCIDInspect logs each unmet expectation +func (m *APIMock) MinimockDeleteCheckBundleByCIDInspect() { + for _, e := range m.DeleteCheckBundleByCIDMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to APIMock.DeleteCheckBundleByCID with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.DeleteCheckBundleByCIDMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterDeleteCheckBundleByCIDCounter) < 1 { + if m.DeleteCheckBundleByCIDMock.defaultExpectation.params == nil { + m.t.Error("Expected call to APIMock.DeleteCheckBundleByCID") + } else { + m.t.Errorf("Expected call to APIMock.DeleteCheckBundleByCID with params: %#v", *m.DeleteCheckBundleByCIDMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcDeleteCheckBundleByCID != nil && mm_atomic.LoadUint64(&m.afterDeleteCheckBundleByCIDCounter) < 1 { + m.t.Error("Expected call to APIMock.DeleteCheckBundleByCID") + } +} + type mAPIMockFetchBroker struct { mock *APIMock defaultExpectation *APIMockFetchBrokerExpectation @@ -2212,6 +2436,8 @@ func (m *APIMock) MinimockFinish() { if !m.minimockDone() { m.MinimockCreateCheckBundleInspect() + m.MinimockDeleteCheckBundleByCIDInspect() + m.MinimockFetchBrokerInspect() m.MinimockFetchBrokersInspect() @@ -2253,6 +2479,7 @@ func (m *APIMock) minimockDone() bool { done := true return done && m.MinimockCreateCheckBundleDone() && + m.MinimockDeleteCheckBundleByCIDDone() && m.MinimockFetchBrokerDone() && m.MinimockFetchBrokersDone() && m.MinimockFetchCheckDone() && diff --git a/internal/check/bundle/bundle.go b/internal/check/bundle/bundle.go index 80b4fcb3..963025da 100644 --- a/internal/check/bundle/bundle.go +++ b/internal/check/bundle/bundle.go @@ -222,15 +222,27 @@ func (cb *Bundle) CheckCID(idx uint) (string, error) { } // initCheck initializes the check for the agent. -// 1. fetch a check explicitly provided via CID -// 2. search for a check matching the current system -// 3. create a check for the system if --check-create specified +// 1. load a saved check bundle +// 2. fetch a check explicitly provided via CID +// 3. search for a check matching the current system +// 4. create a check for the system if --check-create specified // if fetched, found, or created - set Check.bundle // otherwise, return an error. func (cb *Bundle) initCheckBundle(cid string, create bool) error { var bundle *apiclient.CheckBundle - // if explicit cid configured, attempt to fetch check bundle using cid + { + // first, try to load a previously saved bundle + // NOTE: takes precedence over configured check bundle cid + b, loaded := cb.loadBundle() + if loaded { + // set cid to loaded cid so bundle can be + // refreshed and verified to be active + cid = b.CID + } + } + + // if explicit cid loaded or configured, attempt to fetch check bundle using cid if cid != "" { b, err := cb.fetchCheckBundle(cid) if err != nil { @@ -294,6 +306,10 @@ func (cb *Bundle) initCheckBundle(cid string, create bool) error { cb.bundle = bundle cb.logger.Info().Str("cid", cb.bundle.CID).Str("name", cb.bundle.DisplayName).Msg("using check bundle") + // try to save the bundle to enable --check-delete + // this will save a created check, an updated check, a found check, etc. + cb.saveBundle(bundle) + return nil } @@ -679,3 +695,36 @@ func (cb *Bundle) updateCheckBundleTags(cfg *apiclient.CheckBundle) (*apiclient. return cfg, nil } + +// saveBundle stores the bundle in a json file in etc/check_bundle.json if it is writeable +// the presence of this file allows --check-delete to work. +func (cb *Bundle) saveBundle(bundle *apiclient.CheckBundle) { + data, err := json.Marshal(bundle) + if err != nil { + cb.logger.Error().Err(err).Msg("marshaling check bundle") + return + } + if err := os.WriteFile(defaults.CheckBundleFile, data, 0600); err != nil { + cb.logger.Error().Err(err).Msg("saving check bundle, --check-delete is disabled") + } +} + +// loadBundle reads a previously saved check bundle and uses it. +func (cb *Bundle) loadBundle() (*apiclient.CheckBundle, bool) { + bundleFile := defaults.CheckBundleFile + var bundle apiclient.CheckBundle + data, err := os.ReadFile(bundleFile) + if err != nil { + if !os.IsNotExist(err) { + cb.logger.Warn().Err(err).Str("bundle_file", bundleFile).Msg("loading check bundle") + } + return nil, false + } + + if err := json.Unmarshal(data, &bundle); err != nil { + cb.logger.Warn().Err(err).Str("bundle_file", bundleFile).Msg("parsing check bundle") + return nil, false + } + + return &bundle, true +} diff --git a/internal/check/check.go b/internal/check/check.go index 0206330f..e3fb976d 100644 --- a/internal/check/check.go +++ b/internal/check/check.go @@ -9,15 +9,18 @@ package check import ( "crypto/tls" "crypto/x509" + "encoding/json" "fmt" "io/ioutil" "net" "net/url" + "os" "sync" "time" "github.com/circonus-labs/circonus-agent/internal/check/bundle" "github.com/circonus-labs/circonus-agent/internal/config" + "github.com/circonus-labs/circonus-agent/internal/config/defaults" "github.com/circonus-labs/go-apiclient" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -182,6 +185,20 @@ func New(apiClient API) (*Check, error) { c.client = apiClient + // + // delete check (if possible) + // + if viper.GetBool(config.KeyCheckDelete) { + if err := c.DeleteCheck(); err != nil { + c.logger.Fatal().Err(err).Msg("--check-delete") + } + c.logger.Info().Msg("check deleted, exiting") + os.Exit(0) + } + + // + // setup check + // b, err := bundle.New(c.client) if err != nil { return nil, fmt.Errorf("new bundle: %w", err) @@ -356,3 +373,41 @@ func (c *Check) loadAPICAfile(file string) *x509.CertPool { } return cp } + +// DeleteCheck will attempt to delete a check bundle created by the agent. +// 1. The `etc/` directory must be writeable by the user running the agent. +// 2. The agent, when creating a check, will save the check object to `etc/check_bundle.json`. +// 3. The agent, when --check-delete is passed, will attempt to read this file and delete the check bundle. +func (c *Check) DeleteCheck() error { + + bundleFile := defaults.CheckBundleFile + if _, err := os.Stat(bundleFile); os.IsNotExist(err) { + c.logger.Error().Str("bundle_file", bundleFile).Msg("not found, unable to delete check") + return fmt.Errorf("unable to delete check bundle: %w", err) + } + + data, err := os.ReadFile(bundleFile) + if err != nil { + c.logger.Error().Err(err).Str("bundle_file", bundleFile).Msg("unable to open") + return fmt.Errorf("unable to delete check bundle: %w", err) + } + var bundle apiclient.CheckBundle + if err := json.Unmarshal(data, &bundle); err != nil { + c.logger.Error().Err(err).Str("bundle_file", bundleFile).Msg("unable to decode file") + return fmt.Errorf("unable to delete check bundle: %w", err) + } + + if _, err := c.client.DeleteCheckBundleByCID(&bundle.CID); err != nil { + c.logger.Error().Err(err).Str("bundle_id", bundle.CID).Msg("unable to delete bundle") + return fmt.Errorf("unable to delete check bundle: %w", err) + } + + // remove the bundle file if check deleted; to avoid trying to use a deleted check if the + // agent were to be re-started...even though this is technically only for automation + if err := os.Remove(bundleFile); err != nil { + c.logger.Error().Err(err).Str("bundle_file", bundleFile).Msg("unable to delete bundle file") + return fmt.Errorf("unable to delete check bundle: %w", err) + } + + return nil +} diff --git a/internal/config/config.go b/internal/config/config.go index a2339ede..6b5b98b6 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -352,6 +352,10 @@ const ( // KeyCheckMetricStreamtags specifies whether to use stream tags (if stream tags are enabled, check tags are added to all metrics by default). KeyCheckMetricStreamtags = "check.metric_streamtags" + // KeyCheckDelete will allow the agent to delete its check if it had write access to etc/ when it created + // its check so that it could save the check definition. + KeyCheckDelete = "check.delete" + // Cluster mode. KeyCluster = "cluster" // Cluster mode enabled. diff --git a/internal/config/defaults/defaults.go b/internal/config/defaults/defaults.go index dc569cce..de967526 100644 --- a/internal/config/defaults/defaults.go +++ b/internal/config/defaults/defaults.go @@ -130,6 +130,9 @@ const ( // CheckTags to use if creating a check (comma separated list). CheckTags = "" + // CheckDelete can delete the created check if the agent had write access to etc/ when it created the check. + CheckDelete = false + // Cluster mode enabled. ClusterEnabled = false // Cluster mode enable builtins (host filesystems must be mounted in container and corresponding @@ -210,6 +213,8 @@ var ( StatsdConf = "" // (e.g. /opt/circonus/agent/etc/statsd.json) CheckType = "" + + CheckBundleFile = "" ) func init() { @@ -236,6 +241,7 @@ func init() { SSLCertFile = filepath.Join(EtcPath, release.NAME+".pem") SSLKeyFile = filepath.Join(EtcPath, release.NAME+".key") CheckMetricFilterFile = filepath.Join(EtcPath, "metric_filters.json") + CheckBundleFile = filepath.Join(EtcPath, "check_bundle.json") CheckTarget, err = os.Hostname() if err != nil { From 2e949217c427cb62a2aeb0bdfeb8edbbacdd4bfb Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 29 Apr 2021 06:46:32 -0400 Subject: [PATCH 3/7] upd: etc owned by agent user for check bundle caching --- package/build.sh | 3 +++ package/rhel/circonus-agent.spec.in | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package/build.sh b/package/build.sh index 13501735..7c477c9e 100755 --- a/package/build.sh +++ b/package/build.sh @@ -482,6 +482,8 @@ make_package() { $RM -f $deb_file fi + chown nobody:nobody $dir_install_agent/etc && chmod 0750 $dir_install_agent/etc + # when snapshots are used, the embedded Version field in the deb needs # to start with a number. fudge it since these are !!ONLY!! for testing. [[ "$agent_version" == "snapshot" ]] && stripped_ver="1.${agent_version}" @@ -508,6 +510,7 @@ make_package() { ;; *) pushd $dir_install >/dev/null + chown nobody:nobody $dir_install_agent/etc && chmod 0750 $dir_install_agent/etc echo "making tgz for $os_name" local pkg="${dir_build}/circonus-agent-${stripped_ver}-1.${os_name}_${os_arch}.tgz" $TAR czf $pkg . diff --git a/package/rhel/circonus-agent.spec.in b/package/rhel/circonus-agent.spec.in index 1fa825f8..73eb5e3d 100644 --- a/package/rhel/circonus-agent.spec.in +++ b/package/rhel/circonus-agent.spec.in @@ -86,7 +86,7 @@ exit 0 %attr(0755, root, root) /etc/init.d/circonus-agent %endif %{app_dir}/CHANGELOG.md -%{app_dir}/etc +%attr(0750,nobody,nobody) %{app_dir}/etc %{app_dir}/LICENSE %{app_dir}/plugins %{app_dir}/README.md From e3a153b9504cd9871fbf22ae7550efbe0819078c Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 29 Apr 2021 06:51:11 -0400 Subject: [PATCH 4/7] upd: dependencies --- go.mod | 12 ++++++------ go.sum | 23 ++++++++++++----------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 3ef470ea..39780c86 100644 --- a/go.mod +++ b/go.mod @@ -5,17 +5,17 @@ require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 github.com/bi-zone/wmi v1.1.4 - github.com/circonus-labs/circonus-gometrics/v3 v3.4.0 - github.com/circonus-labs/go-apiclient v0.7.13 + github.com/circonus-labs/circonus-gometrics/v3 v3.4.2 + github.com/circonus-labs/go-apiclient v0.7.14 github.com/gojuno/minimock/v3 v3.0.8 github.com/google/uuid v1.2.0 github.com/hashicorp/go-hclog v0.10.1 // indirect - github.com/hashicorp/go-retryablehttp v0.6.8 + github.com/hashicorp/go-retryablehttp v0.7.0 github.com/maier/go-appstats v0.2.0 github.com/onsi/ginkgo v1.14.0 // indirect - github.com/pelletier/go-toml v1.8.1 + github.com/pelletier/go-toml v1.9.0 github.com/prometheus/client_model v0.2.0 - github.com/prometheus/common v0.20.0 + github.com/prometheus/common v0.23.0 github.com/rs/zerolog v1.21.0 github.com/shirou/gopsutil v3.21.3+incompatible github.com/spf13/afero v1.2.2 // indirect @@ -25,7 +25,7 @@ require ( github.com/spf13/viper v1.7.1 github.com/tklauser/go-sysconf v0.3.5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 + golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 gopkg.in/ini.v1 v1.51.1 // indirect gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index fa92cc14..56a10f6e 100644 --- a/go.sum +++ b/go.sum @@ -53,10 +53,10 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/circonus-labs/circonus-gometrics/v3 v3.4.0 h1:JoZf3yXK0bPBIxsy5xVCDVbKXIU9JZCWb00IpKs884w= -github.com/circonus-labs/circonus-gometrics/v3 v3.4.0/go.mod h1:7sMszAjkdA5WxSXvZkrUjNt3SbDl5GslB8txoMZD2GQ= -github.com/circonus-labs/go-apiclient v0.7.13 h1:jiZw0DXsP06WxPFvmFNpcYFfQxC0GiYIVzC78lbCVXw= -github.com/circonus-labs/go-apiclient v0.7.13/go.mod h1:RFgkvdYEkimzgu3V2vVYlS1bitjOz1SF6uw109ieNeY= +github.com/circonus-labs/circonus-gometrics/v3 v3.4.2 h1:MWiWBV8cP+B91jlKWmTzFDiWD3b+jRdn2qwhxpL2Erk= +github.com/circonus-labs/circonus-gometrics/v3 v3.4.2/go.mod h1:027648G1D2mmHJPFGYUbEHc58b+bBF1b8dIg2XDHMt4= +github.com/circonus-labs/go-apiclient v0.7.14 h1:SWES4wUaNNCXuQJeKQ5EC+D/eeARFYbPjPMfjWAj+8M= +github.com/circonus-labs/go-apiclient v0.7.14/go.mod h1:RFgkvdYEkimzgu3V2vVYlS1bitjOz1SF6uw109ieNeY= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -175,8 +175,9 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -292,8 +293,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.0 h1:NOd0BRdOKpPf0SxkL3HxSQOG7rNh+4kl6PHcBPFs7Q0= +github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -324,8 +325,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.20.0 h1:pfeDeUdQcIxOMutNjCejsEFp7qeP+/iltHSSmLpE+hU= -github.com/prometheus/common v0.20.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.23.0 h1:GXWvPYuTUenIa+BhOq/x+L/QZzCqASkVRny5KTlPDGM= +github.com/prometheus/common v0.23.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q= 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.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -513,8 +514,8 @@ golang.org/x/sys v0.0.0-20200806060901-a37d78b92225/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0= -golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= From baf5561d78d29354553ef190bacfdc658c2a6c2e Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 29 Apr 2021 06:51:19 -0400 Subject: [PATCH 5/7] upd: lint issue --- internal/builtins/builtins_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/builtins/builtins_test.go b/internal/builtins/builtins_test.go index 4f1a495d..3dfd708c 100644 --- a/internal/builtins/builtins_test.go +++ b/internal/builtins/builtins_test.go @@ -264,7 +264,7 @@ func TestFlush(t *testing.T) { if metrics == nil { t.Fatal("expected metrics") } - if len(*metrics) > 0 { + if len(*metrics) > 0 { //nolint:staticcheck t.Fatalf("expected empty metrics, got %#v", *metrics) } } From 6de1ecc5c677020e9f50348f35a6077a0a3051fa Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 29 Apr 2021 07:21:59 -0400 Subject: [PATCH 6/7] fix: error wrap when nil on verify --- internal/check/broker.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/check/broker.go b/internal/check/broker.go index 40814e27..b34d4d18 100644 --- a/internal/check/broker.go +++ b/internal/check/broker.go @@ -61,7 +61,10 @@ func (c *Check) brokerTLSConfig(reverseURL *url.URL) (*tls.Config, string, error opts.Intermediates.AddCert(cert) } _, err := cs.PeerCertificates[0].Verify(opts) - return fmt.Errorf("verify peer cert: %w", err) + if err != nil { + return fmt.Errorf("verify peer cert: %w", err) + } + return nil }, } @@ -82,6 +85,9 @@ func (c *Check) getBrokerCN(reverseURL *url.URL) (string, error) { cn := "" for _, detail := range c.broker.Details { + if detail.Status != StatusActive { + continue + } // certs are generated against the CN (in theory) // 1. find the right broker instance with matching IP or external hostname // 2. set the tls.Config.ServerName to whatever that instance's CN is currently From 1e29dd80ece38b34025a4acb725bf31bde41166b Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 29 Apr 2021 07:24:27 -0400 Subject: [PATCH 7/7] v2.4.1 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43133ec7..f3683957 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +# v2.4.1 + +* add: `--check-delete` option +* add: check bundle config caching +* upd: etc owned by agent user for check bundle caching +* upd: turn on prerelease (allow time for os specific packages to be built and uploaded) +* fix: fix: error wrap when nil on verify +* upd: verify broker instance is active when setting cn for tls config +* upd: no windows arm +* fix: lint issues +* upd: stricter linting +* upd: lint ver (1.39) +* upd: dependencies + # v2.4.0 * add: simple installer (deprecate cosi)