GOLANGSTER
A Go linter that checks log messages for style and security issues.
Compatible with go vet and golangci-lint.
Rules
| Rule |
Description |
Example (bad → good) |
| lowercase |
Log message must start with a lowercase letter |
"Starting server" → "starting server" |
| english |
Log message must be in English only |
"Запуск сервера" → "starting server" |
| special-chars |
No emoji, !, ?, or ... in log messages |
"started!🚀" → "started" |
| sensitive |
No sensitive data keywords (password, token, etc.) |
"user password: " + pwd → remove or mask |
Supported loggers
log (standard library)
log/slog (standard library, Go 1.21+)
go.uber.org/zap (*zap.Logger, *zap.SugaredLogger)
Installation
go install github.com/idakhno/golangster/cmd/golangster@latest
Usage
# Build
go build -o golangster ./cmd/golangster/
# Run on a package
go vet -vettool=./golangster ./...
# Run with specific rules disabled
go vet -vettool=./golangster -sensitive=false ./...
As a golangci-lint plugin
Step 1. Build the plugin (requires CGO):
CGO_ENABLED=1 go build -buildmode=plugin -o golangster.so plugin/plugin.go
Step 2. Configure .golangci.yml:
version: "2"
linters:
default: none
enable:
- golangster
linters-settings:
custom:
golangster:
path: ./golangster.so
description: Checks log messages for style and security issues
original-url: github.com/idakhno/golangster
settings:
rules:
lowercase: true
english_only: true
no_special_chars: true
no_sensitive: true
sensitive_keywords:
- password
- token
- secret
- api_key
Note: The plugin and golangci-lint binary must be built with the same Go version and dependency versions.
Check with: go version -m $(which golangci-lint)
Step 3. Run:
golangci-lint run
Flags (standalone mode)
| Flag |
Default |
Description |
-lowercase |
true |
Check that messages start with lowercase |
-english |
true |
Check that messages are in English only |
-special-chars |
true |
Check for emoji and special characters |
-sensitive |
true |
Check for sensitive data keywords |
Configuration (plugin mode)
Settings are passed via .golangci.yml under linters-settings.custom.golangster.settings:
settings:
rules:
lowercase: true
english_only: true
no_special_chars: true
no_sensitive: true
sensitive_keywords:
- password
- token
- myCustomSecret
Examples
import "log/slog"
// BAD — triggers all 4 rules
slog.Info("Starting server!") // uppercase + special char
slog.Error("Ошибка подключения") // non-English
slog.Debug("api_key=" + apiKey) // sensitive data
slog.Warn("loading...") // ellipsis
// GOOD
slog.Info("starting server on port 8080")
slog.Error("connection failed")
slog.Debug("request processed")
slog.Warn("cache miss, fetching from db")
Development
# Run all tests
go test -race ./...
# Run only unit tests for rules
go test -v ./pkg/analyzer/rules/...
# Run integration tests (analysistest)
go test -v ./pkg/analyzer/...
# Build binary
go build -o golangster ./cmd/golangster/
Project structure
golangster/
├── cmd/golangster/ # Standalone binary (go vet -vettool)
├── pkg/analyzer/
│ ├── analyzer.go # Main analyzer (analysis.Analyzer)
│ ├── config.go # Configuration
│ ├── detector.go # Log call detection via AST + type checker
│ └── rules/
│ ├── lowercase.go # Rule 1: lowercase start + SuggestedFix
│ ├── english.go # Rule 2: English only
│ ├── special_chars.go # Rule 3: no emoji/special chars
│ └── sensitive.go # Rule 4: no sensitive data
├── plugin/plugin.go # golangci-lint plugin entry point
└── testdata/src/ # analysistest testdata with // want annotations