Developer Guide
Developer guide for contributing to flokbn
flokbn is open source and welcomes contributions. This guide covers flokbn-specific development requirements.
Quick Start
1. Prerequisites
- Go 1.23+ (check:
go version) - staticcheck (install:
go install honnef.co/go/tools/cmd/staticcheck@latest)
2. Clone and Build
git clone https://github.com/YOUR_USERNAME/flokbn.git
cd flokbn/flokbn/src
go mod download
go build -o flokbn .3. Verify Setup
go test ./...
staticcheck ./...
./flokbn --versionPerformance Requirements
flokbn is performance-critical. All changes must maintain or improve these benchmarks:
- Parse Rate: >=1.3M requests/sec
- End-to-end Processing: >=1M requests/sec
- Cluster Detection: <5ms for typical workloads
- Memory: No unbounded growth
See Performance for benchmarks and profiling.
Development Workflow
Making Changes
cd flokbn/src
# 1. Make your changes
# 2. Run tests
go test ./...
# 3. Run benchmarks (REQUIRED for performance-sensitive code)
go test -bench=. -benchmem ./...
# 4. Run static analysis
staticcheck ./...
# 5. Format code
go fmt ./...Running Benchmarks
Critical: Always benchmark before and after performance-related changes.
# Before making changes
go test -bench=. -benchmem ./... > bench-before.txt
# Make your changes
# After changes
go test -bench=. -benchmem ./... > bench-after.txt
# Compare results
diff bench-before.txt bench-after.txtReal-World Performance Test
cd flokbn/src
time go run . static --logfile /var/log/nginx/access.log \
--clusterArgSets 1000,24,32,0.1 \
--clusterArgSets 10000,16,24,0.2 \
--plainExpected performance (1M+ requests):
- Parse Time: ~750ms
- Parse Rate: 1.3M+ requests/sec
- Total Duration: ~1s
Testing
go test ./... # Run all tests
go test -cover ./... # With coverage
go test ./logparser -v # Specific package
go test -race ./... # Race detectorMakefile (Repo Root)
The repo-root Makefile is the canonical local gate:
make test # gofmt check + vet + staticcheck + go test + non-Docker e2e suites
make test-race # go test -race ./...
make test-docker # Docker live e2e suites
make test-all # Full sweep: test + test-race + test-docker
make bench # Package benchmarks
make fmt # gofmt -w .The git pre-commit hook runs the commit-time Go-only subset (gofmt, vet, staticcheck, go test); make test is the fuller sweep including e2e.
E2E Tests
End-to-end tests live in e2e/ and exercise the full binary against generated or live traffic.
cd e2e
make all # Static E2E tests (no Docker required)
make live # Live mode E2E test (requires Docker)
make live-detection # Live mode multi-trie detection test (requires Docker)
make live-firewall # Closed-loop firewall E2E test (requires Docker)
make everything # All of the aboveIndividual targets: static, filters, whitelist-blacklist, live, live-detection, live-firewall.
Code Quality
Run before every commit:
go fmt ./... && go vet ./... && staticcheck ./... && go test ./...Writing Tests
Conventions
- Place tests in
*_test.gofiles - Use table-driven tests
- Test edge cases and error conditions
- Include benchmarks for performance-critical code
Example Test
func TestParseIPAddress(t *testing.T) {
tests := []struct {
name string
input string
expected string
wantErr bool
}{
{"valid IPv4", "192.168.1.1", "192.168.1.1", false},
{"invalid IP", "not-an-ip", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := ParseIPAddress(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("expected error=%v, got error=%v", tt.wantErr, err)
}
if result != tt.expected {
t.Errorf("expected %s, got %s", tt.expected, result)
}
})
}
}Example Benchmark
func BenchmarkParseIPAddress(b *testing.B) {
input := "192.168.1.1"
b.ResetTimer()
for i := 0; i < b.N; i++ {
ParseIPAddress(input)
}
}Pull Request Checklist
- Tests pass:
go test ./... - Benchmarks run (for performance changes)
- No performance regression
- Static analysis passes:
staticcheck ./... - Code formatted:
go fmt ./... - Real-world test passes (if applicable)
- Documentation updated (if needed)
Repository Structure
flokbn/
├── flokbn/src/ # Main Go application
│ ├── analysis/ # Analysis orchestration
│ ├── cidr/ # CIDR parsing utilities
│ ├── cli/ # CLI commands and API
│ ├── config/ # Configuration structs and loading
│ ├── ingestor/ # Static/live mode ingestion
│ ├── iputils/ # IP address utilities
│ ├── jail/ # Ban/jail management
│ ├── logparser/ # Log parsing
│ ├── output/ # Output formatting (JSON, plain, etc.)
│ ├── pools/ # Memory pool management
│ ├── sliding/ # Sliding window for live mode
│ ├── trie/ # IP trie clustering
│ ├── tui/ # Terminal user interface
│ ├── version/ # Version info
│ └── main.go
├── e2e/ # End-to-end test scripts
├── docs/ # Hugo documentation
├── .github/workflows/ # CI/CD
├── .goreleaser.yaml # Release configuration
└── README.mdSee Internals for how these packages interact.
Profiling
CPU Profiling
go test -cpuprofile=cpu.prof -bench=. ./logparser
go tool pprof cpu.profMemory Profiling
go test -memprofile=mem.prof -bench=. ./logparser
go tool pprof mem.profDebugging
Race Detector
go build -race -o flokbn .
./flokbn static --logfile test.log --clusterArgSets 1000,24,32,0.1Delve Debugger
go install github.com/go-delve/delve/cmd/dlv@latest
dlv test ./logparser - -test.run TestParseLogLineCleanup
cd flokbn/src
rm -f flokbn
rm -f *.prof *.out
go clean -cacheContributing Guidelines
- One feature per PR - Keep changes focused
- Maintain performance - Benchmark everything
- Add tests - All new code needs tests
- Document changes - Update docs when needed
- Follow Go conventions - Use
go fmtandstaticcheck
Common Issues
Import errors: go mod tidy && go mod download
Stale test cache: go test -count=1 ./...
staticcheck not found: go install honnef.co/go/tools/cmd/staticcheck@latest and ensure $(go env GOPATH)/bin is in PATH.