diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 3a9f75c12..0dc20d1bd 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -1,6 +1,5 @@ --- # This action is synced from https://github.com/prometheus/prometheus -version: 1 name: golangci-lint on: push: @@ -26,11 +25,12 @@ jobs: - name: install Go uses: actions/setup-go@v5 with: - go-version: 1.25.x + go-version: 1.26.x - name: Install snmp_exporter/generator dependencies run: sudo apt-get update && sudo apt-get -y install libsnmp-dev if: github.repository == 'prometheus/snmp_exporter' - name: Lint uses: golangci/golangci-lint-action@v8 with: - version: v2.4.0 + version: v2.12.2 + install-mode: goinstall diff --git a/.golangci.yml b/.golangci.yml index 96487c898..c784b374d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,23 +1,23 @@ --- +version: "2" + linters: enable: - - misspell - - revive - -issues: - exclude-rules: - - path: _test.go - linters: - - errcheck - -linters-settings: - errcheck: - exclude-functions: - # Never check for logger errors. - - (github.com/go-kit/log.Logger).Log - revive: + - misspell + - revive + settings: + errcheck: + exclude-functions: + # Never check for logger errors. + - (github.com/go-kit/log.Logger).Log + revive: + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter + - name: unused-parameter + severity: warning + disabled: true + exclusions: rules: - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter - - name: unused-parameter - severity: warning - disabled: true + - path: _test.go + linters: + - errcheck diff --git a/cmd/postgres_exporter/namespace.go b/cmd/postgres_exporter/namespace.go index 41674007d..693fad035 100644 --- a/cmd/postgres_exporter/namespace.go +++ b/cmd/postgres_exporter/namespace.go @@ -45,12 +45,12 @@ func queryNamespaceMapping(server *Server, namespace string, mapping MetricMapNa if !found { // I've no idea how to avoid this properly at the moment, but this is // an admin tool so you're not injecting SQL right? - rows, err = server.db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) // nolint: gas + rows, err = server.db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) // nolint: gosec } else { rows, err = server.db.Query(query) } if err != nil { - return []prometheus.Metric{}, []error{}, fmt.Errorf("Error running query on database %q: %s %v", server, namespace, err) + return []prometheus.Metric{}, []error{}, fmt.Errorf("error running query on database %q: %s %v", server, namespace, err) } defer rows.Close() // nolint: errcheck diff --git a/cmd/postgres_exporter/pg_setting.go b/cmd/postgres_exporter/pg_setting.go index f162c354a..3cd400f81 100644 --- a/cmd/postgres_exporter/pg_setting.go +++ b/cmd/postgres_exporter/pg_setting.go @@ -42,7 +42,7 @@ func querySettings(ch chan<- prometheus.Metric, server *Server) error { rows, err := server.db.Query(query) if err != nil { - return fmt.Errorf("Error running query on database %q: %s %v", server, namespace, err) + return fmt.Errorf("error running query on database %q: %s %v", server, namespace, err) } defer rows.Close() // nolint: errcheck @@ -50,7 +50,7 @@ func querySettings(ch chan<- prometheus.Metric, server *Server) error { s := &pgSetting{} err = rows.Scan(&s.name, &s.setting, &s.unit, &s.shortDesc, &s.vartype) if err != nil { - return fmt.Errorf("Error retrieving rows on %q: %s %v", server, namespace, err) + return fmt.Errorf("error retrieving rows on %q: %s %v", server, namespace, err) } ch <- s.metric(server.labels) @@ -68,7 +68,7 @@ type pgSetting struct { func (s *pgSetting) metric(labels prometheus.Labels) prometheus.Metric { var ( err error - name = strings.Replace(s.name, ".", "_", -1) + name = strings.ReplaceAll(s.name, ".", "_") unit = s.unit // nolint: ineffassign shortDesc = fmt.Sprintf("Server Parameter: %s", s.name) subsystem = "settings" @@ -120,7 +120,7 @@ func (s *pgSetting) normaliseUnit() (val float64, unit string, err error) { val, err = strconv.ParseFloat(s.setting, 64) if err != nil { - return val, unit, fmt.Errorf("Error converting setting %q value %q to float: %s", s.name, s.setting, err) + return val, unit, fmt.Errorf("error converting setting %q value %q to float: %s", s.name, s.setting, err) } // Units defined in: https://www.postgresql.org/docs/current/static/config-setting.html @@ -132,7 +132,7 @@ func (s *pgSetting) normaliseUnit() (val float64, unit string, err error) { case "B", "kB", "MB", "GB", "TB", "1kB", "2kB", "4kB", "8kB", "16kB", "32kB", "64kB", "16MB", "32MB", "64MB": unit = "bytes" default: - err = fmt.Errorf("Unknown unit for runtime variable: %q", s.unit) + err = fmt.Errorf("unknown unit for runtime variable: %q", s.unit) return } diff --git a/cmd/postgres_exporter/postgres_exporter.go b/cmd/postgres_exporter/postgres_exporter.go index fa34eecc5..0653b6e29 100644 --- a/cmd/postgres_exporter/postgres_exporter.go +++ b/cmd/postgres_exporter/postgres_exporter.go @@ -587,11 +587,11 @@ func checkPostgresVersion(db *sql.DB, server string) (semver.Version, string, er var versionString string err := versionRow.Scan(&versionString) if err != nil { - return semver.Version{}, "", fmt.Errorf("Error scanning version string on %q: %v", server, err) + return semver.Version{}, "", fmt.Errorf("error scanning version string on %q: %v", server, err) } semanticVersion, err := parseVersion(versionString) if err != nil { - return semver.Version{}, "", fmt.Errorf("Error parsing version string on %q: %v", server, err) + return semver.Version{}, "", fmt.Errorf("error parsing version string on %q: %v", server, err) } return semanticVersion, versionString, nil @@ -601,7 +601,7 @@ func checkPostgresVersion(db *sql.DB, server string) (semver.Version, string, er func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, server *Server) error { semanticVersion, versionString, err := checkPostgresVersion(server.db, server.String()) if err != nil { - return fmt.Errorf("Error fetching version string on %q: %v", server, err) + return fmt.Errorf("error fetching version string on %q: %v", server, err) } if !e.disableDefaultMetrics && semanticVersion.LT(lowestSupportedVersion) { diff --git a/cmd/postgres_exporter/probe.go b/cmd/postgres_exporter/probe.go index 5945e07b8..c2d86dff0 100644 --- a/cmd/postgres_exporter/probe.go +++ b/cmd/postgres_exporter/probe.go @@ -91,7 +91,7 @@ func handleProbe(logger log.Logger, excludeDatabases []string) http.HandlerFunc } // Cleanup underlying connections to prevent connection leaks - defer pc.Close() + defer func() { _ = pc.Close() }() // TODO(@sysadmind): Remove the registry.MustRegister() call below and instead handle the collection here. That will allow // for the passing of context, handling of timeouts, and more control over the collection. diff --git a/cmd/postgres_exporter/queries.go b/cmd/postgres_exporter/queries.go index fa0b5c272..9638a2947 100644 --- a/cmd/postgres_exporter/queries.go +++ b/cmd/postgres_exporter/queries.go @@ -266,7 +266,7 @@ func addQueries(content []byte, pgVersion semver.Version, server *Server) error func queryDatabases(server *Server) ([]string, error) { rows, err := server.db.Query("SELECT datname FROM pg_database WHERE datallowconn = true AND datistemplate = false AND datname != current_database()") if err != nil { - return nil, fmt.Errorf("Error retrieving databases: %v", err) + return nil, fmt.Errorf("error retrieving databases: %v", err) } defer rows.Close() // nolint: errcheck diff --git a/collector/collector.go b/collector/collector.go index 121129871..24f988b6f 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -176,7 +176,7 @@ func (p PostgresCollector) Collect(ch chan<- prometheus.Metric) { level.Error(p.logger).Log("msg", "Error opening connection to database", "err", err) return } - defer inst.Close() + defer func() { _ = inst.Close() }() wg := sync.WaitGroup{} wg.Add(len(p.Collectors)) diff --git a/collector/collector_test.go b/collector/collector_test.go index 18101f00e..d3b473b43 100644 --- a/collector/collector_test.go +++ b/collector/collector_test.go @@ -48,15 +48,15 @@ func readMetric(m prometheus.Metric) MetricResult { func sanitizeQuery(q string) string { q = strings.Join(strings.Fields(q), " ") - q = strings.Replace(q, "(", "\\(", -1) - q = strings.Replace(q, "?", "\\?", -1) - q = strings.Replace(q, ")", "\\)", -1) - q = strings.Replace(q, "[", "\\[", -1) - q = strings.Replace(q, "]", "\\]", -1) - q = strings.Replace(q, "{", "\\{", -1) - q = strings.Replace(q, "}", "\\}", -1) - q = strings.Replace(q, "*", "\\*", -1) - q = strings.Replace(q, "^", "\\^", -1) - q = strings.Replace(q, "$", "\\$", -1) + q = strings.ReplaceAll(q, "(", "\\(") + q = strings.ReplaceAll(q, "?", "\\?") + q = strings.ReplaceAll(q, ")", "\\)") + q = strings.ReplaceAll(q, "[", "\\[") + q = strings.ReplaceAll(q, "]", "\\]") + q = strings.ReplaceAll(q, "{", "\\{") + q = strings.ReplaceAll(q, "}", "\\}") + q = strings.ReplaceAll(q, "*", "\\*") + q = strings.ReplaceAll(q, "^", "\\^") + q = strings.ReplaceAll(q, "$", "\\$") return q } diff --git a/collector/instance.go b/collector/instance.go index a365697d6..378808107 100644 --- a/collector/instance.go +++ b/collector/instance.go @@ -38,7 +38,7 @@ func newInstance(dsn string) (*instance, error) { if err != nil { return nil, err } - db.Close() + _ = db.Close() return i, nil } diff --git a/collector/pg_database.go b/collector/pg_database.go index d2c4b206a..566487ba6 100644 --- a/collector/pg_database.go +++ b/collector/pg_database.go @@ -75,7 +75,7 @@ func (c PGDatabaseCollector) Update(ctx context.Context, instance *instance, ch if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() var databases []string diff --git a/collector/pg_database_wraparound.go b/collector/pg_database_wraparound.go index d46270637..b865ddcc1 100644 --- a/collector/pg_database_wraparound.go +++ b/collector/pg_database_wraparound.go @@ -70,7 +70,7 @@ func (c *PGDatabaseWraparoundCollector) Update(ctx context.Context, instance *in if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var datname sql.NullString diff --git a/collector/pg_locks.go b/collector/pg_locks.go index d2c77ccd5..4aaed821d 100644 --- a/collector/pg_locks.go +++ b/collector/pg_locks.go @@ -97,7 +97,7 @@ func (c PGLocksCollector) Update(ctx context.Context, instance *instance, ch cha if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() var datname, mode sql.NullString var count sql.NullInt64 diff --git a/collector/pg_long_running_transactions.go b/collector/pg_long_running_transactions.go index ffd89d5f0..d56d55e05 100644 --- a/collector/pg_long_running_transactions.go +++ b/collector/pg_long_running_transactions.go @@ -66,7 +66,7 @@ func (PGLongRunningTransactionsCollector) Update(ctx context.Context, instance * if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var transactions, ageInSeconds float64 diff --git a/collector/pg_replication_slot.go b/collector/pg_replication_slot.go index 7f1ba003e..642cd9c87 100644 --- a/collector/pg_replication_slot.go +++ b/collector/pg_replication_slot.go @@ -84,7 +84,7 @@ func (PGReplicationSlotCollector) Update(ctx context.Context, instance *instance if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var slotName sql.NullString diff --git a/collector/pg_stat_activity_autovacuum.go b/collector/pg_stat_activity_autovacuum.go index 6cf8cdcec..e54f4db8e 100644 --- a/collector/pg_stat_activity_autovacuum.go +++ b/collector/pg_stat_activity_autovacuum.go @@ -61,7 +61,7 @@ func (PGStatActivityAutovacuumCollector) Update(ctx context.Context, instance *i if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var relname string diff --git a/collector/pg_stat_database.go b/collector/pg_stat_database.go index ea7075303..cd9d2fc29 100644 --- a/collector/pg_stat_database.go +++ b/collector/pg_stat_database.go @@ -250,7 +250,7 @@ func (c *PGStatDatabaseCollector) Update(ctx context.Context, instance *instance if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var datid, datname sql.NullString diff --git a/collector/pg_stat_statements.go b/collector/pg_stat_statements.go index c03e78b92..0257bbfcd 100644 --- a/collector/pg_stat_statements.go +++ b/collector/pg_stat_statements.go @@ -126,7 +126,7 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance, if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var user, datname, queryid sql.NullString var callsTotal, rowsTotal sql.NullInt64 diff --git a/collector/pg_stat_user_tables.go b/collector/pg_stat_user_tables.go index af3822ca8..307dd0f5c 100644 --- a/collector/pg_stat_user_tables.go +++ b/collector/pg_stat_user_tables.go @@ -193,7 +193,7 @@ func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instan if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var datname, schemaname, relname sql.NullString diff --git a/collector/pg_stat_walreceiver.go b/collector/pg_stat_walreceiver.go index db533ab55..2f1e522ef 100644 --- a/collector/pg_stat_walreceiver.go +++ b/collector/pg_stat_walreceiver.go @@ -135,13 +135,13 @@ func (c *PGStatWalReceiverCollector) Update(ctx context.Context, instance *insta query = fmt.Sprintf(pgStatWalReceiverQueryTemplate, "") } - hasFlushedLSNRows.Close() + _ = hasFlushedLSNRows.Close() rows, err := db.QueryContext(ctx, query) if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var upstreamHost, slotName, status sql.NullString var receiveStartLsn, receiveStartTli, flushedLsn, receivedTli, latestEndLsn, upstreamNode sql.NullInt64 diff --git a/collector/pg_statio_user_indexes.go b/collector/pg_statio_user_indexes.go index b5516338d..9ddc52d6c 100644 --- a/collector/pg_statio_user_indexes.go +++ b/collector/pg_statio_user_indexes.go @@ -67,7 +67,7 @@ func (c *PGStatioUserIndexesCollector) Update(ctx context.Context, instance *ins if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var schemaname, relname, indexrelname sql.NullString var idxBlksRead, idxBlksHit sql.NullFloat64 diff --git a/collector/pg_statio_user_tables.go b/collector/pg_statio_user_tables.go index 4315fda0a..a61b72dab 100644 --- a/collector/pg_statio_user_tables.go +++ b/collector/pg_statio_user_tables.go @@ -108,7 +108,7 @@ func (PGStatIOUserTablesCollector) Update(ctx context.Context, instance *instanc if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var datname, schemaname, relname sql.NullString diff --git a/collector/pg_xlog_location.go b/collector/pg_xlog_location.go index 237204f7d..c14e0cd94 100644 --- a/collector/pg_xlog_location.go +++ b/collector/pg_xlog_location.go @@ -69,7 +69,7 @@ func (c PGXlogLocationCollector) Update(ctx context.Context, instance *instance, if err != nil { return err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var bytes float64 diff --git a/collector/probe.go b/collector/probe.go index 4c0f0419b..c2d439e9a 100644 --- a/collector/probe.go +++ b/collector/probe.go @@ -81,7 +81,7 @@ func (pc *ProbeCollector) Collect(ch chan<- prometheus.Metric) { level.Error(pc.logger).Log("msg", "Error opening connection to database", "err", err) return } - defer pc.instance.Close() + defer func() { _ = pc.instance.Close() }() wg := sync.WaitGroup{} wg.Add(len(pc.collectors)) diff --git a/config/config.go b/config/config.go index f67969725..c4c6c37e4 100644 --- a/config/config.go +++ b/config/config.go @@ -79,14 +79,14 @@ func (ch *Handler) ReloadConfig(f string, logger log.Logger) error { yamlReader, err := os.Open(f) if err != nil { - return fmt.Errorf("Error opening config file %q: %s", f, err) + return fmt.Errorf("error opening config file %q: %s", f, err) } - defer yamlReader.Close() + defer func() { _ = yamlReader.Close() }() decoder := yaml.NewDecoder(yamlReader) decoder.KnownFields(true) if err = decoder.Decode(config); err != nil { - return fmt.Errorf("Error parsing config file %q: %s", f, err) + return fmt.Errorf("error parsing config file %q: %s", f, err) } ch.Lock()