specweave 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL.md +848 -0
- package/LICENSE +21 -0
- package/README.md +675 -0
- package/SPECWEAVE.md +665 -0
- package/bin/install-agents.sh +57 -0
- package/bin/install-all.sh +49 -0
- package/bin/install-commands.sh +56 -0
- package/bin/install-skills.sh +57 -0
- package/bin/specweave.js +81 -0
- package/dist/adapters/adapter-base.d.ts +50 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -0
- package/dist/adapters/adapter-base.js +146 -0
- package/dist/adapters/adapter-base.js.map +1 -0
- package/dist/adapters/adapter-interface.d.ts +108 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -0
- package/dist/adapters/adapter-interface.js +9 -0
- package/dist/adapters/adapter-interface.js.map +1 -0
- package/dist/adapters/claude/adapter.d.ts +54 -0
- package/dist/adapters/claude/adapter.d.ts.map +1 -0
- package/dist/adapters/claude/adapter.js +184 -0
- package/dist/adapters/claude/adapter.js.map +1 -0
- package/dist/adapters/copilot/adapter.d.ts +42 -0
- package/dist/adapters/copilot/adapter.d.ts.map +1 -0
- package/dist/adapters/copilot/adapter.js +239 -0
- package/dist/adapters/copilot/adapter.js.map +1 -0
- package/dist/adapters/cursor/adapter.d.ts +42 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -0
- package/dist/adapters/cursor/adapter.js +297 -0
- package/dist/adapters/cursor/adapter.js.map +1 -0
- package/dist/adapters/generic/adapter.d.ts +40 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -0
- package/dist/adapters/generic/adapter.js +155 -0
- package/dist/adapters/generic/adapter.js.map +1 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +247 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +7 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +160 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +154 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/package.json +90 -0
- package/src/adapters/README.md +312 -0
- package/src/adapters/adapter-base.ts +146 -0
- package/src/adapters/adapter-interface.ts +120 -0
- package/src/adapters/claude/README.md +241 -0
- package/src/adapters/claude/adapter.ts +157 -0
- package/src/adapters/copilot/.github/copilot/instructions.md +376 -0
- package/src/adapters/copilot/README.md +200 -0
- package/src/adapters/copilot/adapter.ts +210 -0
- package/src/adapters/cursor/.cursor/context/docs-context.md +62 -0
- package/src/adapters/cursor/.cursor/context/increments-context.md +71 -0
- package/src/adapters/cursor/.cursor/context/strategy-context.md +73 -0
- package/src/adapters/cursor/.cursor/context/tests-context.md +89 -0
- package/src/adapters/cursor/.cursorrules +325 -0
- package/src/adapters/cursor/README.md +243 -0
- package/src/adapters/cursor/adapter.ts +268 -0
- package/src/adapters/generic/README.md +277 -0
- package/src/adapters/generic/SPECWEAVE-MANUAL.md +676 -0
- package/src/adapters/generic/adapter.ts +159 -0
- package/src/adapters/registry.yaml +126 -0
- package/src/agents/architect/AGENT.md +416 -0
- package/src/agents/devops/AGENT.md +1738 -0
- package/src/agents/docs-writer/AGENT.md +239 -0
- package/src/agents/performance/AGENT.md +228 -0
- package/src/agents/pm/AGENT.md +751 -0
- package/src/agents/qa-lead/AGENT.md +150 -0
- package/src/agents/security/AGENT.md +179 -0
- package/src/agents/sre/AGENT.md +582 -0
- package/src/agents/sre/modules/backend-diagnostics.md +481 -0
- package/src/agents/sre/modules/database-diagnostics.md +509 -0
- package/src/agents/sre/modules/infrastructure.md +561 -0
- package/src/agents/sre/modules/monitoring.md +439 -0
- package/src/agents/sre/modules/security-incidents.md +421 -0
- package/src/agents/sre/modules/ui-diagnostics.md +302 -0
- package/src/agents/sre/playbooks/01-high-cpu-usage.md +204 -0
- package/src/agents/sre/playbooks/02-database-deadlock.md +241 -0
- package/src/agents/sre/playbooks/03-memory-leak.md +252 -0
- package/src/agents/sre/playbooks/04-slow-api-response.md +269 -0
- package/src/agents/sre/playbooks/05-ddos-attack.md +293 -0
- package/src/agents/sre/playbooks/06-disk-full.md +314 -0
- package/src/agents/sre/playbooks/07-service-down.md +333 -0
- package/src/agents/sre/playbooks/08-data-corruption.md +337 -0
- package/src/agents/sre/playbooks/09-cascade-failure.md +430 -0
- package/src/agents/sre/playbooks/10-rate-limit-exceeded.md +464 -0
- package/src/agents/sre/scripts/health-check.sh +230 -0
- package/src/agents/sre/scripts/log-analyzer.py +213 -0
- package/src/agents/sre/scripts/metrics-collector.sh +294 -0
- package/src/agents/sre/scripts/trace-analyzer.js +257 -0
- package/src/agents/sre/templates/incident-report.md +249 -0
- package/src/agents/sre/templates/mitigation-plan.md +375 -0
- package/src/agents/sre/templates/post-mortem.md +418 -0
- package/src/agents/sre/templates/runbook-template.md +412 -0
- package/src/agents/tech-lead/AGENT.md +263 -0
- package/src/commands/add-tasks.md +176 -0
- package/src/commands/close-increment.md +347 -0
- package/src/commands/create-increment.md +223 -0
- package/src/commands/create-project.md +528 -0
- package/src/commands/generate-docs.md +623 -0
- package/src/commands/list-increments.md +180 -0
- package/src/commands/review-docs.md +331 -0
- package/src/commands/start-increment.md +139 -0
- package/src/commands/sync-github.md +115 -0
- package/src/commands/validate-increment.md +800 -0
- package/src/hooks/README.md +252 -0
- package/src/hooks/docs-changed.sh +59 -0
- package/src/hooks/human-input-required.sh +55 -0
- package/src/hooks/post-task-completion.sh +57 -0
- package/src/hooks/pre-implementation.sh +47 -0
- package/src/skills/ado-sync/README.md +449 -0
- package/src/skills/ado-sync/SKILL.md +245 -0
- package/src/skills/ado-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/ado-sync/test-cases/test-2.yaml +8 -0
- package/src/skills/ado-sync/test-cases/test-3.yaml +9 -0
- package/src/skills/bmad-method-expert/SKILL.md +628 -0
- package/src/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
- package/src/skills/bmad-method-expert/scripts/check-setup.js +208 -0
- package/src/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
- package/src/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
- package/src/skills/bmad-method-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/SKILL.md +523 -0
- package/src/skills/brownfield-analyzer/test-cases/test-1-basic-analysis.yaml +48 -0
- package/src/skills/brownfield-analyzer/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/SKILL.md +625 -0
- package/src/skills/brownfield-onboarder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/context-loader/SKILL.md +734 -0
- package/src/skills/context-loader/test-cases/test-1-basic-loading.yaml +39 -0
- package/src/skills/context-loader/test-cases/test-2-token-budget-exceeded.yaml +44 -0
- package/src/skills/context-loader/test-cases/test-3-section-anchors.yaml +45 -0
- package/src/skills/context-optimizer/SKILL.md +618 -0
- package/src/skills/context-optimizer/test-cases/test-1-bug-fix-narrow.yaml +97 -0
- package/src/skills/context-optimizer/test-cases/test-2-feature-focused.yaml +109 -0
- package/src/skills/context-optimizer/test-cases/test-3-architecture-broad.yaml +98 -0
- package/src/skills/cost-optimizer/SKILL.md +190 -0
- package/src/skills/cost-optimizer/test-cases/test-1-basic-comparison.yaml +75 -0
- package/src/skills/cost-optimizer/test-cases/test-2-budget-constraint.yaml +52 -0
- package/src/skills/cost-optimizer/test-cases/test-3-scale-requirement.yaml +63 -0
- package/src/skills/cost-optimizer/test-results/README.md +46 -0
- package/src/skills/design-system-architect/SKILL.md +107 -0
- package/src/skills/design-system-architect/test-cases/test-1-token-structure.yaml +23 -0
- package/src/skills/design-system-architect/test-cases/test-2-component-hierarchy.yaml +24 -0
- package/src/skills/design-system-architect/test-cases/test-3-accessibility-checklist.yaml +23 -0
- package/src/skills/diagrams-architect/SKILL.md +763 -0
- package/src/skills/diagrams-generator/SKILL.md +25 -0
- package/src/skills/diagrams-generator/test-cases/test-1.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-2.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-3.yaml +8 -0
- package/src/skills/docs-updater/README.md +48 -0
- package/src/skills/docs-updater/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/dotnet-backend/SKILL.md +250 -0
- package/src/skills/e2e-playwright/README.md +506 -0
- package/src/skills/e2e-playwright/SKILL.md +457 -0
- package/src/skills/e2e-playwright/execute.js +373 -0
- package/src/skills/e2e-playwright/lib/utils.js +514 -0
- package/src/skills/e2e-playwright/package.json +33 -0
- package/src/skills/e2e-playwright/test-cases/TC-001-basic-navigation.yaml +54 -0
- package/src/skills/e2e-playwright/test-cases/TC-002-form-interaction.yaml +64 -0
- package/src/skills/e2e-playwright/test-cases/TC-003-specweave-integration.yaml +74 -0
- package/src/skills/e2e-playwright/test-cases/TC-004-accessibility-check.yaml +98 -0
- package/src/skills/figma-designer/SKILL.md +149 -0
- package/src/skills/figma-implementer/SKILL.md +148 -0
- package/src/skills/figma-mcp-connector/SKILL.md +136 -0
- package/src/skills/figma-mcp-connector/test-cases/test-1-read-file-desktop.yaml +22 -0
- package/src/skills/figma-mcp-connector/test-cases/test-2-read-file-framelink.yaml +21 -0
- package/src/skills/figma-mcp-connector/test-cases/test-3-error-handling.yaml +18 -0
- package/src/skills/figma-to-code/SKILL.md +128 -0
- package/src/skills/figma-to-code/test-cases/test-1-token-generation.yaml +29 -0
- package/src/skills/figma-to-code/test-cases/test-2-component-generation.yaml +27 -0
- package/src/skills/figma-to-code/test-cases/test-3-typescript-generation.yaml +28 -0
- package/src/skills/frontend/SKILL.md +177 -0
- package/src/skills/github-sync/SKILL.md +252 -0
- package/src/skills/github-sync/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/hetzner-provisioner/README.md +308 -0
- package/src/skills/hetzner-provisioner/SKILL.md +251 -0
- package/src/skills/hetzner-provisioner/test-cases/test-1-basic-provision.yaml +71 -0
- package/src/skills/hetzner-provisioner/test-cases/test-2-postgres-provision.yaml +85 -0
- package/src/skills/hetzner-provisioner/test-cases/test-3-ssl-config.yaml +126 -0
- package/src/skills/hetzner-provisioner/test-results/README.md +259 -0
- package/src/skills/increment-planner/SKILL.md +889 -0
- package/src/skills/increment-planner/scripts/feature-utils.js +250 -0
- package/src/skills/increment-planner/test-cases/test-1-basic-feature.yaml +27 -0
- package/src/skills/increment-planner/test-cases/test-2-complex-feature.yaml +30 -0
- package/src/skills/increment-planner/test-cases/test-3-auto-numbering.yaml +24 -0
- package/src/skills/increment-quality-judge/SKILL.md +566 -0
- package/src/skills/increment-quality-judge/test-cases/test-1-good-spec.yaml +95 -0
- package/src/skills/increment-quality-judge/test-cases/test-2-poor-spec.yaml +108 -0
- package/src/skills/increment-quality-judge/test-cases/test-3-export-suggestions.yaml +87 -0
- package/src/skills/jira-sync/README.md +328 -0
- package/src/skills/jira-sync/SKILL.md +209 -0
- package/src/skills/jira-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-2.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-3.yaml +10 -0
- package/src/skills/nextjs/SKILL.md +176 -0
- package/src/skills/nodejs-backend/SKILL.md +181 -0
- package/src/skills/notification-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/python-backend/SKILL.md +226 -0
- package/src/skills/role-orchestrator/README.md +197 -0
- package/src/skills/role-orchestrator/SKILL.md +1184 -0
- package/src/skills/role-orchestrator/test-cases/test-1-simple-product.yaml +98 -0
- package/src/skills/role-orchestrator/test-cases/test-2-quality-gate-failure.yaml +73 -0
- package/src/skills/role-orchestrator/test-cases/test-3-security-workflow.yaml +121 -0
- package/src/skills/role-orchestrator/test-cases/test-4-parallel-execution.yaml +145 -0
- package/src/skills/role-orchestrator/test-cases/test-5-feedback-loops.yaml +149 -0
- package/src/skills/skill-creator/LICENSE.txt +202 -0
- package/src/skills/skill-creator/SKILL.md +209 -0
- package/src/skills/skill-creator/scripts/init_skill.py +303 -0
- package/src/skills/skill-creator/scripts/package_skill.py +110 -0
- package/src/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/src/skills/skill-creator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/skill-router/SKILL.md +497 -0
- package/src/skills/skill-router/test-cases/test-1-basic-routing.yaml +33 -0
- package/src/skills/skill-router/test-cases/test-2-ambiguous-request.yaml +42 -0
- package/src/skills/skill-router/test-cases/test-3-nested-orchestration.yaml +50 -0
- package/src/skills/spec-driven-brainstorming/README.md +264 -0
- package/src/skills/spec-driven-brainstorming/SKILL.md +439 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-001-simple-idea-to-design.yaml +148 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-002-complex-ultrathink-design.yaml +190 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-003-unclear-requirements-socratic.yaml +233 -0
- package/src/skills/spec-driven-debugging/README.md +479 -0
- package/src/skills/spec-driven-debugging/SKILL.md +652 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-001-simple-auth-bug.yaml +212 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-002-race-condition-ultrathink.yaml +461 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-003-brownfield-missing-spec.yaml +366 -0
- package/src/skills/spec-kit-expert/SKILL.md +1012 -0
- package/src/skills/spec-kit-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/specweave-ado-mapper/SKILL.md +501 -0
- package/src/skills/specweave-detector/SKILL.md +420 -0
- package/src/skills/specweave-detector/test-cases/test-1-basic-detection.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-2-missing-config.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-3-non-specweave-project.yaml +34 -0
- package/src/skills/specweave-jira-mapper/SKILL.md +500 -0
- package/src/skills/stripe-integrator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/task-builder/README.md +90 -0
- package/src/skills/task-builder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/templates/.env.example +144 -0
- package/src/templates/.gitignore.template +81 -0
- package/src/templates/CLAUDE.md.template +383 -0
- package/src/templates/README.md.template +240 -0
- package/src/templates/config.yaml +333 -0
- package/src/templates/docs/README.md +124 -0
- package/src/templates/docs/adr-template.md +118 -0
- package/src/templates/docs/hld-template.md +220 -0
- package/src/templates/docs/lld-template.md +580 -0
- package/src/templates/docs/prd-template.md +132 -0
- package/src/templates/docs/rfc-template.md +229 -0
- package/src/templates/docs/runbook-template.md +298 -0
- package/src/templates/environments/minimal/.env.production +16 -0
- package/src/templates/environments/minimal/README.md +54 -0
- package/src/templates/environments/minimal/deploy-production.yml +52 -0
- package/src/templates/environments/progressive/.env.qa +28 -0
- package/src/templates/environments/progressive/README.md +129 -0
- package/src/templates/environments/progressive/deploy-production.yml +93 -0
- package/src/templates/environments/progressive/deploy-qa.yml +62 -0
- package/src/templates/environments/progressive/deploy-staging.yml +67 -0
- package/src/templates/environments/standard/.env.development +20 -0
- package/src/templates/environments/standard/.env.production +30 -0
- package/src/templates/environments/standard/.env.staging +23 -0
- package/src/templates/environments/standard/README.md +97 -0
- package/src/templates/environments/standard/deploy-production.yml +68 -0
- package/src/templates/environments/standard/deploy-staging.yml +61 -0
- package/src/templates/environments/standard/docker-compose.yml +43 -0
- package/src/templates/increment-metadata-template.yaml +138 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
log-analyzer.py
|
|
5
|
+
Parse application/system logs for error patterns and anomalies
|
|
6
|
+
|
|
7
|
+
Usage: python3 log-analyzer.py /var/log/application.log
|
|
8
|
+
python3 log-analyzer.py /var/log/application.log --errors-only
|
|
9
|
+
python3 log-analyzer.py /var/log/application.log --since "2025-10-26 14:00"
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import re
|
|
13
|
+
import sys
|
|
14
|
+
import argparse
|
|
15
|
+
from datetime import datetime, timedelta
|
|
16
|
+
from collections import Counter, defaultdict
|
|
17
|
+
|
|
18
|
+
def parse_args():
|
|
19
|
+
parser = argparse.ArgumentParser(description='Analyze log files for errors and patterns')
|
|
20
|
+
parser.add_argument('logfile', help='Path to log file')
|
|
21
|
+
parser.add_argument('--errors-only', action='store_true', help='Show only errors (ERROR, FATAL)')
|
|
22
|
+
parser.add_argument('--warnings', action='store_true', help='Include warnings')
|
|
23
|
+
parser.add_argument('--since', help='Show logs since timestamp (YYYY-MM-DD HH:MM)')
|
|
24
|
+
parser.add_argument('--until', help='Show logs until timestamp (YYYY-MM-DD HH:MM)')
|
|
25
|
+
parser.add_argument('--pattern', help='Search for specific pattern (regex)')
|
|
26
|
+
parser.add_argument('--top', type=int, default=10, help='Show top N errors (default: 10)')
|
|
27
|
+
return parser.parse_args()
|
|
28
|
+
|
|
29
|
+
def parse_log_line(line):
|
|
30
|
+
"""Parse common log formats"""
|
|
31
|
+
# Try different log formats
|
|
32
|
+
patterns = [
|
|
33
|
+
# JSON: {"timestamp":"2025-10-26T14:00:00Z","level":"ERROR","message":"..."}
|
|
34
|
+
r'\{"timestamp":"(?P<timestamp>[^"]+)".*"level":"(?P<level>[^"]+)".*"message":"(?P<message>[^"]+)"',
|
|
35
|
+
|
|
36
|
+
# Standard: [2025-10-26 14:00:00] ERROR: message
|
|
37
|
+
r'\[(?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]\s+(?P<level>\w+):\s+(?P<message>.*)',
|
|
38
|
+
|
|
39
|
+
# Syslog: Oct 26 14:00:00 hostname application[1234]: ERROR message
|
|
40
|
+
r'(?P<timestamp>\w+ \d+ \d{2}:\d{2}:\d{2})\s+\S+\s+\S+:\s+(?P<level>\w+)\s+(?P<message>.*)',
|
|
41
|
+
|
|
42
|
+
# Simple: 2025-10-26 14:00:00 ERROR message
|
|
43
|
+
r'(?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+(?P<level>\w+)\s+(?P<message>.*)',
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
for pattern in patterns:
|
|
47
|
+
match = re.match(pattern, line)
|
|
48
|
+
if match:
|
|
49
|
+
return match.groupdict()
|
|
50
|
+
|
|
51
|
+
# If no pattern matched, return raw line
|
|
52
|
+
return {'timestamp': None, 'level': 'INFO', 'message': line.strip()}
|
|
53
|
+
|
|
54
|
+
def parse_timestamp(ts_str):
|
|
55
|
+
"""Parse various timestamp formats"""
|
|
56
|
+
if not ts_str:
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
formats = [
|
|
60
|
+
'%Y-%m-%dT%H:%M:%SZ',
|
|
61
|
+
'%Y-%m-%d %H:%M:%S',
|
|
62
|
+
'%b %d %H:%M:%S',
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
for fmt in formats:
|
|
66
|
+
try:
|
|
67
|
+
return datetime.strptime(ts_str, fmt)
|
|
68
|
+
except ValueError:
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
def main():
|
|
74
|
+
args = parse_args()
|
|
75
|
+
|
|
76
|
+
# Parse filters
|
|
77
|
+
since = datetime.strptime(args.since, '%Y-%m-%d %H:%M') if args.since else None
|
|
78
|
+
until = datetime.strptime(args.until, '%Y-%m-%d %H:%M') if args.until else None
|
|
79
|
+
|
|
80
|
+
# Stats
|
|
81
|
+
total_lines = 0
|
|
82
|
+
error_count = 0
|
|
83
|
+
warning_count = 0
|
|
84
|
+
error_messages = Counter()
|
|
85
|
+
errors_by_hour = defaultdict(int)
|
|
86
|
+
error_timeline = []
|
|
87
|
+
|
|
88
|
+
print(f"Analyzing log file: {args.logfile}")
|
|
89
|
+
print("=" * 80)
|
|
90
|
+
print()
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
with open(args.logfile, 'r', encoding='utf-8', errors='ignore') as f:
|
|
94
|
+
for line in f:
|
|
95
|
+
total_lines += 1
|
|
96
|
+
|
|
97
|
+
# Parse log line
|
|
98
|
+
parsed = parse_log_line(line)
|
|
99
|
+
level = parsed.get('level', '').upper()
|
|
100
|
+
message = parsed.get('message', '')
|
|
101
|
+
timestamp = parse_timestamp(parsed.get('timestamp'))
|
|
102
|
+
|
|
103
|
+
# Filter by time range
|
|
104
|
+
if since and timestamp and timestamp < since:
|
|
105
|
+
continue
|
|
106
|
+
if until and timestamp and timestamp > until:
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
# Filter by pattern
|
|
110
|
+
if args.pattern and not re.search(args.pattern, message, re.IGNORECASE):
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
# Filter by level
|
|
114
|
+
if args.errors_only and level not in ['ERROR', 'FATAL', 'CRITICAL']:
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
# Count errors and warnings
|
|
118
|
+
if level in ['ERROR', 'FATAL', 'CRITICAL']:
|
|
119
|
+
error_count += 1
|
|
120
|
+
|
|
121
|
+
# Extract error message (first 100 chars)
|
|
122
|
+
error_key = message[:100] if len(message) > 100 else message
|
|
123
|
+
error_messages[error_key] += 1
|
|
124
|
+
|
|
125
|
+
# Group by hour
|
|
126
|
+
if timestamp:
|
|
127
|
+
hour_key = timestamp.strftime('%Y-%m-%d %H:00')
|
|
128
|
+
errors_by_hour[hour_key] += 1
|
|
129
|
+
error_timeline.append((timestamp, message))
|
|
130
|
+
|
|
131
|
+
elif level in ['WARN', 'WARNING'] and args.warnings:
|
|
132
|
+
warning_count += 1
|
|
133
|
+
|
|
134
|
+
# Print summary
|
|
135
|
+
print(f"📊 SUMMARY")
|
|
136
|
+
print(f"---------")
|
|
137
|
+
print(f"Total lines: {total_lines:,}")
|
|
138
|
+
print(f"Errors: {error_count:,}")
|
|
139
|
+
if args.warnings:
|
|
140
|
+
print(f"Warnings: {warning_count:,}")
|
|
141
|
+
print()
|
|
142
|
+
|
|
143
|
+
# Top errors
|
|
144
|
+
if error_messages:
|
|
145
|
+
print(f"🔥 TOP {args.top} ERRORS")
|
|
146
|
+
print(f"{'Count':<10} {'Message':<70}")
|
|
147
|
+
print("-" * 80)
|
|
148
|
+
for msg, count in error_messages.most_common(args.top):
|
|
149
|
+
msg_short = (msg[:67] + '...') if len(msg) > 70 else msg
|
|
150
|
+
print(f"{count:<10} {msg_short}")
|
|
151
|
+
print()
|
|
152
|
+
|
|
153
|
+
# Errors by hour
|
|
154
|
+
if errors_by_hour:
|
|
155
|
+
print(f"📈 ERRORS BY HOUR")
|
|
156
|
+
print(f"{'Hour':<20} {'Count':<10} {'Graph':<50}")
|
|
157
|
+
print("-" * 80)
|
|
158
|
+
|
|
159
|
+
max_errors = max(errors_by_hour.values())
|
|
160
|
+
for hour in sorted(errors_by_hour.keys()):
|
|
161
|
+
count = errors_by_hour[hour]
|
|
162
|
+
bar_length = int((count / max_errors) * 40)
|
|
163
|
+
bar = '█' * bar_length
|
|
164
|
+
print(f"{hour:<20} {count:<10} {bar}")
|
|
165
|
+
print()
|
|
166
|
+
|
|
167
|
+
# Error timeline (last 20)
|
|
168
|
+
if error_timeline:
|
|
169
|
+
print(f"⏱️ ERROR TIMELINE (Last 20)")
|
|
170
|
+
print(f"{'Timestamp':<20} {'Message':<60}")
|
|
171
|
+
print("-" * 80)
|
|
172
|
+
|
|
173
|
+
for timestamp, message in sorted(error_timeline, reverse=True)[:20]:
|
|
174
|
+
ts_str = timestamp.strftime('%Y-%m-%d %H:%M:%S')
|
|
175
|
+
msg_short = (message[:57] + '...') if len(message) > 60 else message
|
|
176
|
+
print(f"{ts_str:<20} {msg_short}")
|
|
177
|
+
print()
|
|
178
|
+
|
|
179
|
+
# Recommendations
|
|
180
|
+
print(f"💡 RECOMMENDATIONS")
|
|
181
|
+
print(f"-----------------")
|
|
182
|
+
|
|
183
|
+
if error_count == 0:
|
|
184
|
+
print("✅ No errors found. System looks healthy!")
|
|
185
|
+
elif error_count < 10:
|
|
186
|
+
print(f"⚠️ {error_count} errors found. Review above for details.")
|
|
187
|
+
elif error_count < 100:
|
|
188
|
+
print(f"⚠️ {error_count} errors found. Investigate top errors.")
|
|
189
|
+
else:
|
|
190
|
+
print(f"🚨 {error_count} errors found! Immediate investigation required.")
|
|
191
|
+
print(" - Check for cascading failures")
|
|
192
|
+
print(" - Review error timeline for spike")
|
|
193
|
+
print(" - Check related services")
|
|
194
|
+
|
|
195
|
+
if errors_by_hour:
|
|
196
|
+
# Find hour with most errors
|
|
197
|
+
peak_hour = max(errors_by_hour.items(), key=lambda x: x[1])
|
|
198
|
+
print(f"\n📍 Peak error hour: {peak_hour[0]} ({peak_hour[1]} errors)")
|
|
199
|
+
print(f" - Review what happened at this time")
|
|
200
|
+
print(f" - Check deployment, traffic spike, external dependency")
|
|
201
|
+
|
|
202
|
+
print()
|
|
203
|
+
|
|
204
|
+
except FileNotFoundError:
|
|
205
|
+
print(f"❌ Error: Log file not found: {args.logfile}")
|
|
206
|
+
sys.exit(1)
|
|
207
|
+
except PermissionError:
|
|
208
|
+
print(f"❌ Error: Permission denied: {args.logfile}")
|
|
209
|
+
print(f" Try: sudo python3 {sys.argv[0]} {args.logfile}")
|
|
210
|
+
sys.exit(1)
|
|
211
|
+
|
|
212
|
+
if __name__ == '__main__':
|
|
213
|
+
main()
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# metrics-collector.sh
|
|
4
|
+
# Gather system metrics for incident diagnosis
|
|
5
|
+
# Usage: ./metrics-collector.sh [output_file]
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
OUTPUT_FILE=${1:-"metrics-$(date +%Y%m%d-%H%M%S).txt"}
|
|
10
|
+
|
|
11
|
+
echo "Collecting system metrics..."
|
|
12
|
+
echo "Output: $OUTPUT_FILE"
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
{
|
|
16
|
+
echo "========================================="
|
|
17
|
+
echo "SYSTEM METRICS COLLECTION"
|
|
18
|
+
echo "========================================="
|
|
19
|
+
echo "Date: $(date)"
|
|
20
|
+
echo "Hostname: $(hostname)"
|
|
21
|
+
echo "Uptime: $(uptime -p 2>/dev/null || uptime)"
|
|
22
|
+
echo ""
|
|
23
|
+
|
|
24
|
+
# 1. CPU Metrics
|
|
25
|
+
echo "========================================="
|
|
26
|
+
echo "1. CPU METRICS"
|
|
27
|
+
echo "========================================="
|
|
28
|
+
echo ""
|
|
29
|
+
|
|
30
|
+
echo "CPU Info:"
|
|
31
|
+
lscpu | grep -E "^Model name|^CPU\(s\)|^Thread|^Core|^Socket"
|
|
32
|
+
echo ""
|
|
33
|
+
|
|
34
|
+
echo "CPU Usage (snapshot):"
|
|
35
|
+
top -bn1 | head -20
|
|
36
|
+
echo ""
|
|
37
|
+
|
|
38
|
+
echo "Load Average:"
|
|
39
|
+
uptime
|
|
40
|
+
echo ""
|
|
41
|
+
|
|
42
|
+
if command -v mpstat &> /dev/null; then
|
|
43
|
+
echo "CPU by Core:"
|
|
44
|
+
mpstat -P ALL 1 1
|
|
45
|
+
echo ""
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# 2. Memory Metrics
|
|
49
|
+
echo "========================================="
|
|
50
|
+
echo "2. MEMORY METRICS"
|
|
51
|
+
echo "========================================="
|
|
52
|
+
echo ""
|
|
53
|
+
|
|
54
|
+
echo "Memory Overview:"
|
|
55
|
+
free -h
|
|
56
|
+
echo ""
|
|
57
|
+
|
|
58
|
+
echo "Memory Details:"
|
|
59
|
+
cat /proc/meminfo | head -20
|
|
60
|
+
echo ""
|
|
61
|
+
|
|
62
|
+
echo "Top Memory Processes:"
|
|
63
|
+
ps aux | sort -nrk 4,4 | head -10
|
|
64
|
+
echo ""
|
|
65
|
+
|
|
66
|
+
# 3. Disk Metrics
|
|
67
|
+
echo "========================================="
|
|
68
|
+
echo "3. DISK METRICS"
|
|
69
|
+
echo "========================================="
|
|
70
|
+
echo ""
|
|
71
|
+
|
|
72
|
+
echo "Disk Usage:"
|
|
73
|
+
df -h
|
|
74
|
+
echo ""
|
|
75
|
+
|
|
76
|
+
echo "Inode Usage:"
|
|
77
|
+
df -i
|
|
78
|
+
echo ""
|
|
79
|
+
|
|
80
|
+
if command -v iostat &> /dev/null; then
|
|
81
|
+
echo "Disk I/O Stats:"
|
|
82
|
+
iostat -x 1 5
|
|
83
|
+
echo ""
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
echo "Disk Space by Directory (/):"
|
|
87
|
+
du -sh /* 2>/dev/null | sort -hr | head -20
|
|
88
|
+
echo ""
|
|
89
|
+
|
|
90
|
+
# 4. Network Metrics
|
|
91
|
+
echo "========================================="
|
|
92
|
+
echo "4. NETWORK METRICS"
|
|
93
|
+
echo "========================================="
|
|
94
|
+
echo ""
|
|
95
|
+
|
|
96
|
+
echo "Network Interfaces:"
|
|
97
|
+
ip addr show
|
|
98
|
+
echo ""
|
|
99
|
+
|
|
100
|
+
echo "Network Statistics:"
|
|
101
|
+
netstat -s | head -50
|
|
102
|
+
echo ""
|
|
103
|
+
|
|
104
|
+
echo "Active Connections:"
|
|
105
|
+
netstat -an | grep ESTABLISHED | wc -l
|
|
106
|
+
echo ""
|
|
107
|
+
|
|
108
|
+
echo "Top 10 IPs by Connection Count:"
|
|
109
|
+
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10
|
|
110
|
+
echo ""
|
|
111
|
+
|
|
112
|
+
if command -v ss &> /dev/null; then
|
|
113
|
+
echo "Socket Stats:"
|
|
114
|
+
ss -s
|
|
115
|
+
echo ""
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# 5. Process Metrics
|
|
119
|
+
echo "========================================="
|
|
120
|
+
echo "5. PROCESS METRICS"
|
|
121
|
+
echo "========================================="
|
|
122
|
+
echo ""
|
|
123
|
+
|
|
124
|
+
echo "Process Count:"
|
|
125
|
+
ps aux | wc -l
|
|
126
|
+
echo ""
|
|
127
|
+
|
|
128
|
+
echo "Top CPU Processes:"
|
|
129
|
+
ps aux | sort -nrk 3,3 | head -10
|
|
130
|
+
echo ""
|
|
131
|
+
|
|
132
|
+
echo "Top Memory Processes:"
|
|
133
|
+
ps aux | sort -nrk 4,4 | head -10
|
|
134
|
+
echo ""
|
|
135
|
+
|
|
136
|
+
echo "Zombie Processes:"
|
|
137
|
+
ps aux | grep -E "<defunct>|Z" | grep -v grep
|
|
138
|
+
echo ""
|
|
139
|
+
|
|
140
|
+
# 6. Database Metrics (PostgreSQL)
|
|
141
|
+
echo "========================================="
|
|
142
|
+
echo "6. DATABASE METRICS (PostgreSQL)"
|
|
143
|
+
echo "========================================="
|
|
144
|
+
echo ""
|
|
145
|
+
|
|
146
|
+
if command -v psql &> /dev/null; then
|
|
147
|
+
if sudo -u postgres psql -c "SELECT 1" &> /dev/null; then
|
|
148
|
+
echo "PostgreSQL Connection Count:"
|
|
149
|
+
sudo -u postgres psql -t -c "SELECT count(*) FROM pg_stat_activity;"
|
|
150
|
+
echo ""
|
|
151
|
+
|
|
152
|
+
echo "PostgreSQL Max Connections:"
|
|
153
|
+
sudo -u postgres psql -t -c "SHOW max_connections;"
|
|
154
|
+
echo ""
|
|
155
|
+
|
|
156
|
+
echo "PostgreSQL Active Queries:"
|
|
157
|
+
sudo -u postgres psql -x -c "SELECT pid, usename, application_name, state, query FROM pg_stat_activity WHERE state != 'idle' LIMIT 10;"
|
|
158
|
+
echo ""
|
|
159
|
+
|
|
160
|
+
echo "PostgreSQL Database Sizes:"
|
|
161
|
+
sudo -u postgres psql -c "SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database WHERE datistemplate = false;"
|
|
162
|
+
echo ""
|
|
163
|
+
|
|
164
|
+
echo "PostgreSQL Table Sizes (top 10):"
|
|
165
|
+
sudo -u postgres psql -c "SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size FROM pg_tables ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC LIMIT 10;"
|
|
166
|
+
echo ""
|
|
167
|
+
|
|
168
|
+
if command -v pg_stat_statements &> /dev/null; then
|
|
169
|
+
echo "PostgreSQL Slow Queries (top 5):"
|
|
170
|
+
sudo -u postgres psql -c "SELECT query, calls, total_exec_time, mean_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 5;"
|
|
171
|
+
echo ""
|
|
172
|
+
fi
|
|
173
|
+
else
|
|
174
|
+
echo "PostgreSQL not accessible"
|
|
175
|
+
echo ""
|
|
176
|
+
fi
|
|
177
|
+
else
|
|
178
|
+
echo "PostgreSQL not installed"
|
|
179
|
+
echo ""
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
# 7. Web Server Metrics (nginx)
|
|
183
|
+
echo "========================================="
|
|
184
|
+
echo "7. WEB SERVER METRICS (nginx)"
|
|
185
|
+
echo "========================================="
|
|
186
|
+
echo ""
|
|
187
|
+
|
|
188
|
+
if systemctl is-active --quiet nginx 2>/dev/null; then
|
|
189
|
+
echo "Nginx Status: Running"
|
|
190
|
+
|
|
191
|
+
if [ -f /var/log/nginx/access.log ]; then
|
|
192
|
+
echo ""
|
|
193
|
+
echo "Nginx Request Count (last 1000 lines):"
|
|
194
|
+
tail -1000 /var/log/nginx/access.log | wc -l
|
|
195
|
+
|
|
196
|
+
echo ""
|
|
197
|
+
echo "Nginx Status Codes (last 1000 lines):"
|
|
198
|
+
tail -1000 /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -nr
|
|
199
|
+
|
|
200
|
+
echo ""
|
|
201
|
+
echo "Nginx Top 10 URLs:"
|
|
202
|
+
tail -1000 /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -10
|
|
203
|
+
|
|
204
|
+
echo ""
|
|
205
|
+
echo "Nginx Top 10 IPs:"
|
|
206
|
+
tail -1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
|
|
207
|
+
fi
|
|
208
|
+
else
|
|
209
|
+
echo "Nginx not running"
|
|
210
|
+
fi
|
|
211
|
+
echo ""
|
|
212
|
+
|
|
213
|
+
# 8. Application Metrics (customize as needed)
|
|
214
|
+
echo "========================================="
|
|
215
|
+
echo "8. APPLICATION METRICS"
|
|
216
|
+
echo "========================================="
|
|
217
|
+
echo ""
|
|
218
|
+
|
|
219
|
+
echo "Application Processes:"
|
|
220
|
+
ps aux | grep -E "node|java|python|ruby" | grep -v grep
|
|
221
|
+
echo ""
|
|
222
|
+
|
|
223
|
+
echo "Application Ports:"
|
|
224
|
+
netstat -tlnp 2>/dev/null | grep -E "node|java|python|ruby"
|
|
225
|
+
echo ""
|
|
226
|
+
|
|
227
|
+
# 9. System Logs (recent errors)
|
|
228
|
+
echo "========================================="
|
|
229
|
+
echo "9. RECENT SYSTEM ERRORS"
|
|
230
|
+
echo "========================================="
|
|
231
|
+
echo ""
|
|
232
|
+
|
|
233
|
+
echo "Recent Syslog Errors (last 50):"
|
|
234
|
+
if [ -f /var/log/syslog ]; then
|
|
235
|
+
grep -i "error\|fail\|critical" /var/log/syslog | tail -50
|
|
236
|
+
else
|
|
237
|
+
echo "Syslog not found"
|
|
238
|
+
fi
|
|
239
|
+
echo ""
|
|
240
|
+
|
|
241
|
+
echo "Recent Journal Errors (last 10 minutes):"
|
|
242
|
+
if command -v journalctl &> /dev/null; then
|
|
243
|
+
journalctl --since "10 minutes ago" --priority=err --no-pager | tail -50
|
|
244
|
+
else
|
|
245
|
+
echo "journalctl not available"
|
|
246
|
+
fi
|
|
247
|
+
echo ""
|
|
248
|
+
|
|
249
|
+
# 10. System Info
|
|
250
|
+
echo "========================================="
|
|
251
|
+
echo "10. SYSTEM INFORMATION"
|
|
252
|
+
echo "========================================="
|
|
253
|
+
echo ""
|
|
254
|
+
|
|
255
|
+
echo "OS Version:"
|
|
256
|
+
cat /etc/os-release 2>/dev/null || uname -a
|
|
257
|
+
echo ""
|
|
258
|
+
|
|
259
|
+
echo "Kernel Version:"
|
|
260
|
+
uname -r
|
|
261
|
+
echo ""
|
|
262
|
+
|
|
263
|
+
echo "System Time:"
|
|
264
|
+
date
|
|
265
|
+
echo ""
|
|
266
|
+
|
|
267
|
+
echo "Timezone:"
|
|
268
|
+
timedatectl 2>/dev/null || cat /etc/timezone
|
|
269
|
+
echo ""
|
|
270
|
+
|
|
271
|
+
# Summary
|
|
272
|
+
echo "========================================="
|
|
273
|
+
echo "COLLECTION COMPLETE"
|
|
274
|
+
echo "========================================="
|
|
275
|
+
echo "Collected at: $(date)"
|
|
276
|
+
echo "Metrics saved to: $OUTPUT_FILE"
|
|
277
|
+
echo ""
|
|
278
|
+
|
|
279
|
+
} > "$OUTPUT_FILE" 2>&1
|
|
280
|
+
|
|
281
|
+
# Print summary to console
|
|
282
|
+
echo ""
|
|
283
|
+
echo "✅ Metrics collection complete!"
|
|
284
|
+
echo ""
|
|
285
|
+
echo "Summary:"
|
|
286
|
+
grep -E "CPU Usage|Memory Overview|Disk Usage|Active Connections|PostgreSQL Connection Count" "$OUTPUT_FILE" | head -20
|
|
287
|
+
echo ""
|
|
288
|
+
echo "Full report: $OUTPUT_FILE"
|
|
289
|
+
echo ""
|
|
290
|
+
echo "Next steps:"
|
|
291
|
+
echo " - Review metrics for anomalies"
|
|
292
|
+
echo " - Compare with baseline metrics"
|
|
293
|
+
echo " - Share with team for analysis"
|
|
294
|
+
echo ""
|