- Refactor logger package to use Go's slog for JSON-structured logs - Add configurable log levels (debug, info, warn, error) via config and flags - Integrate logging across commands, git operations, and API client with metrics like timing and sizes - Update README with logging documentation and usage examples - Add global --debug and --verbose flags - Enhance tests for logger initialization, levels, and structured output
124 lines
2.9 KiB
Go
124 lines
2.9 KiB
Go
package logger
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestInit(t *testing.T) {
|
|
// Create temp directory
|
|
tmpDir := t.TempDir()
|
|
oldHome := os.Getenv("HOME")
|
|
os.Setenv("HOME", tmpDir)
|
|
defer os.Setenv("HOME", oldHome)
|
|
|
|
tests := []struct {
|
|
name string
|
|
logLevel string
|
|
}{
|
|
{"default level", "info"},
|
|
{"debug level", "debug"},
|
|
{"warn level", "warn"},
|
|
{"error level", "error"},
|
|
{"invalid level defaults to info", "invalid"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := Init(tt.logLevel)
|
|
if err != nil {
|
|
t.Errorf("Init(%q) unexpected error: %v", tt.logLevel, err)
|
|
}
|
|
|
|
// Check log file was created
|
|
logFile := filepath.Join(tmpDir, ".config", "grokkit", "grokkit.log")
|
|
if _, err := os.Stat(logFile); os.IsNotExist(err) {
|
|
t.Errorf("Log file not created at %s", logFile)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLogging(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
oldHome := os.Getenv("HOME")
|
|
os.Setenv("HOME", tmpDir)
|
|
defer os.Setenv("HOME", oldHome)
|
|
|
|
if err := Init("debug"); err != nil {
|
|
t.Fatalf("Init() failed: %v", err)
|
|
}
|
|
|
|
// Test all log levels with structured fields
|
|
Debug("test debug message", "key", "value")
|
|
Info("test info message", "count", 42)
|
|
Warn("test warn message", "enabled", true)
|
|
Error("test error message", "error", "something went wrong")
|
|
|
|
// Verify log file has content
|
|
logFile := filepath.Join(tmpDir, ".config", "grokkit", "grokkit.log")
|
|
content, err := os.ReadFile(logFile)
|
|
if err != nil {
|
|
t.Errorf("Failed to read log file: %v", err)
|
|
}
|
|
if len(content) == 0 {
|
|
t.Errorf("Log file is empty")
|
|
}
|
|
|
|
// Check for JSON structure (slog uses JSON handler)
|
|
contentStr := string(content)
|
|
if !strings.Contains(contentStr, `"level"`) {
|
|
t.Errorf("Log content doesn't contain JSON level field")
|
|
}
|
|
if !strings.Contains(contentStr, `"msg"`) {
|
|
t.Errorf("Log content doesn't contain JSON msg field")
|
|
}
|
|
}
|
|
|
|
func TestSetLevel(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
oldHome := os.Getenv("HOME")
|
|
os.Setenv("HOME", tmpDir)
|
|
defer os.Setenv("HOME", oldHome)
|
|
|
|
if err := Init("info"); err != nil {
|
|
t.Fatalf("Init() failed: %v", err)
|
|
}
|
|
|
|
// Change level to debug
|
|
SetLevel("debug")
|
|
|
|
// Log at debug level
|
|
Debug("debug after level change", "test", true)
|
|
|
|
// Verify log file has the debug message
|
|
logFile := filepath.Join(tmpDir, ".config", "grokkit", "grokkit.log")
|
|
content, err := os.ReadFile(logFile)
|
|
if err != nil {
|
|
t.Errorf("Failed to read log file: %v", err)
|
|
}
|
|
|
|
if !strings.Contains(string(content), "debug after level change") {
|
|
t.Errorf("Debug message not found after level change")
|
|
}
|
|
}
|
|
|
|
func TestWith(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
oldHome := os.Getenv("HOME")
|
|
os.Setenv("HOME", tmpDir)
|
|
defer os.Setenv("HOME", oldHome)
|
|
|
|
if err := Init("info"); err != nil {
|
|
t.Fatalf("Init() failed: %v", err)
|
|
}
|
|
|
|
// Create logger with context
|
|
contextLogger := With("request_id", "123", "user", "testuser")
|
|
if contextLogger == nil {
|
|
t.Errorf("With() returned nil logger")
|
|
}
|
|
}
|