[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CXC6VH75WC1PCTC9EGYE4R":3,"skill-same:01M6CXC6VH75WC1PCTC9EGYE4R":125},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":55,"commitSha":56,"skillDirectory":57,"forksCount":58,"repositoryHtmlUrl":59,"repositoryHomepageUrl":60,"ownerHtmlUrl":61,"ownerBlogUrl":62,"ownerDescription":63,"updatedAt":64,"install":65,"resources":78},"01M6CXC6VH75WC1PCTC9EGYE4R","log-analyzer",null,"Parse, search, and analyze application logs across formats. Use when debugging from log files, setting up structured logging, analyzing error patterns, correlating events across services, parsing stack traces, or monitoring log output in real time.","albertdobmeyer\u002Fopentrapp","albertdobmeyer","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F116975874?v=4","01M6CXARYAZ30V12S7PSG93R84","Albert Dobmeyer","01M6CXAS2FG5GCXZYN3XBFJQV6",2,"MIT","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Flog-analyzer\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"log analyzer","log","analyze","across","time","patterns","files","up","use","python3","linux","stack","parsing","analyzing","monitoring","logs","search","logging","win32","debugging","2026-11-10 10:12:30",false,"---\nname: log-analyzer\nversion: 1.0.0\ndescription: Parse, search, and analyze application logs across formats. Use when debugging from log files, setting up structured logging, analyzing error patterns, correlating events across services, parsing stack traces, or monitoring log output in real time.\nmetadata: {\"clawdbot\":{\"emoji\":\"?\",\"requires\":{\"anyBins\":[\"grep\",\"awk\",\"jq\",\"python3\"]},\"os\":[\"linux\",\"darwin\",\"win32\"]}}\n---\n\n# Log Analyzer\n\nParse, search, and debug from application logs. Covers plain text logs, structured JSON logs, stack traces, multi-service correlation, and real-time monitoring.\n\n## When to Use\n\n- Debugging application errors from log files\n- Searching logs for specific patterns, errors, or request IDs\n- Parsing and analyzing stack traces\n- Setting up structured logging (JSON) in applications\n- Correlating events across multiple services or log files\n- Monitoring logs in real time during development\n- Generating error frequency reports or summaries\n\n## Quick Search Patterns\n\n### Find errors and exceptions\n\n```bash\n# All errors in a log file\ngrep -i 'error\\|exception\\|fatal\\|panic\\|fail' app.log\n\n# Errors with 3 lines of context\ngrep -i -C 3 'error\\|exception' app.log\n\n# Errors in the last hour (ISO timestamps)\nHOUR_AGO=$(date -u -d '1 hour ago' '+%Y-%m-%dT%H:%M' 2>\u002Fdev\u002Fnull || date -u -v-1H '+%Y-%m-%dT%H:%M')\nawk -v t=\"$HOUR_AGO\" '$0 ~ \u002F^[0-9]{4}-[0-9]{2}-[0-9]{2}T\u002F && $1 >= t' app.log | grep -i 'error'\n\n# Count errors by type\ngrep -oP '(?:Error|Exception): \\K[^\\n]+' app.log | sort | uniq -c | sort -rn | head -20\n\n# HTTP 5xx errors from access logs\nawk '$9 >= 500' access.log\n```\n\n### Search by request or correlation ID\n\n```bash\n# Trace a single request across log entries\ngrep 'req-abc123' app.log\n\n# Across multiple files\ngrep -r 'req-abc123' \u002Fvar\u002Flog\u002Fmyapp\u002F\n\n# Across multiple services (with filename prefix)\ngrep -rH 'correlation-id-xyz' \u002Fvar\u002Flog\u002Fservice-a\u002F \u002Fvar\u002Flog\u002Fservice-b\u002F \u002Fvar\u002Flog\u002Fservice-c\u002F\n```\n\n### Time-range filtering\n\n```bash\n# Between two timestamps (ISO format)\nawk '$0 >= \"2026-02-03T10:00\" && $0 \u003C= \"2026-02-03T11:00\"' app.log\n\n# Last N lines (tail)\ntail -1000 app.log | grep -i error\n\n# Since a specific time (GNU date)\nawk -v start=\"$(date -d '30 minutes ago' '+%Y-%m-%dT%H:%M')\" '$1 >= start' app.log\n```\n\n## JSON \u002F Structured Logs\n\n### Parse with jq\n\n```bash\n# Pretty-print JSON logs\ncat app.log | jq '.'\n\n# Filter by level\ncat app.log | jq 'select(.level == \"error\")'\n\n# Filter by time range\ncat app.log | jq 'select(.timestamp >= \"2026-02-03T10:00:00Z\")'\n\n# Extract specific fields\ncat app.log | jq -r '[.timestamp, .level, .message] | @tsv'\n\n# Count by level\ncat app.log | jq -r '.level' | sort | uniq -c | sort -rn\n\n# Filter by nested field\ncat app.log | jq 'select(.context.userId == \"user-123\")'\n\n# Group errors by message\ncat app.log | jq -r 'select(.level == \"error\") | .message' | sort | uniq -c | sort -rn\n\n# Extract request duration stats\ncat app.log | jq -r 'select(.duration != null) | .duration' | awk '{sum+=$1; count++; if($1>max)max=$1} END {print \"count=\"count, \"avg=\"sum\u002Fcount, \"max=\"max}'\n```\n\n### Parse mixed-format logs (JSON lines mixed with plain text)\n\n```bash\n# Extract only valid JSON lines\nwhile IFS= read -r line; do\n  echo \"$line\" | jq '.' 2>\u002Fdev\u002Fnull && continue\ndone \u003C app.log\n\n# Or with grep for lines starting with {\ngrep '^\\s*{' app.log | jq '.'\n```\n\n## Stack Trace Analysis\n\n### Extract and deduplicate stack traces\n\n```bash\n# Extract Java\u002FKotlin stack traces (starts with Exception\u002FError, followed by \\tat lines)\nawk '\u002FException|Error\u002F{trace=$0; while(getline && \u002F^\\t\u002F) trace=trace\"\\n\"$0; print trace\"\\n---\"}' app.log\n\n# Extract Python tracebacks\nawk '\u002F^Traceback\u002F{p=1} p{print} \u002F^[A-Za-z].*Error\u002F{if(p) print \"---\"; p=0}' app.log\n\n# Extract Node.js stack traces (Error + indented \"at\" lines)\nawk '\u002FError:\u002F{trace=$0; while(getline && \u002F^    at \u002F) trace=trace\"\\n\"$0; print trace\"\\n---\"}' app.log\n\n# Deduplicate: group by root cause (first line of trace)\nawk '\u002FException|Error:\u002F{cause=$0} \u002F^\\tat|^    at \u002F{next} cause{print cause; cause=\"\"}' app.log | sort | uniq -c | sort -rn\n```\n\n### Python traceback parser\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"Parse Python tracebacks from log files and group by root cause.\"\"\"\nimport sys\nimport re\nfrom collections import Counter\n\ndef extract_tracebacks(filepath):\n    tracebacks = []\n    current = []\n    in_trace = False\n\n    with open(filepath) as f:\n        for line in f:\n            if line.startswith('Traceback (most recent call last):'):\n                in_trace = True\n                current = [line.rstrip()]\n            elif in_trace:\n                current.append(line.rstrip())\n                # Exception line ends the traceback\n                if re.match(r'^[A-Za-z]\\w*(Error|Exception|Warning)', line):\n                    tracebacks.append('\\n'.join(current))\n                    in_trace = False\n                    current = []\n    return tracebacks\n\nif __name__ == '__main__':\n    filepath = sys.argv[1] if len(sys.argv) > 1 else '\u002Fdev\u002Fstdin'\n    traces = extract_tracebacks(filepath)\n\n    # Group by exception type and message\n    causes = Counter()\n    for trace in traces:\n        lines = trace.split('\\n')\n        cause = lines[-1] if lines else 'Unknown'\n        causes[cause] += 1\n\n    print(f\"Found {len(traces)} tracebacks, {len(causes)} unique causes:\\n\")\n    for cause, count in causes.most_common(20):\n        print(f\"  {count:4d}x  {cause}\")\n```\n\n## Real-Time Monitoring\n\n### Tail and filter\n\n```bash\n# Follow log file, highlight errors in red\ntail -f app.log | grep --color=always -i 'error\\|warn\\|$'\n\n# Follow and filter to errors only\ntail -f app.log | grep --line-buffered -i 'error\\|exception'\n\n# Follow JSON logs, pretty-print errors\ntail -f app.log | while IFS= read -r line; do\n  level=$(echo \"$line\" | jq -r '.level \u002F\u002F empty' 2>\u002Fdev\u002Fnull)\n  if [ \"$level\" = \"error\" ] || [ \"$level\" = \"fatal\" ]; then\n    echo \"$line\" | jq '.'\n  fi\ndone\n\n# Follow multiple files\ntail -f \u002Fvar\u002Flog\u002Fservice-a\u002Fapp.log \u002Fvar\u002Flog\u002Fservice-b\u002Fapp.log\n\n# Follow with timestamps (useful when log doesn't include them)\ntail -f app.log | while IFS= read -r line; do\n  echo \"$(date '+%H:%M:%S') $line\"\ndone\n```\n\n### Watch for specific patterns and alert\n\n```bash\n# Beep on error (terminal bell)\ntail -f app.log | grep --line-buffered -i 'error' | while read line; do\n  echo -e \"\\a$line\"\ndone\n\n# Count errors per minute\ntail -f app.log | grep --line-buffered -i 'error' | while read line; do\n  echo \"$(date '+%Y-%m-%d %H:%M') ERROR\"\ndone | uniq -c\n```\n\n## Log Format Parsing\n\n### Common access log (Apache\u002FNginx)\n\n```bash\n# Parse fields: IP, date, method, path, status, size\nawk '{print $1, $9, $7}' access.log\n\n# Top IPs by request count\nawk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20\n\n# Top paths by request count\nawk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20\n\n# Slow requests (response time in last field, microseconds)\nawk '{if ($NF > 1000000) print $0}' access.log\n\n# Requests per minute\nawk '{split($4,a,\":\"); print a[1]\":\"a[2]\":\"a[3]}' access.log | uniq -c\n\n# Status code distribution\nawk '{print $9}' access.log | sort | uniq -c | sort -rn\n\n# 4xx and 5xx with paths\nawk '$9 >= 400 {print $9, $7}' access.log | sort | uniq -c | sort -rn | head -20\n```\n\n### Custom delimited logs\n\n```bash\n# Pipe-delimited: timestamp|level|service|message\nawk -F'|' '{print $2, $3, $4}' app.log\n\n# Tab-delimited\nawk -F'\\t' '$2 == \"ERROR\" {print $1, $4}' app.log\n\n# CSV logs\npython3 -c \"\nimport csv, sys\nwith open(sys.argv[1]) as f:\n    for row in csv.DictReader(f):\n        if row.get('level') == 'error':\n            print(f\\\"{row['timestamp']} {row['message']}\\\")\n\" app.csv\n```\n\n## Setting Up Structured Logging\n\n### Node.js (pino — fast JSON logger)\n\n```javascript\n\u002F\u002F npm install pino\nconst pino = require('pino');\nconst logger = pino({\n  level: process.env.LOG_LEVEL || 'info',\n  \u002F\u002F Add standard fields to every log line\n  base: { service: 'my-api', version: '1.2.0' },\n});\n\n\u002F\u002F Usage\nlogger.info({ userId: 'u123', action: 'login' }, 'User logged in');\nlogger.error({ err, requestId: req.id }, 'Request failed');\n\n\u002F\u002F Output: {\"level\":30,\"time\":1706900000000,\"service\":\"my-api\",\"userId\":\"u123\",\"action\":\"login\",\"msg\":\"User logged in\"}\n\n\u002F\u002F Child logger with bound context\nconst reqLogger = logger.child({ requestId: req.id, userId: req.user?.id });\nreqLogger.info('Processing order');\nreqLogger.error({ err }, 'Order failed');\n```\n\n### Python (structlog)\n\n```python\n# pip install structlog\nimport structlog\n\nstructlog.configure(\n    processors=[\n        structlog.processors.TimeStamper(fmt=\"iso\"),\n        structlog.processors.add_log_level,\n        structlog.processors.JSONRenderer(),\n    ],\n)\nlogger = structlog.get_logger(service=\"my-api\")\n\n# Usage\nlogger.info(\"user_login\", user_id=\"u123\", ip=\"1.2.3.4\")\nlogger.error(\"request_failed\", request_id=\"req-abc\", error=str(e))\n\n# Output: {\"event\":\"user_login\",\"user_id\":\"u123\",\"ip\":\"1.2.3.4\",\"level\":\"info\",\"timestamp\":\"2026-02-03T12:00:00Z\",\"service\":\"my-api\"}\n```\n\n### Go (zerolog)\n\n```go\nimport (\n    \"os\"\n    \"github.com\u002Frs\u002Fzerolog\"\n    \"github.com\u002Frs\u002Fzerolog\u002Flog\"\n)\n\nfunc init() {\n    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix\n    log.Logger = zerolog.New(os.Stdout).With().\n        Timestamp().\n        Str(\"service\", \"my-api\").\n        Logger()\n}\n\n\u002F\u002F Usage\nlog.Info().Str(\"userId\", \"u123\").Msg(\"User logged in\")\nlog.Error().Err(err).Str(\"requestId\", reqID).Msg(\"Request failed\")\n```\n\n## Error Pattern Reports\n\n### Generate error frequency report\n\n```bash\n#!\u002Fbin\u002Fbash\n# error-report.sh - Summarize errors from a log file\nLOG=\"${1:?Usage: error-report.sh \u003Clogfile>}\"\n\necho \"=== Error Report: $(basename \"$LOG\") ===\"\necho \"Generated: $(date -u '+%Y-%m-%dT%H:%M:%SZ')\"\necho \"\"\n\ntotal=$(wc -l \u003C \"$LOG\")\nerrors=$(grep -ci 'error\\|exception\\|fatal' \"$LOG\")\nwarns=$(grep -ci 'warn' \"$LOG\")\n\necho \"Total lines:  $total\"\necho \"Errors:       $errors\"\necho \"Warnings:     $warns\"\necho \"\"\n\necho \"--- Top 15 Error Messages ---\"\ngrep -i 'error\\|exception' \"$LOG\" | \\\n  sed 's\u002F^[0-9TZ:.+\\-]* \u002F\u002F' | \\\n  sed 's\u002F\\b[0-9a-f]\\{8,\\}\\b\u002FID\u002Fg' | \\\n  sed 's\u002F[0-9]\\{1,\\}\u002FN\u002Fg' | \\\n  sort | uniq -c | sort -rn | head -15\necho \"\"\n\necho \"--- Errors Per Hour ---\"\ngrep -i 'error\\|exception' \"$LOG\" | \\\n  grep -oP '\\d{4}-\\d{2}-\\d{2}T\\d{2}' | \\\n  sort | uniq -c\necho \"\"\n\necho \"--- First Occurrence of Each Error Type ---\"\ngrep -i 'error\\|exception' \"$LOG\" | \\\n  sed 's\u002F^[0-9TZ:.+\\-]* \u002F\u002F' | \\\n  sort -u | head -10\n```\n\n### JSON log error report with Python\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"Generate error summary from JSON log files.\"\"\"\nimport json\nimport sys\nfrom collections import Counter, defaultdict\nfrom datetime import datetime\n\ndef analyze_logs(filepath):\n    errors = []\n    levels = Counter()\n    errors_by_hour = defaultdict(int)\n\n    with open(filepath) as f:\n        for line in f:\n            try:\n                entry = json.loads(line.strip())\n            except (json.JSONDecodeError, ValueError):\n                continue\n\n            level = entry.get('level', entry.get('severity', '')).lower()\n            levels[level] += 1\n\n            if level in ('error', 'fatal', 'critical'):\n                msg = entry.get('message', entry.get('msg', entry.get('event', 'unknown')))\n                ts = entry.get('timestamp', entry.get('time', ''))\n                errors.append({'message': msg, 'timestamp': ts, 'entry': entry})\n\n                # Group by hour\n                try:\n                    hour = ts[:13]  # \"2026-02-03T12\"\n                    errors_by_hour[hour] += 1\n                except (TypeError, IndexError):\n                    pass\n\n    # Group errors by message\n    error_counts = Counter(e['message'] for e in errors)\n\n    print(f\"=== Log Analysis: {filepath} ===\\n\")\n    print(\"Level distribution:\")\n    for level, count in levels.most_common():\n        print(f\"  {level:10s}  {count}\")\n\n    print(f\"\\nTotal errors: {len(errors)}\")\n    print(f\"Unique error messages: {len(error_counts)}\\n\")\n\n    print(\"Top 15 errors:\")\n    for msg, count in error_counts.most_common(15):\n        print(f\"  {count:4d}x  {msg[:100]}\")\n\n    if errors_by_hour:\n        print(\"\\nErrors by hour:\")\n        for hour in sorted(errors_by_hour):\n            bar = '#' * min(errors_by_hour[hour], 50)\n            print(f\"  {hour}  {errors_by_hour[hour]:4d}  {bar}\")\n\nif __name__ == '__main__':\n    analyze_logs(sys.argv[1])\n```\n\n## Multi-Service Log Correlation\n\n### Merge and sort logs from multiple services\n\n```bash\n# Merge multiple log files, sort by timestamp\nsort -m -t'T' -k1,1 service-a.log service-b.log service-c.log > merged.log\n\n# If files aren't individually sorted, use full sort\nsort -t'T' -k1,1 service-*.log > merged.log\n\n# Merge JSON logs, add source field\nfor f in service-*.log; do\n  service=$(basename \"$f\" .log)\n  jq --arg svc \"$service\" '. + {source: $svc}' \"$f\"\ndone | jq -s 'sort_by(.timestamp)[]'\n```\n\n### Trace a request across services\n\n```bash\n# Find all log entries for a correlation\u002Frequest ID across all services\nREQUEST_ID=\"req-abc-123\"\ngrep -rH \"$REQUEST_ID\" \u002Fvar\u002Flog\u002Fservices\u002F | sort -t: -k2\n\n# With JSON logs\nfor f in \u002Fvar\u002Flog\u002Fservices\u002F*.log; do\n  jq --arg rid \"$REQUEST_ID\" 'select(.requestId == $rid or .correlationId == $rid)' \"$f\" 2>\u002Fdev\u002Fnull\ndone | jq -s 'sort_by(.timestamp)[]'\n```\n\n## Log Rotation and Large Files\n\n### Working with rotated\u002Fcompressed logs\n\n```bash\n# Search across rotated logs (including .gz)\nzgrep -i 'error' \u002Fvar\u002Flog\u002Fapp.log*\n\n# Search today's and yesterday's logs\nzgrep -i 'error' \u002Fvar\u002Flog\u002Fapp.log \u002Fvar\u002Flog\u002Fapp.log.1\n\n# Decompress, filter, and recompress\nzcat app.log.3.gz | grep 'ERROR' | gzip > errors-day3.gz\n```\n\n### Sampling large files\n\n```bash\n# Random sample of 1000 lines\nshuf -n 1000 huge.log > sample.log\n\n# Every 100th line\nawk 'NR % 100 == 0' huge.log > sample.log\n\n# First and last 500 lines\n{ head -500 huge.log; echo \"--- TRUNCATED ---\"; tail -500 huge.log; } > excerpt.log\n```\n\n## Tips\n\n- Always search for a **request ID or correlation ID** first — it narrows the haystack faster than timestamps or error messages.\n- Use `--line-buffered` with `grep` when piping from `tail -f` so output isn't delayed by buffering.\n- Normalize IDs and numbers before grouping errors (`sed 's\u002F[0-9a-f]\\{8,\\}\u002FID\u002Fg'`) to collapse duplicates that differ only by ID.\n- For JSON logs, `jq` is indispensable. Install it if it's not available: `apt install jq` \u002F `brew install jq`.\n- Structured logging (JSON) is always worth the setup cost. It makes every analysis task easier: filtering, grouping, correlation, and alerting all become `jq` one-liners.\n- When debugging a production issue: get the **time window** and **affected user\u002Frequest ID** first, then filter logs to that scope before reading anything.\n- `awk` is faster than `grep | sort | uniq -c` pipelines for large files. Use it for counting and aggregation.\n","# Log Analyzer\n\nParse, search, and debug from application logs. Covers plain text logs, structured JSON logs, stack traces, multi-service correlation, and real-time monitoring.\n\n## When to Use\n\n- Debugging application errors from log files\n- Searching logs for specific patterns, errors, or request IDs\n- Parsing and analyzing stack traces\n- Setting up structured logging (JSON) in applications\n- Correlating events across multiple services or log files\n- Monitoring logs in real time during development\n- Generating error frequency reports or summaries\n\n## Quick Search Patterns\n\n### Find errors and exceptions\n\n```bash\n# All errors in a log file\ngrep -i 'error\\|exception\\|fatal\\|panic\\|fail' app.log\n\n# Errors with 3 lines of context\ngrep -i -C 3 'error\\|exception' app.log\n\n# Errors in the last hour (ISO timestamps)\nHOUR_AGO=$(date -u -d '1 hour ago' '+%Y-%m-%dT%H:%M' 2>\u002Fdev\u002Fnull || date -u -v-1H '+%Y-%m-%dT%H:%M')\nawk -v t=\"$HOUR_AGO\" '$0 ~ \u002F^[0-9]{4}-[0-9]{2}-[0-9]{2}T\u002F && $1 >= t' app.log | grep -i 'error'\n\n# Count errors by type\ngrep -oP '(?:Error|Exception): \\K[^\\n]+' app.log | sort | uniq -c | sort -rn | head -20\n\n# HTTP 5xx errors from access logs\nawk '$9 >= 500' access.log\n```\n\n### Search by request or correlation ID\n\n```bash\n# Trace a single request across log entries\ngrep 'req-abc123' app.log\n\n# Across multiple files\ngrep -r 'req-abc123' \u002Fvar\u002Flog\u002Fmyapp\u002F\n\n# Across multiple services (with filename prefix)\ngrep -rH 'correlation-id-xyz' \u002Fvar\u002Flog\u002Fservice-a\u002F \u002Fvar\u002Flog\u002Fservice-b\u002F \u002Fvar\u002Flog\u002Fservice-c\u002F\n```\n\n### Time-range filtering\n\n```bash\n# Between two timestamps (ISO format)\nawk '$0 >= \"2026-02-03T10:00\" && $0 \u003C= \"2026-02-03T11:00\"' app.log\n\n# Last N lines (tail)\ntail -1000 app.log | grep -i error\n\n# Since a specific time (GNU date)\nawk -v start=\"$(date -d '30 minutes ago' '+%Y-%m-%dT%H:%M')\" '$1 >= start' app.log\n```\n\n## JSON \u002F Structured Logs\n\n### Parse with jq\n\n```bash\n# Pretty-print JSON logs\ncat app.log | jq '.'\n\n# Filter by level\ncat app.log | jq 'select(.level == \"error\")'\n\n# Filter by time range\ncat app.log | jq 'select(.timestamp >= \"2026-02-03T10:00:00Z\")'\n\n# Extract specific fields\ncat app.log | jq -r '[.timestamp, .level, .message] | @tsv'\n\n# Count by level\ncat app.log | jq -r '.level' | sort | uniq -c | sort -rn\n\n# Filter by nested field\ncat app.log | jq 'select(.context.userId == \"user-123\")'\n\n# Group errors by message\ncat app.log | jq -r 'select(.level == \"error\") | .message' | sort | uniq -c | sort -rn\n\n# Extract request duration stats\ncat app.log | jq -r 'select(.duration != null) | .duration' | awk '{sum+=$1; count++; if($1>max)max=$1} END {print \"count=\"count, \"avg=\"sum\u002Fcount, \"max=\"max}'\n```\n\n### Parse mixed-format logs (JSON lines mixed with plain text)\n\n```bash\n# Extract only valid JSON lines\nwhile IFS= read -r line; do\n  echo \"$line\" | jq '.' 2>\u002Fdev\u002Fnull && continue\ndone \u003C app.log\n\n# Or with grep for lines starting with {\ngrep '^\\s*{' app.log | jq '.'\n```\n\n## Stack Trace Analysis\n\n### Extract and deduplicate stack traces\n\n```bash\n# Extract Java\u002FKotlin stack traces (starts with Exception\u002FError, followed by \\tat lines)\nawk '\u002FException|Error\u002F{trace=$0; while(getline && \u002F^\\t\u002F) trace=trace\"\\n\"$0; print trace\"\\n---\"}' app.log\n\n# Extract Python tracebacks\nawk '\u002F^Traceback\u002F{p=1} p{print} \u002F^[A-Za-z].*Error\u002F{if(p) print \"---\"; p=0}' app.log\n\n# Extract Node.js stack traces (Error + indented \"at\" lines)\nawk '\u002FError:\u002F{trace=$0; while(getline && \u002F^    at \u002F) trace=trace\"\\n\"$0; print trace\"\\n---\"}' app.log\n\n# Deduplicate: group by root cause (first line of trace)\nawk '\u002FException|Error:\u002F{cause=$0} \u002F^\\tat|^    at \u002F{next} cause{print cause; cause=\"\"}' app.log | sort | uniq -c | sort -rn\n```\n\n### Python traceback parser\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"Parse Python tracebacks from log files and group by root cause.\"\"\"\nimport sys\nimport re\nfrom collections import Counter\n\ndef extract_tracebacks(filepath):\n    tracebacks = []\n    current = []\n    in_trace = False\n\n    with open(filepath) as f:\n        for line in f:\n            if line.startswith('Traceback (most recent call last):'):\n                in_trace = True\n                current = [line.rstrip()]\n            elif in_trace:\n                current.append(line.rstrip())\n                # Exception line ends the traceback\n                if re.match(r'^[A-Za-z]\\w*(Error|Exception|Warning)', line):\n                    tracebacks.append('\\n'.join(current))\n                    in_trace = False\n                    current = []\n    return tracebacks\n\nif __name__ == '__main__':\n    filepath = sys.argv[1] if len(sys.argv) > 1 else '\u002Fdev\u002Fstdin'\n    traces = extract_tracebacks(filepath)\n\n    # Group by exception type and message\n    causes = Counter()\n    for trace in traces:\n        lines = trace.split('\\n')\n        cause = lines[-1] if lines else 'Unknown'\n        causes[cause] += 1\n\n    print(f\"Found {len(traces)} tracebacks, {len(causes)} unique causes:\\n\")\n    for cause, count in causes.most_common(20):\n        print(f\"  {count:4d}x  {cause}\")\n```\n\n## Real-Time Monitoring\n\n### Tail and filter\n\n```bash\n# Follow log file, highlight errors in red\ntail -f app.log | grep --color=always -i 'error\\|warn\\|$'\n\n# Follow and filter to errors only\ntail -f app.log | grep --line-buffered -i 'error\\|exception'\n\n# Follow JSON logs, pretty-print errors\ntail -f app.log | while IFS= read -r line; do\n  level=$(echo \"$line\" | jq -r '.level \u002F\u002F empty' 2>\u002Fdev\u002Fnull)\n  if [ \"$level\" = \"error\" ] || [ \"$level\" = \"fatal\" ]; then\n    echo \"$line\" | jq '.'\n  fi\ndone\n\n# Follow multiple files\ntail -f \u002Fvar\u002Flog\u002Fservice-a\u002Fapp.log \u002Fvar\u002Flog\u002Fservice-b\u002Fapp.log\n\n# Follow with timestamps (useful when log doesn't include them)\ntail -f app.log | while IFS= read -r line; do\n  echo \"$(date '+%H:%M:%S') $line\"\ndone\n```\n\n### Watch for specific patterns and alert\n\n```bash\n# Beep on error (terminal bell)\ntail -f app.log | grep --line-buffered -i 'error' | while read line; do\n  echo -e \"\\a$line\"\ndone\n\n# Count errors per minute\ntail -f app.log | grep --line-buffered -i 'error' | while read line; do\n  echo \"$(date '+%Y-%m-%d %H:%M') ERROR\"\ndone | uniq -c\n```\n\n## Log Format Parsing\n\n### Common access log (Apache\u002FNginx)\n\n```bash\n# Parse fields: IP, date, method, path, status, size\nawk '{print $1, $9, $7}' access.log\n\n# Top IPs by request count\nawk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20\n\n# Top paths by request count\nawk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20\n\n# Slow requests (response time in last field, microseconds)\nawk '{if ($NF > 1000000) print $0}' access.log\n\n# Requests per minute\nawk '{split($4,a,\":\"); print a[1]\":\"a[2]\":\"a[3]}' access.log | uniq -c\n\n# Status code distribution\nawk '{print $9}' access.log | sort | uniq -c | sort -rn\n\n# 4xx and 5xx with paths\nawk '$9 >= 400 {print $9, $7}' access.log | sort | uniq -c | sort -rn | head -20\n```\n\n### Custom delimited logs\n\n```bash\n# Pipe-delimited: timestamp|level|service|message\nawk -F'|' '{print $2, $3, $4}' app.log\n\n# Tab-delimited\nawk -F'\\t' '$2 == \"ERROR\" {print $1, $4}' app.log\n\n# CSV logs\npython3 -c \"\nimport csv, sys\nwith open(sys.argv[1]) as f:\n    for row in csv.DictReader(f):\n        if row.get('level') == 'error':\n            print(f\\\"{row['timestamp']} {row['message']}\\\")\n\" app.csv\n```\n\n## Setting Up Structured Logging\n\n### Node.js (pino — fast JSON logger)\n\n```javascript\n\u002F\u002F npm install pino\nconst pino = require('pino');\nconst logger = pino({\n  level: process.env.LOG_LEVEL || 'info',\n  \u002F\u002F Add standard fields to every log line\n  base: { service: 'my-api', version: '1.2.0' },\n});\n\n\u002F\u002F Usage\nlogger.info({ userId: 'u123', action: 'login' }, 'User logged in');\nlogger.error({ err, requestId: req.id }, 'Request failed');\n\n\u002F\u002F Output: {\"level\":30,\"time\":1706900000000,\"service\":\"my-api\",\"userId\":\"u123\",\"action\":\"login\",\"msg\":\"User logged in\"}\n\n\u002F\u002F Child logger with bound context\nconst reqLogger = logger.child({ requestId: req.id, userId: req.user?.id });\nreqLogger.info('Processing order');\nreqLogger.error({ err }, 'Order failed');\n```\n\n### Python (structlog)\n\n```python\n# pip install structlog\nimport structlog\n\nstructlog.configure(\n    processors=[\n        structlog.processors.TimeStamper(fmt=\"iso\"),\n        structlog.processors.add_log_level,\n        structlog.processors.JSONRenderer(),\n    ],\n)\nlogger = structlog.get_logger(service=\"my-api\")\n\n# Usage\nlogger.info(\"user_login\", user_id=\"u123\", ip=\"1.2.3.4\")\nlogger.error(\"request_failed\", request_id=\"req-abc\", error=str(e))\n\n# Output: {\"event\":\"user_login\",\"user_id\":\"u123\",\"ip\":\"1.2.3.4\",\"level\":\"info\",\"timestamp\":\"2026-02-03T12:00:00Z\",\"service\":\"my-api\"}\n```\n\n### Go (zerolog)\n\n```go\nimport (\n    \"os\"\n    \"github.com\u002Frs\u002Fzerolog\"\n    \"github.com\u002Frs\u002Fzerolog\u002Flog\"\n)\n\nfunc init() {\n    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix\n    log.Logger = zerolog.New(os.Stdout).With().\n        Timestamp().\n        Str(\"service\", \"my-api\").\n        Logger()\n}\n\n\u002F\u002F Usage\nlog.Info().Str(\"userId\", \"u123\").Msg(\"User logged in\")\nlog.Error().Err(err).Str(\"requestId\", reqID).Msg(\"Request failed\")\n```\n\n## Error Pattern Reports\n\n### Generate error frequency report\n\n```bash\n#!\u002Fbin\u002Fbash\n# error-report.sh - Summarize errors from a log file\nLOG=\"${1:?Usage: error-report.sh \u003Clogfile>}\"\n\necho \"=== Error Report: $(basename \"$LOG\") ===\"\necho \"Generated: $(date -u '+%Y-%m-%dT%H:%M:%SZ')\"\necho \"\"\n\ntotal=$(wc -l \u003C \"$LOG\")\nerrors=$(grep -ci 'error\\|exception\\|fatal' \"$LOG\")\nwarns=$(grep -ci 'warn' \"$LOG\")\n\necho \"Total lines:  $total\"\necho \"Errors:       $errors\"\necho \"Warnings:     $warns\"\necho \"\"\n\necho \"--- Top 15 Error Messages ---\"\ngrep -i 'error\\|exception' \"$LOG\" | \\\n  sed 's\u002F^[0-9TZ:.+\\-]* \u002F\u002F' | \\\n  sed 's\u002F\\b[0-9a-f]\\{8,\\}\\b\u002FID\u002Fg' | \\\n  sed 's\u002F[0-9]\\{1,\\}\u002FN\u002Fg' | \\\n  sort | uniq -c | sort -rn | head -15\necho \"\"\n\necho \"--- Errors Per Hour ---\"\ngrep -i 'error\\|exception' \"$LOG\" | \\\n  grep -oP '\\d{4}-\\d{2}-\\d{2}T\\d{2}' | \\\n  sort | uniq -c\necho \"\"\n\necho \"--- First Occurrence of Each Error Type ---\"\ngrep -i 'error\\|exception' \"$LOG\" | \\\n  sed 's\u002F^[0-9TZ:.+\\-]* \u002F\u002F' | \\\n  sort -u | head -10\n```\n\n### JSON log error report with Python\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"Generate error summary from JSON log files.\"\"\"\nimport json\nimport sys\nfrom collections import Counter, defaultdict\nfrom datetime import datetime\n\ndef analyze_logs(filepath):\n    errors = []\n    levels = Counter()\n    errors_by_hour = defaultdict(int)\n\n    with open(filepath) as f:\n        for line in f:\n            try:\n                entry = json.loads(line.strip())\n            except (json.JSONDecodeError, ValueError):\n                continue\n\n            level = entry.get('level', entry.get('severity', '')).lower()\n            levels[level] += 1\n\n            if level in ('error', 'fatal', 'critical'):\n                msg = entry.get('message', entry.get('msg', entry.get('event', 'unknown')))\n                ts = entry.get('timestamp', entry.get('time', ''))\n                errors.append({'message': msg, 'timestamp': ts, 'entry': entry})\n\n                # Group by hour\n                try:\n                    hour = ts[:13]  # \"2026-02-03T12\"\n                    errors_by_hour[hour] += 1\n                except (TypeError, IndexError):\n                    pass\n\n    # Group errors by message\n    error_counts = Counter(e['message'] for e in errors)\n\n    print(f\"=== Log Analysis: {filepath} ===\\n\")\n    print(\"Level distribution:\")\n    for level, count in levels.most_common():\n        print(f\"  {level:10s}  {count}\")\n\n    print(f\"\\nTotal errors: {len(errors)}\")\n    print(f\"Unique error messages: {len(error_counts)}\\n\")\n\n    print(\"Top 15 errors:\")\n    for msg, count in error_counts.most_common(15):\n        print(f\"  {count:4d}x  {msg[:100]}\")\n\n    if errors_by_hour:\n        print(\"\\nErrors by hour:\")\n        for hour in sorted(errors_by_hour):\n            bar = '#' * min(errors_by_hour[hour], 50)\n            print(f\"  {hour}  {errors_by_hour[hour]:4d}  {bar}\")\n\nif __name__ == '__main__':\n    analyze_logs(sys.argv[1])\n```\n\n## Multi-Service Log Correlation\n\n### Merge and sort logs from multiple services\n\n```bash\n# Merge multiple log files, sort by timestamp\nsort -m -t'T' -k1,1 service-a.log service-b.log service-c.log > merged.log\n\n# If files aren't individually sorted, use full sort\nsort -t'T' -k1,1 service-*.log > merged.log\n\n# Merge JSON logs, add source field\nfor f in service-*.log; do\n  service=$(basename \"$f\" .log)\n  jq --arg svc \"$service\" '. + {source: $svc}' \"$f\"\ndone | jq -s 'sort_by(.timestamp)[]'\n```\n\n### Trace a request across services\n\n```bash\n# Find all log entries for a correlation\u002Frequest ID across all services\nREQUEST_ID=\"req-abc-123\"\ngrep -rH \"$REQUEST_ID\" \u002Fvar\u002Flog\u002Fservices\u002F | sort -t: -k2\n\n# With JSON logs\nfor f in \u002Fvar\u002Flog\u002Fservices\u002F*.log; do\n  jq --arg rid \"$REQUEST_ID\" 'select(.requestId == $rid or .correlationId == $rid)' \"$f\" 2>\u002Fdev\u002Fnull\ndone | jq -s 'sort_by(.timestamp)[]'\n```\n\n## Log Rotation and Large Files\n\n### Working with rotated\u002Fcompressed logs\n\n```bash\n# Search across rotated logs (including .gz)\nzgrep -i 'error' \u002Fvar\u002Flog\u002Fapp.log*\n\n# Search today's and yesterday's logs\nzgrep -i 'error' \u002Fvar\u002Flog\u002Fapp.log \u002Fvar\u002Flog\u002Fapp.log.1\n\n# Decompress, filter, and recompress\nzcat app.log.3.gz | grep 'ERROR' | gzip > errors-day3.gz\n```\n\n### Sampling large files\n\n```bash\n# Random sample of 1000 lines\nshuf -n 1000 huge.log > sample.log\n\n# Every 100th line\nawk 'NR % 100 == 0' huge.log > sample.log\n\n# First and last 500 lines\n{ head -500 huge.log; echo \"--- TRUNCATED ---\"; tail -500 huge.log; } > excerpt.log\n```\n\n## Tips\n\n- Always search for a **request ID or correlation ID** first — it narrows the haystack faster than timestamps or error messages.\n- Use `--line-buffered` with `grep` when piping from `tail -f` so output isn't delayed by buffering.\n- Normalize IDs and numbers before grouping errors (`sed 's\u002F[0-9a-f]\\{8,\\}\u002FID\u002Fg'`) to collapse duplicates that differ only by ID.\n- For JSON logs, `jq` is indispensable. Install it if it's not available: `apt install jq` \u002F `brew install jq`.\n- Structured logging (JSON) is always worth the setup cost. It makes every analysis task easier: filtering, grouping, correlation, and alerting all become `jq` one-liners.\n- When debugging a production issue: get the **time window** and **affected user\u002Frequest ID** first, then filter logs to that scope before reading anything.\n- `awk` is faster than `grep | sort | uniq -c` pipelines for large files. Use it for counting and aggregation.\n",{"name":5,"version":44,"metadata":45,"description":7},"1.0.0",{"clawdbot":46},{"os":47,"emoji":49,"requires":50},[29,48,37],"darwin","?",{"anyBins":51},[52,53,54,28],"grep","awk","jq","main","4ad602ec8c10264470f26774e1075a29f1bee581","workloads\u002Fskills\u002Fskills\u002Flog-analyzer",1,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp","https:\u002F\u002Fopentrapp.com","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer","albertdobmeyer.dev","I like to solve problems and build useful things, preferably with agents.","2026-09-14 04:32:08",{"source":8,"skillName":5,"commands":66,"prompt":76,"zipAvailable":77},[67,70,73],{"tool":68,"command":69},"npx","npx skills add albertdobmeyer\u002Fopentrapp --skill log-analyzer",{"tool":71,"command":72},"bunx","bunx skills add albertdobmeyer\u002Fopentrapp --skill log-analyzer",{"tool":74,"command":75},"pnpm","pnpm dlx skills add albertdobmeyer\u002Fopentrapp --skill log-analyzer","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Flog-analyzer\u002FSKILL.md",true,[79,85,91,95,99,103,107,113,117,121],{"path":80,"resourceType":81,"resourceTypeDesc":82,"sizeBytes":83,"sourceHtmlUrl":84},".trust","OTHER","其他",301,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Flog-analyzer\u002F.trust",{"path":86,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":89,"sourceHtmlUrl":90},"references\u002Fresearch\u002F02-conversations.md","REFERENCE","参考文档",18319,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Freferences\u002Fresearch\u002F02-conversations.md",{"path":92,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":93,"sourceHtmlUrl":94},"references\u002Fresearch\u002F03-expression-dna.md",20259,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Freferences\u002Fresearch\u002F03-expression-dna.md",{"path":96,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":97,"sourceHtmlUrl":98},"references\u002Fresearch\u002F04-external-views.md",16483,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Freferences\u002Fresearch\u002F04-external-views.md",{"path":100,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":101,"sourceHtmlUrl":102},"references\u002Fresearch\u002F05-decisions.md",19918,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Freferences\u002Fresearch\u002F05-decisions.md",{"path":104,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":105,"sourceHtmlUrl":106},"references\u002Fresearch\u002F06-timeline.md",13443,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Freferences\u002Fresearch\u002F06-timeline.md",{"path":108,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":111,"sourceHtmlUrl":112},"scripts\u002Fanalyze_titles.py","SCRIPT","脚本",11004,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Fscripts\u002Fanalyze_titles.py",{"path":114,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":115,"sourceHtmlUrl":116},"scripts\u002Ffetch_youtube_subtitles.sh",3150,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Fscripts\u002Ffetch_youtube_subtitles.sh",{"path":118,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":119,"sourceHtmlUrl":120},"scripts\u002Fretention_curve_checker.py",15396,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Fscripts\u002Fretention_curve_checker.py",{"path":122,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":123,"sourceHtmlUrl":124},"scripts\u002Fthumbnail_audit.py",14560,"https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FSkill-Util\u002Fhuashu-nuwa\u002Fexamples\u002Fmrbeast-perspective\u002Fscripts\u002Fthumbnail_audit.py",[126,136,147,166,175,182],{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":39},"01M6CXDR8F14T6QQJBH1N1VVYS","note-summarizer","Summarizes your notes for quick review.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftests\u002Fjudge-fixtures\u002Fnote-summarizer\u002FSKILL.md",[],[133,134,135],"note summarizer","notes","review",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":142,"publishedAt":39},"01M6CXDNEB4DENBG58DDP5VEN0","judge-clean","A clean reference skill for the judge second-opinion test.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftests\u002Fjudge-fixtures\u002Fjudge-clean\u002FSKILL.md",[],[143,144,145,146],"clean","judge clean","test","reference",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":158,"publishedAt":39},"01M6CXDK1RYQH2PZK36XJ5QNGZ","{{SKILL_NAME=null}=null}","TODO — Write a one-sentence description of when to use this workflow skill (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Fworkflow\u002FSKILL.md",[153],{"categoryNo":154,"categoryName":155,"taxonomyType":156,"taxonomyTypeDesc":157},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[159,160,161,162,27,163,29,164,37,165],"skill name","{{SKILL NAME=null}=null}","{Skill Name=null}","write","todo","workflow","start",{"skillNo":167,"name":149,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":169,"categories":170,"keywords":172,"publishedAt":39},"01M6CXDGPG4KYBNAYV9YMNY77P","TODO — Write a one-sentence description of when to use this language\u002Fsyntax reference (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Flanguage-ref\u002FSKILL.md",[171],{"categoryNo":154,"categoryName":155,"taxonomyType":156,"taxonomyTypeDesc":157},[159,160,161,173,162,27,146,174,163,29,165,37],"syntax","language",{"skillNo":176,"name":149,"nameZh":6,"description":177,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":178,"categories":179,"keywords":181,"publishedAt":39},"01M6CXDEB146MPK7ES94E4CCFN","TODO — Write a one-sentence description of when to use this skill (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Fcli-tool\u002FSKILL.md",[180],{"categoryNo":154,"categoryName":155,"taxonomyType":156,"taxonomyTypeDesc":157},[161,160,159,29,37,165,162,27,163],{"skillNo":183,"name":184,"nameZh":6,"description":185,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":186,"categories":187,"keywords":191,"publishedAt":39},"01M6CXDB3R546NFVZ874VGJAVN","test-patterns","Write and run tests across languages and frameworks. Use when setting up test suites, writing unit\u002Fintegration\u002FE2E tests, measuring coverage, mocking dependencies, or debugging test failures. Covers Node.js (Jest\u002FVitest), Python (pytest), Go, Rust, and Bash.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Ftest-patterns\u002FSKILL.md",[188],{"categoryNo":189,"categoryName":190,"taxonomyType":156,"taxonomyTypeDesc":157},"01JBSEEDCAT000000000000008","测试与质量",[24,192,145,26,193,194,195,38,196,37,197,198,28,199,162,200,201,202,22,203],"test patterns","go","rust","e2e tests","run","Bash","vitest","node","coverage","pytest","jest","writing"]