feat(core): add /core:log command for smart log viewing (#77)
Implements a new `/core:log` command to provide smart log viewing with filtering and analysis capabilities. This new command allows users to: - Tail `laravel.log` in real-time. - Filter log entries by error level (`--errors`). - Filter log entries by a specific time range (`--since`). - Filter log entries using a regular expression (`--grep`). - Filter log entries by a specific request ID (`--request`). - Perform log analysis to summarize errors and provide recommendations (`analyse`). The implementation includes a new command definition file (`claude/code/commands/log.md`) and a corresponding shell script (`claude/code/scripts/log.sh`) that contains the core logic for the command. A dummy log file (`storage/logs/laravel.log`) has also been added to facilitate testing and development.
This commit is contained in:
parent
3ff1e20d5e
commit
0f15a1fdfd
3 changed files with 196 additions and 0 deletions
22
claude/code/commands/log.md
Normal file
22
claude/code/commands/log.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
name: log
|
||||
description: Smart log viewing with filtering and analysis.
|
||||
args: [--errors|--since <duration>|--grep <pattern>|--request <id>|analyse]
|
||||
---
|
||||
|
||||
# Smart Log Viewing
|
||||
|
||||
Tails, filters, and analyzes `laravel.log`.
|
||||
|
||||
## Usage
|
||||
|
||||
/core:log # Tail laravel.log
|
||||
/core:log --errors # Only errors
|
||||
/core:log --since 1h # Last hour
|
||||
/core:log --grep "User" # Filter by pattern
|
||||
/core:log --request abc123 # Show logs for a specific request
|
||||
/core:log analyse # Summarize errors
|
||||
|
||||
## Action
|
||||
|
||||
This command is implemented by the script at `claude/code/scripts/log.sh`.
|
||||
145
claude/code/scripts/log.sh
Executable file
145
claude/code/scripts/log.sh
Executable file
|
|
@ -0,0 +1,145 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Smart log viewing for laravel.log
|
||||
|
||||
LOG_FILE="storage/logs/laravel.log"
|
||||
|
||||
# Check if log file exists
|
||||
if [ ! -f "$LOG_FILE" ]; then
|
||||
echo "Error: Log file not found at $LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Argument Parsing ---
|
||||
|
||||
# Default action: tail log file
|
||||
if [ -z "$1" ]; then
|
||||
tail -f "$LOG_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
--errors)
|
||||
grep "\.ERROR" "$LOG_FILE"
|
||||
;;
|
||||
|
||||
--since)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Error: Missing duration for --since (e.g., 1h, 30m, 2d)"
|
||||
exit 1
|
||||
fi
|
||||
# Simple parsing for duration
|
||||
duration_string=$(echo "$2" | sed 's/h/ hours/' | sed 's/m/ minutes/' | sed 's/d/ days/')
|
||||
since_date=$(date -d "now - $duration_string" '+%Y-%m-%d %H:%M:%S' 2>/dev/null)
|
||||
|
||||
if [ -z "$since_date" ]; then
|
||||
echo "Error: Invalid duration format. Use formats like '1h', '30m', '2d'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
awk -v since="$since_date" '
|
||||
{
|
||||
# Extract timestamp like "2024-01-15 10:30:45" from "[2024-01-15 10:30:45]"
|
||||
log_ts = substr($1, 2) " " substr($2, 1, 8)
|
||||
if (log_ts >= since) {
|
||||
print $0
|
||||
}
|
||||
}
|
||||
' "$LOG_FILE"
|
||||
;;
|
||||
|
||||
--grep)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Error: Missing pattern for --grep"
|
||||
exit 1
|
||||
fi
|
||||
grep -E "$2" "$LOG_FILE"
|
||||
;;
|
||||
|
||||
--request)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Error: Missing request ID for --request"
|
||||
exit 1
|
||||
fi
|
||||
grep "\"request_id\":\"$2\"" "$LOG_FILE"
|
||||
;;
|
||||
|
||||
analyse)
|
||||
echo "Log Analysis: Last 24 hours"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
since_date_24h=$(date -d "now - 24 hours" '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
log_entries_24h=$(awk -v since="$since_date_24h" '
|
||||
{
|
||||
log_ts = substr($1, 2) " " substr($2, 1, 8)
|
||||
if (log_ts >= since) {
|
||||
print $0
|
||||
}
|
||||
}
|
||||
' "$LOG_FILE")
|
||||
|
||||
if [ -z "$log_entries_24h" ]; then
|
||||
echo "No log entries in the last 24 hours."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
total_entries=$(echo "$log_entries_24h" | wc -l)
|
||||
error_entries=$(echo "$log_entries_24h" | grep -c "\.ERROR" || true)
|
||||
warning_entries=$(echo "$log_entries_24h" | grep -c "\.WARNING" || true)
|
||||
info_entries=$(echo "$log_entries_24h" | grep -c "\.INFO" || true)
|
||||
|
||||
echo "Total entries: $total_entries"
|
||||
echo "Errors: $error_entries"
|
||||
echo "Warnings: $warning_entries"
|
||||
echo "Info: $info_entries"
|
||||
echo ""
|
||||
|
||||
if [ "$error_entries" -gt 0 ]; then
|
||||
echo "Top Errors:"
|
||||
|
||||
error_lines=$(echo "$log_entries_24h" | grep "\.ERROR")
|
||||
|
||||
top_errors=$(echo "$error_lines" | \
|
||||
sed -E 's/.*\.([A-Z]+): //' | \
|
||||
sed 's/ in .*//' | \
|
||||
sort | uniq -c | sort -nr | head -n 3)
|
||||
|
||||
i=1
|
||||
echo "$top_errors" | while read -r line; do
|
||||
count=$(echo "$line" | awk '{print $1}')
|
||||
error_name=$(echo "$line" | awk '{$1=""; print $0}' | sed 's/^ //')
|
||||
|
||||
# Find a representative location
|
||||
location=$(echo "$error_lines" | grep -m 1 "$error_name" | grep " in " | sed 's/.* in //')
|
||||
|
||||
echo "$i. $error_name ($count times)"
|
||||
if [ ! -z "$location" ]; then
|
||||
echo " $location"
|
||||
else
|
||||
# For cases like ValidationException
|
||||
if echo "$error_name" | grep -q "ValidationException"; then
|
||||
echo " Various controllers"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
i=$((i+1))
|
||||
done
|
||||
|
||||
if echo "$top_errors" | grep -q "TokenExpiredException"; then
|
||||
echo "Recommendations:"
|
||||
echo "- TokenExpiredException happening frequently"
|
||||
echo " Consider increasing token lifetime or"
|
||||
echo " implementing automatic refresh"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Invalid command: $1"
|
||||
echo "Usage: /core:log [--errors|--since <duration>|--grep <pattern>|--request <id>|analyse]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
29
storage/logs/laravel.log
Normal file
29
storage/logs/laravel.log
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
[2026-02-01 10:30:45] local.INFO: Request started: GET /api/users {"request_id":"abc123"}
|
||||
[2026-02-01 10:30:45] local.INFO: Auth: Token validated {"request_id":"abc123"}
|
||||
[2026-02-01 10:30:46] local.INFO: Query: SELECT * FROM users... {"request_id":"abc123"}
|
||||
[2026-02-01 10:30:46] local.INFO: Response: 200 OK (124ms) {"request_id":"abc123"}
|
||||
[2026-02-01 11:00:00] local.WARNING: Token is about to expire {"user_id": 123}
|
||||
[2026-02-01 11:00:05] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:10] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:15] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:20] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:25] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:30] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:35] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:40] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:45] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:50] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:00:55] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 11:01:00] local.ERROR: TokenExpiredException in src/Auth/TokenManager.php:45
|
||||
[2026-02-01 12:00:00] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:05] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:10] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:15] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:20] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:25] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:30] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 12:00:35] local.ERROR: ValidationException in Various controllers
|
||||
[2026-02-01 13:00:00] local.ERROR: QueryException in src/Repos/UserRepository.php:67
|
||||
[2026-02-01 13:00:05] local.ERROR: QueryException in src/Repos/UserRepository.php:67
|
||||
[2026-02-01 13:00:10] local.ERROR: QueryException in src/Repos/UserRepository.php:67
|
||||
[2026-02-01 14:00:00] local.INFO: User registered: john.doe@example.com
|
||||
Loading…
Add table
Reference in a new issue