Skip to content

alchemmist/loglint

Repository files navigation

loglint

go version license type

loglint is a Go static analyzer that checks log messages for quality and safety issues. It runs as a golangci-lint plugin or as a standalone analyzer (singlechecker).

What it checks

# Rule Description
1 lowercase_start Log messages must start with a lowercase letter (string literals only)
2 english_only Log messages must not contain non-ASCII letters (string literals only; emojis ignored)
3 no_special_chars Log messages must not contain emojis or non-alnum characters (string literals only)
4 no_sensitive_data Looks for sensitive keywords in identifiers in the message expression and in identifiers or string literals in arguments after the message

Supported loggers

  • log/slog with Info/Warn/Error/Debug, *Context, and Log
  • go.uber.org/zap with SugaredLogger (Info/Infof/Infow/...) and Logger (Info/Warn/Error/...)
  • log (standard library) with Print*, Fatal*, and Panic*

The analyzer also recognizes common receiver names like log, logger, l, s, sugar, and zap when deciding how to extract the message argument.

Installation

Build from source

make build

Build the golangci-lint plugin

make plugin

Usage

Standalone CLI

./loglint ./...

Flags:

  • -config /path/to/.loglint.yml
  • -fix (apply suggested fixes)

As a golangci-lint plugin

  1. Build the plugin:
make plugin
  1. Add it to .golangci.yml:
linters-settings:
  custom:
    loglint:
      path: ./loglint.so
      description: "Linter for checking log messages"
      original-url: github.com/alchemmist/loglint

linters:
  enable:
    - loglint
  1. Run:
golangci-lint run

If your golangci-lint version supports analyzer fixes, run it with --fix to apply loglint suggestions.

Configuration

Supported file names:

  • .loglint.yml
  • .loglint.yaml
  • .loglint.json

The analyzer searches the current directory and all parent directories. You can also pass -config to point to a specific file.

Example (YAML)

rules:
  lowercase_start: true
  english_only: true
  no_special_chars: true
  no_sensitive_data: true

patterns:
  sensitive_keywords:
    - password
    - secret
    - token
    - api_key
    - private_key

Example (JSON)

{
  "rules": {
    "lowercase_start": true,
    "english_only": true,
    "no_special_chars": true,
    "no_sensitive_data": true
  },
  "patterns": {
    "sensitive_keywords": ["password", "secret", "token", "api_key", "private_key"]
  }
}

If sensitive_keywords is empty, the default keyword list is used.

Auto-fix

Suggested fixes are provided for:

  • lowercase_start: lowercases the first character
  • no_special_chars: removes emojis and non-alnum characters (collapses extra spaces)

Apply fixes via -fix in the standalone CLI or via golangci-lint --fix if supported.

Notes and limitations

  • Rules 1-3 only run when the log message is a string literal.
  • The sensitive data rule does not scan the literal message text itself. It scans identifiers in the message expression and identifiers or string literals in arguments after the message.

Development

# Run tests
make test

# Run tests with coverage report
make test-cover

# Run vet, formatting checks, golangci-lint, and staticcheck
make check

# Format the codebase (gofmt + gofumpt)
make fmt

# Clean build artifacts and local caches
make clean

Project layout

cmd/           # Standalone CLI entrypoint
pkg/analyzer/  # Analyzer implementation, rules, and config
plugin/        # golangci-lint plugin
testdata/      # Analyzer test fixtures

License

MIT

References

About

Check log messaging in Go code

Resources

License

Stars

Watchers

Forks

Contributors