diff --git a/.golangci.yml b/.golangci.yml index 75707ba..06f5b22 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,6 +7,7 @@ linters: # not useful - exhaustivestruct - exhaustruct + - goerr113 linters-settings: gci: diff --git a/LICENSE b/LICENSE index e96ac48..24ae015 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Utku Özdemir +Copyright (c) 2024 Utku Özdemir Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/go.mod b/go.mod index b797092..e1bc71d 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,6 @@ module github.com/utkuozdemir/nvidia_gpu_exporter -// renovate: go -go 1.20 +go 1.22 require ( github.com/alecthomas/kingpin/v2 v2.4.0 diff --git a/go.sum b/go.sum index b8b0e85..8a8e307 100644 --- a/go.sum +++ b/go.sum @@ -22,10 +22,13 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -41,6 +44,7 @@ github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrP github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= @@ -76,6 +80,7 @@ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7 google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/internal/exporter/csv.go b/internal/exporter/csv.go index a959cd1..c37597b 100644 --- a/internal/exporter/csv.go +++ b/internal/exporter/csv.go @@ -22,8 +22,6 @@ type Cell[T any] struct { RawValue T } -var ErrFieldCountMismatch = fmt.Errorf("field count mismatch") - func ParseCSVIntoTable(queryResult string, qFields []QField) (Table[string], error) { lines := strings.Split(strings.TrimSpace(queryResult), "\n") titlesLine := lines[0] @@ -46,8 +44,8 @@ func ParseCSVIntoTable(queryResult string, qFields []QField) (Table[string], err rawValues := parseCSVLine(valuesLine) if len(qFields) != len(rFields) { - return Table[string]{}, fmt.Errorf("%w: query fields: %d, returned fields: %d", - ErrFieldCountMismatch, len(qFields), len(rFields)) + return Table[string]{}, fmt.Errorf("field count mismatch: query fields: %d, returned fields: %d", + len(qFields), len(rFields)) } for colIndex, rawValue := range rawValues { diff --git a/internal/exporter/exporter.go b/internal/exporter/exporter.go index 91c7202..b5cf4a1 100644 --- a/internal/exporter/exporter.go +++ b/internal/exporter/exporter.go @@ -34,9 +34,6 @@ const ( ) var ( - ErrUnexpectedQueryField = errors.New("unexpected query field") - ErrParseNumber = errors.New("could not parse number from value") - numericRegex = regexp.MustCompile(`[+-]?(\d*[.])?\d+`) //nolint:gochecknoglobals @@ -221,7 +218,7 @@ func scrape(qFields []QField, nvidiaSmiCommand string, command runCmd) (int, *Ta qFieldsJoined := strings.Join(QFieldSliceToStringSlice(qFields), ",") cmdAndArgs := strings.Fields(nvidiaSmiCommand) - cmdAndArgs = append(cmdAndArgs, fmt.Sprintf("--query-gpu=%s", qFieldsJoined)) + cmdAndArgs = append(cmdAndArgs, "--query-gpu="+qFieldsJoined) cmdAndArgs = append(cmdAndArgs, "--format=csv") var stdout bytes.Buffer @@ -241,8 +238,8 @@ func scrape(qFields []QField, nvidiaSmiCommand string, command runCmd) (int, *Ta exitCode = exitError.ExitCode() } - return exitCode, nil, fmt.Errorf("%w: command failed. code: %d | command: %s | stdout: %s | stderr: %s", - err, exitCode, strings.Join(cmdAndArgs, " "), stdout.String(), stderr.String()) + return exitCode, nil, fmt.Errorf("command failed: code: %d | command: %s | stdout: %s | stderr: %s: %w", + exitCode, strings.Join(cmdAndArgs, " "), stdout.String(), stderr.String(), err) } t, err := ParseCSVIntoTable(strings.TrimSpace(stdout.String()), qFields) @@ -265,7 +262,7 @@ func TransformRawValue(rawValue string, valueMultiplier float64) (float64, error if strings.HasPrefix(trimmed, "0x") { decimal, err := util.HexToDecimal(trimmed) if err != nil { - return 0, fmt.Errorf("%w: %s", err, trimmed) + return 0, fmt.Errorf("failed to transform raw value %q: %w", trimmed, err) } return decimal, nil @@ -294,12 +291,12 @@ func TransformRawValue(rawValue string, valueMultiplier float64) (float64, error func parseSanitizedValueWithBestEffort(sanitizedValue string, valueMultiplier float64) (float64, error) { allNums := numericRegex.FindAllString(sanitizedValue, 2) //nolint:gomnd if len(allNums) != 1 { - return -1, fmt.Errorf("%w: %s", ErrParseNumber, sanitizedValue) + return -1, fmt.Errorf("could not parse number from value: %q", sanitizedValue) } parsed, err := strconv.ParseFloat(allNums[0], floatBitSize) if err != nil { - return -1, fmt.Errorf("failed to parse float: %w", err) + return -1, fmt.Errorf("failed to parse float %q: %w", allNums[0], err) } return parsed * valueMultiplier, nil @@ -359,7 +356,7 @@ func getFallbackValues(qFields []QField) ([]RField, error) { for _, q := range qFields { val, contains := fallbackQFieldToRFieldMap[q] if !contains { - return nil, fmt.Errorf("%w: %s", ErrUnexpectedQueryField, q) + return nil, fmt.Errorf("unexpected query field: %q", q) } rFields[counter] = val diff --git a/internal/exporter/fields.go b/internal/exporter/fields.go index 137ff50..1409f1c 100644 --- a/internal/exporter/fields.go +++ b/internal/exporter/fields.go @@ -21,8 +21,6 @@ const ( ) var ( - ErrNoQueryFields = errors.New("could not extract any query fields") - fieldRegex = regexp.MustCompile(`(?m)\n\s*\n^"([^"]+)"`) //nolint:gochecknoglobals @@ -170,13 +168,13 @@ func ParseAutoQFields(nvidiaSmiCommand string, command runCmd) ([]QField, error) } if err != nil { - return nil, fmt.Errorf("%w: command failed. code: %d | command: %s | stdout: %s | stderr: %s", err, - exitCode, strings.Join(cmdAndArgs, " "), outStr, errStr) + return nil, fmt.Errorf("command failed: code: %d | command: %q | stdout: %q | stderr: %q: %w", + exitCode, strings.Join(cmdAndArgs, " "), outStr, errStr, err) } fields := ExtractQFields(outStr) if fields == nil { - return nil, fmt.Errorf("%w: code: %d | command: %s | stdout: %s | stderr: %s", ErrNoQueryFields, + return nil, fmt.Errorf("could not extract any query fields: code: %d | command: %q | stdout: %q | stderr: %q", exitCode, strings.Join(cmdAndArgs, " "), outStr, errStr) }