First off, thank you for considering contributing to DNSMonster! It's people like you that make DNSMonster such a great tool.
- Code of Conduct
- Getting Started
- Development Setup
- How to Contribute
- Coding Standards
- Testing
- Pull Request Process
- Reporting Bugs
- Suggesting Enhancements
This project and everyone participating in it is governed by respect and professionalism. Be kind to others.
- Fork the repository on GitHub
- Clone your fork locally
- Create a new branch for your contribution
- Make your changes
- Push to your fork and submit a pull request
- Go 1.24 or higher
- Git
- Make (optional, for build automation)
# Clone your fork
git clone https://github.com/YOUR_USERNAME/dnsmonster.git
cd dnsmonster
# Add upstream remote
git remote add upstream https://github.com/mosajjal/dnsmonster.git
# Install dependencies
go mod download
# Build the project
go build ./cmd/dnsmonster
# Run tests
go test ./...We welcome many types of contributions:
- Bug fixes: Fix issues found in the code
- New features: Add new functionality
- Documentation: Improve or add documentation
- Tests: Add or improve test coverage
- Performance improvements: Optimize existing code
- Code refactoring: Improve code structure and readability
- Check if there's already an issue for what you want to work on
- For large changes, please open an issue first to discuss
- Make sure you're working on the latest main branch
We follow standard Go conventions:
-
Use
gofmt: All code must be formatted withgofmtgofmt -w . -
Use
goimports: Organize imports properlygoimports -w . -
Run
go vet: Check for common mistakesgo vet ./...
-
Use
golangci-lint: Run comprehensive lintinggolangci-lint run
- Keep functions small and focused (ideally < 50 lines)
- Use meaningful variable and function names
- Add comments for exported functions and complex logic
- Group related code together
- Always check errors: Never ignore errors
- Wrap errors with context: Use
fmt.Errorf("context: %w", err) - Don't panic: Use proper error returns instead of panic()
- Log errors appropriately: Use appropriate log levels
// Good
if err != nil {
return fmt.Errorf("failed to open file %s: %w", filename, err)
}
// Bad
if err != nil {
panic(err)
}Use structured logging with logrus:
log.WithFields(log.Fields{
"component": "output",
"type": "clickhouse",
"batch_size": batchSize,
}).Info("Batch processed successfully")- Add package-level documentation to all packages
- Document all exported functions, types, and constants
- Use complete sentences in comments
- Keep comments up-to-date with code changes
// ProcessDNSPacket extracts DNS information from a raw packet.
// It returns a DNSResult containing parsed data or an error if parsing fails.
func ProcessDNSPacket(data []byte) (DNSResult, error) {
// implementation
}- Write tests for all new code
- Aim for at least 70% code coverage for new features
- Use table-driven tests when appropriate
- Test edge cases and error conditions
func TestFunctionName(t *testing.T) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
{
name: "valid input",
input: "test",
want: "expected",
wantErr: false,
},
// more test cases...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := FunctionName(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("FunctionName() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("FunctionName() = %v, want %v", got, tt.want)
}
})
}
}# Run all tests
go test ./...
# Run tests with coverage
go test ./... -cover
# Run tests with verbose output
go test ./... -v
# Run specific test
go test ./internal/util -run TestMaskIPv4
# Run benchmarks
go test ./... -bench=.Add benchmark tests for performance-critical code:
func BenchmarkFunctionName(b *testing.B) {
// setup
b.ResetTimer()
for i := 0; i < b.N; i++ {
FunctionName()
}
}-
Update tests: Ensure tests pass and add new tests for your changes
go test ./... -
Run linters: Fix any linting issues
golangci-lint run
-
Update documentation: Update relevant documentation
- Update README.md if adding features
- Update inline code documentation
- Update user-facing documentation if applicable
-
Commit messages: Write clear, descriptive commit messages
Fix panic in sentinel output when proxy URL is invalid - Replace panic() with proper error handling - Add error logging with context - Return early on error instead of crashing Fixes #123
Your PR description should include:
- What: Brief description of changes
- Why: Motivation for the changes
- How: Technical approach taken
- Testing: How you tested the changes
- Related Issues: Link to related issues
Example:
## What
Add proper error handling to output modules
## Why
Several output modules use panic() which can crash the entire application.
This PR replaces panic() calls with proper error handling and logging.
## How
- Modified sentinel.go, splunk.go, victorialogs.go
- Added error returns instead of panic
- Added detailed error logging
## Testing
- Added unit tests for error cases
- Manually tested with invalid configuration
- Verified graceful degradation
## Related Issues
Fixes #123
Related to #456- At least one maintainer must approve your PR
- All CI checks must pass
- Code coverage should not decrease
- Address all review comments
- Check if the bug has already been reported
- Check if the bug exists in the latest version
- Collect relevant information (logs, configuration, etc.)
Use the GitHub issue tracker and include:
- Title: Clear, concise description
- Environment:
- DNSMonster version
- Operating system and version
- Go version
- Steps to Reproduce: Detailed steps
- Expected Behavior: What should happen
- Actual Behavior: What actually happens
- Logs: Relevant log output
- Configuration: Relevant configuration settings
- Additional Context: Any other relevant information
- Check if the enhancement has been suggested before
- Consider if it fits the project's scope
- Think about how it benefits other users
Use the GitHub issue tracker and include:
- Title: Clear description of the enhancement
- Problem: What problem does this solve?
- Solution: Proposed solution
- Alternatives: Alternative solutions considered
- Additional Context: Any other relevant information
Feel free to:
- Open a GitHub issue
- Join our community discussions
- Check existing documentation
By contributing, you agree that your contributions will be licensed under the project's GPL-3.0 License.
Thank you for contributing to DNSMonster! 🎉