From 0f15a1fdfdb5b8742ec9196f81176033c18ebba7 Mon Sep 17 00:00:00 2001 From: Snider Date: Mon, 2 Feb 2026 07:17:59 +0000 Subject: [PATCH] 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. --- claude/code/commands/log.md | 22 ++++++ claude/code/scripts/log.sh | 145 ++++++++++++++++++++++++++++++++++++ storage/logs/laravel.log | 29 ++++++++ 3 files changed, 196 insertions(+) create mode 100644 claude/code/commands/log.md create mode 100755 claude/code/scripts/log.sh create mode 100644 storage/logs/laravel.log diff --git a/claude/code/commands/log.md b/claude/code/commands/log.md new file mode 100644 index 0000000..19c2b63 --- /dev/null +++ b/claude/code/commands/log.md @@ -0,0 +1,22 @@ +--- +name: log +description: Smart log viewing with filtering and analysis. +args: [--errors|--since |--grep |--request |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`. diff --git a/claude/code/scripts/log.sh b/claude/code/scripts/log.sh new file mode 100755 index 0000000..b39cc05 --- /dev/null +++ b/claude/code/scripts/log.sh @@ -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 |--grep |--request |analyse]" + exit 1 + ;; +esac diff --git a/storage/logs/laravel.log b/storage/logs/laravel.log new file mode 100644 index 0000000..406b6b4 --- /dev/null +++ b/storage/logs/laravel.log @@ -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