codex-genesis-harness 0.1.0 → 0.1.4
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/.codebase/API_CONTRACTS.md +12 -0
- package/.codebase/ARCHITECTURE.md +6 -0
- package/.codebase/ARCHITECTURE_REVIEW_COMPLETE.md +216 -0
- package/.codebase/CURRENT_STATE.md +8 -0
- package/.codebase/DEPENDENCY_GRAPH.md +14 -0
- package/.codebase/DOMAIN_MODELS.md +10 -0
- package/.codebase/EVOLUTION_PLAN.md +35 -0
- package/.codebase/FILE_NAMING_CLARIFICATION.md +161 -0
- package/.codebase/HARNESS_COMPLETENESS_AUDIT.md +613 -0
- package/.codebase/IMPLEMENTATION_COMPLETE.md +429 -0
- package/.codebase/IMPLEMENTATION_HANDOFF.md +351 -0
- package/.codebase/IMPROVEMENTS_SUMMARY.md +419 -0
- package/.codebase/KNOWN_PROBLEMS.md +6 -0
- package/.codebase/MODULE_INDEX.md +13 -0
- package/.codebase/PHASE3_SKILLS_NAMING_COMPLETE.md +292 -0
- package/.codebase/PHASE_DEPENDENCY_MAP.md +486 -0
- package/.codebase/PIPELINE_FLOW.md +14 -0
- package/.codebase/QUICK_START_SPEC_IMPACT.md +456 -0
- package/.codebase/README.md +139 -0
- package/.codebase/RECOVERY_POINTS.md +438 -0
- package/.codebase/TEST_MATRIX.md +11 -0
- package/.codebase/UI_ROUTES.md +4 -0
- package/.codebase/context/backend-summary.md +4 -0
- package/.codebase/context/frontend-summary.md +4 -0
- package/.codebase/context/pipeline-summary.md +4 -0
- package/.codebase/context/providers-summary.md +4 -0
- package/.codebase/context/render-summary.md +4 -0
- package/.codebase/context/tests-summary.md +4 -0
- package/.codex/skills/genesis-ai-provider/SKILL.md +46 -0
- package/.codex/skills/genesis-ai-provider/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-ai-provider/checklists/checklist.md +9 -0
- package/.codex/skills/genesis-ai-provider/examples/example.md +4 -0
- package/.codex/skills/genesis-ai-provider/templates/provider-contract-template.md +9 -0
- package/.codex/skills/genesis-api-contract/SKILL.md +46 -0
- package/.codex/skills/genesis-api-contract/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-api-contract/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-api-contract/examples/example.md +4 -0
- package/.codex/skills/genesis-api-contract/templates/api-contract-template.md +4 -0
- package/.codex/skills/genesis-api-sync/SKILL.md +354 -0
- package/.codex/skills/genesis-api-sync/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-api-sync/checklists/api-sync-checklist.md +101 -0
- package/.codex/skills/genesis-api-sync/examples/example.md +68 -0
- package/.codex/skills/genesis-api-sync/templates/api-change-template.md +257 -0
- package/.codex/skills/genesis-architecture/SKILL.md +46 -0
- package/.codex/skills/genesis-architecture/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-architecture/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-architecture/examples/example.md +4 -0
- package/.codex/skills/genesis-architecture/templates/architecture-decision-template.md +14 -0
- package/.codex/skills/genesis-codebase-map/SKILL.md +46 -0
- package/.codex/skills/genesis-codebase-map/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-codebase-map/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-codebase-map/examples/example.md +4 -0
- package/.codex/skills/genesis-codebase-map/templates/map-update-template.md +8 -0
- package/.codex/skills/genesis-debug-guide/SKILL.md +479 -0
- package/.codex/skills/genesis-debug-guide/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-debug-guide/checklists/flaky-test-investigation.md +339 -0
- package/.codex/skills/genesis-debug-guide/checklists/production-bug-debug.md +210 -0
- package/.codex/skills/genesis-debug-guide/checklists/test-failure-debug.md +158 -0
- package/.codex/skills/genesis-debug-guide/examples/example.md +48 -0
- package/.codex/skills/genesis-debug-guide/observability/debug-commands.md +365 -0
- package/.codex/skills/genesis-debug-guide/playbooks/unit-test-failures.md +289 -0
- package/.codex/skills/genesis-debug-guide/templates/debug-investigation-log.md +288 -0
- package/.codex/skills/genesis-design-spec/SKILL.md +46 -0
- package/.codex/skills/genesis-design-spec/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-design-spec/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-design-spec/examples/example.md +4 -0
- package/.codex/skills/genesis-design-spec/templates/design-spec-template.md +9 -0
- package/.codex/skills/genesis-docs/SKILL.md +46 -0
- package/.codex/skills/genesis-docs/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-docs/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-docs/examples/example.md +4 -0
- package/.codex/skills/genesis-docs/templates/docs-update-template.md +8 -0
- package/.codex/skills/genesis-docs-automation/SKILL.md +1003 -0
- package/.codex/skills/genesis-docs-automation/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-docs-automation/checklists/docs-validation.md +359 -0
- package/.codex/skills/genesis-docs-automation/checklists/spec-alignment.md +312 -0
- package/.codex/skills/genesis-docs-automation/examples/example.md +59 -0
- package/.codex/skills/genesis-docs-automation/observability/docs-tracking.md +382 -0
- package/.codex/skills/genesis-docs-automation/playbooks/auto-update-flow.md +851 -0
- package/.codex/skills/genesis-docs-automation/playbooks/changelog-generation.md +491 -0
- package/.codex/skills/genesis-docs-automation/templates/changelog-entry-template.md +187 -0
- package/.codex/skills/genesis-docs-automation/templates/handoff-template.md +297 -0
- package/.codex/skills/genesis-harness/SKILL.md +1418 -0
- package/.codex/skills/genesis-harness/agents/openai.yaml +9 -0
- package/.codex/skills/genesis-harness/checklists/bug-fix-qa.md +169 -0
- package/.codex/skills/genesis-harness/checklists/checklist.md +10 -0
- package/.codex/skills/genesis-harness/checklists/new-feature-qa.md +157 -0
- package/.codex/skills/genesis-harness/checklists/refactor-qa.md +216 -0
- package/.codex/skills/genesis-harness/checklists/requirements-validation.md +211 -0
- package/.codex/skills/genesis-harness/examples/example.md +4 -0
- package/.codex/skills/genesis-harness/resources/change-impact-matrix-template.md +204 -0
- package/.codex/skills/genesis-harness/resources/foundation-phase-template.md +131 -0
- package/.codex/skills/genesis-harness/resources/phase-00-foundation-template.md +76 -0
- package/.codex/skills/genesis-harness/resources/post-implementation-guide.md +347 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-architecture-boundaries.sh +23 -23
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-docs-sync.sh +24 -24
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-no-debug-logs.sh +21 -21
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-required-planning-files.sh +46 -46
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-spec-changelog.sh +24 -24
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-task-tracking.sh +25 -25
- package/.codex/skills/genesis-harness/scripts/compact-context.sh +54 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/create-adr.sh +74 -74
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/create-bug.sh +160 -160
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/create-feature.sh +217 -217
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/detect-stack.sh +26 -26
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/init-planning.sh +750 -719
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/list-changed-files.sh +12 -12
- package/.codex/skills/genesis-harness/scripts/offload-log.sh +72 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/run-verification.sh +47 -47
- package/.codex/skills/genesis-harness/scripts/run-verify-loop.sh +75 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/update-state.sh +33 -33
- package/.codex/skills/genesis-harness/templates/harness-workflow-template.md +10 -0
- package/.codex/skills/genesis-harness-engineering/SKILL.md +159 -0
- package/.codex/skills/genesis-harness-engineering/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-harness-engineering/checklists/checklist.md +48 -0
- package/.codex/skills/genesis-harness-engineering/examples/example.md +57 -0
- package/.codex/skills/genesis-harness-engineering/playbooks/harness-evolution.md +99 -0
- package/.codex/skills/genesis-harness-engineering/templates/harness-change-template.md +37 -0
- package/.codex/skills/genesis-new-design/SKILL.md +95 -0
- package/.codex/skills/genesis-new-design/agents/openai.yaml +4 -0
- package/.codex/skills/genesis-new-design/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-new-design/examples/example.md +4 -0
- package/.codex/skills/genesis-new-design/templates/new-design-template.md +9 -0
- package/.codex/skills/genesis-observability-automation/SKILL.md +382 -0
- package/.codex/skills/genesis-observability-automation/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-observability-automation/examples/example.md +86 -0
- package/.codex/skills/genesis-performance-profiling/SKILL.md +510 -0
- package/.codex/skills/genesis-performance-profiling/agents/openai.yaml +6 -0
- package/.codex/skills/genesis-performance-profiling/checklists/optimization-verification.md +199 -0
- package/.codex/skills/genesis-performance-profiling/checklists/performance-baseline.md +183 -0
- package/.codex/skills/genesis-performance-profiling/examples/example.md +234 -0
- package/.codex/skills/genesis-performance-profiling/observability/performance-tracking.md +202 -0
- package/.codex/skills/genesis-performance-profiling/playbooks/load-testing-orchestration.md +593 -0
- package/.codex/skills/genesis-performance-profiling/playbooks/profiling-playbook.md +601 -0
- package/.codex/skills/genesis-performance-profiling/templates/load-test-config-template.md +428 -0
- package/.codex/skills/genesis-performance-profiling/templates/performance-report-template.md +238 -0
- package/.codex/skills/genesis-pipeline-orchestration/SKILL.md +46 -0
- package/.codex/skills/genesis-pipeline-orchestration/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-pipeline-orchestration/checklists/checklist.md +12 -0
- package/.codex/skills/genesis-pipeline-orchestration/examples/example.md +4 -0
- package/.codex/skills/genesis-pipeline-orchestration/templates/orchestration-template.md +12 -0
- package/.codex/skills/genesis-planning/SKILL.md +46 -0
- package/.codex/skills/genesis-planning/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-planning/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-planning/examples/example.md +4 -0
- package/.codex/skills/genesis-planning/templates/plan-template.md +11 -0
- package/.codex/skills/genesis-release/SKILL.md +46 -0
- package/.codex/skills/genesis-release/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-release/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-release/examples/example.md +4 -0
- package/.codex/skills/genesis-release/templates/release-checklist-template.md +9 -0
- package/.codex/skills/genesis-release-orchestration/SKILL.md +653 -0
- package/.codex/skills/genesis-release-orchestration/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-release-orchestration/checklists/post-deployment-verification.md +274 -0
- package/.codex/skills/genesis-release-orchestration/checklists/pre-release-validation.md +220 -0
- package/.codex/skills/genesis-release-orchestration/examples/example.md +78 -0
- package/.codex/skills/genesis-release-orchestration/observability/release-tracking.md +253 -0
- package/.codex/skills/genesis-release-orchestration/playbooks/canary-deployment-orchestration.md +472 -0
- package/.codex/skills/genesis-release-orchestration/playbooks/semantic-versioning-automation.md +494 -0
- package/.codex/skills/genesis-release-orchestration/templates/deployment-strategy-template.md +303 -0
- package/.codex/skills/genesis-release-orchestration/templates/release-runbook-template.md +420 -0
- package/.codex/skills/genesis-research/SKILL.md +46 -0
- package/.codex/skills/genesis-research/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-research/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-research/examples/example.md +4 -0
- package/.codex/skills/genesis-research/templates/research-note-template.md +9 -0
- package/.codex/skills/genesis-research-first/SKILL.md +237 -0
- package/.codex/skills/genesis-research-first/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-research-first/examples/example.md +85 -0
- package/.codex/skills/genesis-spec-propagation/SKILL.md +534 -0
- package/.codex/skills/genesis-spec-propagation/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-spec-propagation/checklists/phase-update-verification.md +384 -0
- package/.codex/skills/genesis-spec-propagation/checklists/spec-change-detection.md +257 -0
- package/.codex/skills/genesis-spec-propagation/examples/example.md +63 -0
- package/.codex/skills/genesis-spec-propagation/observability/propagation-tracking.md +373 -0
- package/.codex/skills/genesis-spec-propagation/playbooks/breaking-change-propagation.md +692 -0
- package/.codex/skills/genesis-spec-propagation/playbooks/feature-change-propagation.md +434 -0
- package/.codex/skills/genesis-spec-propagation/templates/migration-guide-template.md +407 -0
- package/.codex/skills/genesis-upgrade-design/SKILL.md +97 -0
- package/.codex/skills/genesis-upgrade-design/agents/openai.yaml +4 -0
- package/.codex/skills/genesis-upgrade-design/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-upgrade-design/examples/example.md +4 -0
- package/.codex/skills/genesis-upgrade-design/templates/upgrade-design-template.md +9 -0
- package/.codex/skills/spec-impact-engine/SKILL.md +504 -0
- package/.codex/skills/spec-impact-engine/agents/openai.yaml +7 -0
- package/.codex/skills/spec-impact-engine/detect-spec-changes.sh +262 -0
- package/.codex/skills/spec-impact-engine/examples/example.md +98 -0
- package/.codex/skills/spec-impact-engine/templates/impact-report.md +248 -0
- package/.codex/skills/spec-impact-engine/templates/migration-guide.md +223 -0
- package/.codex/skills/ui-ux-test-skill/SKILL.md +46 -0
- package/.codex/skills/ui-ux-test-skill/agents/openai.yaml +7 -0
- package/.codex/skills/ui-ux-test-skill/checklists/checklist.md +8 -0
- package/.codex/skills/ui-ux-test-skill/examples/example.md +4 -0
- package/.codex/skills/ui-ux-test-skill/templates/playwright-test-template.md +4 -0
- package/.codex-plugin/plugin.json +13 -11
- package/README.EN.md +719 -0
- package/README.VI.md +712 -0
- package/README.md +318 -181
- package/VERSION +1 -1
- package/bin/genesis-harness.js +133 -79
- package/contracts/agents/CharacterBibleAgent/error.json +1 -0
- package/contracts/agents/CharacterBibleAgent/example.json +1 -0
- package/contracts/agents/CharacterBibleAgent/request.json +1 -0
- package/contracts/agents/CharacterBibleAgent/response.json +1 -0
- package/contracts/agents/CharacterBibleAgent/schema.json +1 -0
- package/contracts/agents/ImageGenerationAgent/error.json +1 -0
- package/contracts/agents/ImageGenerationAgent/example.json +1 -0
- package/contracts/agents/ImageGenerationAgent/request.json +1 -0
- package/contracts/agents/ImageGenerationAgent/response.json +1 -0
- package/contracts/agents/ImageGenerationAgent/schema.json +1 -0
- package/contracts/agents/PipelineOrchestrator/error.json +1 -0
- package/contracts/agents/PipelineOrchestrator/example.json +1 -0
- package/contracts/agents/PipelineOrchestrator/request.json +1 -0
- package/contracts/agents/PipelineOrchestrator/response.json +1 -0
- package/contracts/agents/PipelineOrchestrator/schema.json +1 -0
- package/contracts/agents/PromptGenerationAgent/error.json +1 -0
- package/contracts/agents/PromptGenerationAgent/example.json +1 -0
- package/contracts/agents/PromptGenerationAgent/request.json +1 -0
- package/contracts/agents/PromptGenerationAgent/response.json +1 -0
- package/contracts/agents/PromptGenerationAgent/schema.json +1 -0
- package/contracts/agents/RenderAgent/error.json +1 -0
- package/contracts/agents/RenderAgent/example.json +1 -0
- package/contracts/agents/RenderAgent/request.json +1 -0
- package/contracts/agents/RenderAgent/response.json +1 -0
- package/contracts/agents/RenderAgent/schema.json +1 -0
- package/contracts/agents/ScenePlanningAgent/error.json +1 -0
- package/contracts/agents/ScenePlanningAgent/example.json +1 -0
- package/contracts/agents/ScenePlanningAgent/request.json +1 -0
- package/contracts/agents/ScenePlanningAgent/response.json +1 -0
- package/contracts/agents/ScenePlanningAgent/schema.json +1 -0
- package/contracts/agents/ScreenplayAgent/error.json +1 -0
- package/contracts/agents/ScreenplayAgent/example.json +1 -0
- package/contracts/agents/ScreenplayAgent/request.json +1 -0
- package/contracts/agents/ScreenplayAgent/response.json +1 -0
- package/contracts/agents/ScreenplayAgent/schema.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/error.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/example.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/request.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/response.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/schema.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/error.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/example.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/request.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/response.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/schema.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/error.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/example.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/request.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/response.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/schema.json +1 -0
- package/contracts/api/README.md +4 -0
- package/contracts/api/endpoint-template/error.json +7 -0
- package/contracts/api/endpoint-template/example.json +11 -0
- package/contracts/api/endpoint-template/request.json +7 -0
- package/contracts/api/endpoint-template/response.json +6 -0
- package/contracts/api/endpoint-template/schema.json +9 -0
- package/contracts/events/README.md +4 -0
- package/contracts/events/event-template/error.json +4 -0
- package/contracts/events/event-template/example.json +6 -0
- package/contracts/events/event-template/request.json +6 -0
- package/contracts/events/event-template/response.json +3 -0
- package/contracts/events/event-template/schema.json +8 -0
- package/contracts/ui/README.md +4 -0
- package/contracts/ui/screen-template/error.json +4 -0
- package/contracts/ui/screen-template/example.json +7 -0
- package/contracts/ui/screen-template/request.json +4 -0
- package/contracts/ui/screen-template/response.json +4 -0
- package/contracts/ui/screen-template/schema.json +8 -0
- package/fixtures/agents/agent-fixture-template.md +14 -0
- package/fixtures/api/api-fixture-template.md +14 -0
- package/fixtures/images/image-fixture-template.md +14 -0
- package/fixtures/pipeline/pipeline-fixture-template.md +14 -0
- package/fixtures/render/render-fixture-template.md +14 -0
- package/fixtures/tts/tts-fixture-template.md +14 -0
- package/fixtures/videos/video-fixture-template.md +14 -0
- package/observability/agent-runs/agent-run-template.md +22 -0
- package/observability/decision-logs/decision-log-template.md +18 -0
- package/observability/failures/failure-template.md +18 -0
- package/package.json +8 -2
- package/playwright/e2e/e2e-template.md +4 -0
- package/playwright/fixtures/ui-fixture-template.md +4 -0
- package/playwright/smoke/smoke-template.md +4 -0
- package/playwright/visual/visual-regression-template.md +4 -0
- package/scripts/README.md +342 -0
- package/scripts/compact-context.sh +54 -0
- package/scripts/detect-changes.sh +152 -0
- package/scripts/install.sh +103 -69
- package/scripts/offload-log.sh +72 -0
- package/scripts/run-evals.sh +118 -52
- package/scripts/run-verify-loop.sh +75 -0
- package/scripts/uninstall.sh +81 -52
- package/scripts/verify.sh +380 -109
- package/tests/contracts/contract-template.test.md +10 -0
- package/tests/fixtures/fixture-index.md +4 -0
- package/tests/integration/integration-template.test.md +4 -0
- package/tests/unit/unit-template.test.md +4 -0
- package/.codex/skills/project-genesis-harness/SKILL.md +0 -727
- package/.codex/skills/project-genesis-harness/agents/openai.yaml +0 -9
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/planning-schema.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/quality-rubric.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/research-rubric.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/workflows.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/agents-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/api-docs-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/architecture-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/audit-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/bug-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/check-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/conventions-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/decision-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/design-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/escalation-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/feature-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/integrations-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/journeys-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/lessons-learned-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/observability-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/phase-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/pitfalls-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/planning-tree-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/project-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/quality-score-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/requirements-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/research-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/review-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/spec-changelog-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/stack-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/verification-template.md +0 -0
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
# Profiling Playbook
|
|
2
|
+
|
|
3
|
+
This playbook provides step-by-step profiling instructions for identifying performance bottlenecks across languages and bottleneck types. Follow the decision tree in Phase 2 of the SKILL.md to select the right profiling approach, then use the corresponding section here.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Decision Tree: Select Your Profiling Approach
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Is CPU > 70% during test?
|
|
11
|
+
├── YES → Go to Section 1 (CPU Profiling) for your language
|
|
12
|
+
└── NO → Is memory growing unboundedly over time?
|
|
13
|
+
├── YES → Go to Section 2 (Memory Profiling)
|
|
14
|
+
└── NO → Is DB query time > 50% of response time?
|
|
15
|
+
├── YES → Go to Section 3 (Database Query Analysis)
|
|
16
|
+
└── NO → Is network latency or connection time high?
|
|
17
|
+
├── YES → Go to Section 4 (Network I/O Profiling)
|
|
18
|
+
└── NO → Go to Section 5 (Async Call Stack Tracing)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Section 1: CPU Profiling
|
|
24
|
+
|
|
25
|
+
### 1.1 Node.js CPU Profiling
|
|
26
|
+
|
|
27
|
+
#### Method A: clinic.js (recommended for web services)
|
|
28
|
+
|
|
29
|
+
clinic.js produces beautiful flame graphs and auto-detects common Node.js issues.
|
|
30
|
+
|
|
31
|
+
**Installation:**
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g clinic
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Profile a running server under load:**
|
|
37
|
+
```bash
|
|
38
|
+
# Terminal 1: Start server under clinic
|
|
39
|
+
clinic doctor -- node server.js
|
|
40
|
+
|
|
41
|
+
# Terminal 2: Apply load while profiling
|
|
42
|
+
k6 run --vus 50 --duration 60s load-test.js
|
|
43
|
+
|
|
44
|
+
# Stop server (Ctrl+C). clinic auto-generates report.
|
|
45
|
+
# Open the generated HTML flame graph in browser.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Interpret the output:**
|
|
49
|
+
- Red bars = CPU-intensive functions (hot path candidates).
|
|
50
|
+
- Blue bars = I/O wait time.
|
|
51
|
+
- Look for user-land code (your code) at the top of red stacks, not Node.js internals.
|
|
52
|
+
- clinic doctor will show a recommendation panel: "I/O bottleneck detected", "Event loop blocked", etc.
|
|
53
|
+
|
|
54
|
+
**Profile a specific endpoint:**
|
|
55
|
+
```bash
|
|
56
|
+
# Use autocannon to generate targeted load
|
|
57
|
+
clinic flame -- node server.js &
|
|
58
|
+
SERVER_PID=$!
|
|
59
|
+
autocannon -c 50 -d 30 http://localhost:3000/api/users
|
|
60
|
+
kill $SERVER_PID
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Method B: V8 --prof flag (for precise hot function identification)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Run with V8 profiler
|
|
67
|
+
node --prof server.js &
|
|
68
|
+
SERVER_PID=$!
|
|
69
|
+
|
|
70
|
+
# Apply load
|
|
71
|
+
k6 run --vus 50 --duration 60s load-test.js
|
|
72
|
+
|
|
73
|
+
# Stop server
|
|
74
|
+
kill $SERVER_PID
|
|
75
|
+
|
|
76
|
+
# Process the profile (creates isolate-*.log files)
|
|
77
|
+
node --prof-process isolate-*.log > processed-profile.txt
|
|
78
|
+
|
|
79
|
+
# Read the output: look for "[Summary]" section
|
|
80
|
+
# "ticks" = CPU samples. High tick count = hot path.
|
|
81
|
+
grep -A 50 "\[Summary\]" processed-profile.txt
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Read the profile output:**
|
|
85
|
+
```
|
|
86
|
+
Statistical profiling result from isolate-0x...log (1234 ticks)
|
|
87
|
+
|
|
88
|
+
[Summary]:
|
|
89
|
+
ticks total nonlib name
|
|
90
|
+
456 37.0% 42.1% LazyCompile: *parseJSON node:internal/deps/undici/...
|
|
91
|
+
234 19.0% 21.6% LazyCompile: *serialize /app/src/utils/serializer.js:45
|
|
92
|
+
123 10.0% 11.4% LazyCompile: *getUser /app/src/routes/users.js:23
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
In this example, `serialize` in `serializer.js:45` is your hot path — it's taking 19% of all CPU time.
|
|
96
|
+
|
|
97
|
+
#### Method C: 0x (flame graph only, minimal overhead)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install -g 0x
|
|
101
|
+
0x -- node server.js
|
|
102
|
+
# Apply load, then Ctrl+C
|
|
103
|
+
# Opens flamegraph.html automatically
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 1.2 Python CPU Profiling
|
|
107
|
+
|
|
108
|
+
#### Method A: py-spy (production-safe, minimal overhead)
|
|
109
|
+
|
|
110
|
+
py-spy attaches to a running process without modifying the code — safe to use in staging under real load.
|
|
111
|
+
|
|
112
|
+
**Installation:**
|
|
113
|
+
```bash
|
|
114
|
+
pip install py-spy
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Profile a running process:**
|
|
118
|
+
```bash
|
|
119
|
+
# Find the PID of your Python service
|
|
120
|
+
ps aux | grep python
|
|
121
|
+
|
|
122
|
+
# Record a flame graph (60 seconds under load)
|
|
123
|
+
sudo py-spy record -o flamegraph.svg --pid 12345 --duration 60
|
|
124
|
+
|
|
125
|
+
# Open flamegraph.svg in a browser
|
|
126
|
+
# Wide frames = time spent in that function
|
|
127
|
+
# Look for your application code (not stdlib) that is wide
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Profile with top-like live view:**
|
|
131
|
+
```bash
|
|
132
|
+
sudo py-spy top --pid 12345
|
|
133
|
+
# Updates every 1 second. Shows which functions are consuming CPU right now.
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Method B: cProfile (for offline/script profiling)
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
# Wrap the slow function or script:
|
|
140
|
+
import cProfile
|
|
141
|
+
import pstats
|
|
142
|
+
import io
|
|
143
|
+
|
|
144
|
+
pr = cProfile.Profile()
|
|
145
|
+
pr.enable()
|
|
146
|
+
|
|
147
|
+
# --- your code here ---
|
|
148
|
+
result = slow_function(input_data)
|
|
149
|
+
# --- end of code ---
|
|
150
|
+
|
|
151
|
+
pr.disable()
|
|
152
|
+
|
|
153
|
+
s = io.StringIO()
|
|
154
|
+
ps = pstats.Stats(pr, stream=s).sort_stats('cumulative')
|
|
155
|
+
ps.print_stats(20) # top 20 functions by cumulative time
|
|
156
|
+
print(s.getvalue())
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Run and analyze:**
|
|
160
|
+
```bash
|
|
161
|
+
python -m cProfile -o profile.out your_script.py
|
|
162
|
+
python -m pstats profile.out
|
|
163
|
+
# In pstats interactive mode:
|
|
164
|
+
# sort cumtime # sort by cumulative time
|
|
165
|
+
# stats 20 # show top 20
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### Method C: line_profiler (line-by-line timing)
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
pip install line_profiler
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# Decorate the specific function you want to profile:
|
|
176
|
+
@profile
|
|
177
|
+
def slow_function(data):
|
|
178
|
+
result = []
|
|
179
|
+
for item in data: # Line A
|
|
180
|
+
processed = transform(item) # Line B — this is the hot line
|
|
181
|
+
result.append(processed)
|
|
182
|
+
return result
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
kernprof -l -v your_script.py
|
|
187
|
+
# Output shows time per line:
|
|
188
|
+
# Line A: 1.2 ms total (10 hits)
|
|
189
|
+
# Line B: 8.9 ms total (10 hits) ← hot line
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 1.3 Go CPU Profiling with pprof
|
|
193
|
+
|
|
194
|
+
#### Method A: HTTP pprof endpoint (for running services)
|
|
195
|
+
|
|
196
|
+
Add to your service (already included if using `net/http/pprof`):
|
|
197
|
+
```go
|
|
198
|
+
import _ "net/http/pprof"
|
|
199
|
+
|
|
200
|
+
// In main():
|
|
201
|
+
go func() {
|
|
202
|
+
log.Println(http.ListenAndServe(":6060", nil))
|
|
203
|
+
}()
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Capture and analyze:**
|
|
207
|
+
```bash
|
|
208
|
+
# Apply load first (30+ seconds)
|
|
209
|
+
k6 run --vus 50 --duration 60s load-test.js &
|
|
210
|
+
|
|
211
|
+
# Capture 30-second CPU profile
|
|
212
|
+
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=30
|
|
213
|
+
|
|
214
|
+
# Browser opens at localhost:8080 with interactive flame graph
|
|
215
|
+
# Navigate to "Flame Graph" view
|
|
216
|
+
# Look for wide red bars (your hot functions)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Command-line analysis:**
|
|
220
|
+
```bash
|
|
221
|
+
# Download profile
|
|
222
|
+
curl -o cpu.pprof http://localhost:6060/debug/pprof/profile?seconds=30
|
|
223
|
+
|
|
224
|
+
# Analyze in interactive mode
|
|
225
|
+
go tool pprof cpu.pprof
|
|
226
|
+
# Commands in pprof:
|
|
227
|
+
(pprof) top 10 # Top 10 functions by CPU
|
|
228
|
+
(pprof) list ParseJSON # Show annotated source for ParseJSON
|
|
229
|
+
(pprof) web # Open flame graph in browser
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Method B: Unit test CPU benchmark
|
|
233
|
+
|
|
234
|
+
```go
|
|
235
|
+
func BenchmarkSlowFunction(b *testing.B) {
|
|
236
|
+
data := generateTestData()
|
|
237
|
+
b.ResetTimer()
|
|
238
|
+
for i := 0; i < b.N; i++ {
|
|
239
|
+
SlowFunction(data)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Run benchmark with CPU profile
|
|
246
|
+
go test -bench=BenchmarkSlowFunction -cpuprofile=cpu.pprof ./...
|
|
247
|
+
go tool pprof -http=:8080 cpu.pprof
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Section 2: Memory Profiling
|
|
253
|
+
|
|
254
|
+
### 2.1 Node.js Memory Leak Detection
|
|
255
|
+
|
|
256
|
+
#### Protocol: Heap Snapshot Comparison
|
|
257
|
+
|
|
258
|
+
Memory leaks are identified by comparing heap snapshots at regular intervals and looking for object counts that grow monotonically.
|
|
259
|
+
|
|
260
|
+
**Step 1: Enable heap snapshot capture**
|
|
261
|
+
```javascript
|
|
262
|
+
// Add to your service (NOT in production — introduces overhead):
|
|
263
|
+
const v8 = require('v8');
|
|
264
|
+
const fs = require('fs');
|
|
265
|
+
|
|
266
|
+
function takeHeapSnapshot(label) {
|
|
267
|
+
const snapshotStream = v8.writeHeapSnapshot();
|
|
268
|
+
fs.renameSync(snapshotStream, `heap-${label}-${Date.now()}.heapsnapshot`);
|
|
269
|
+
console.log(`Heap snapshot written: heap-${label}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Schedule snapshots every 5 minutes
|
|
273
|
+
setInterval(() => takeHeapSnapshot('t' + (Date.now() / 60000 | 0)), 5 * 60 * 1000);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Step 2: Apply steady load for 15+ minutes**
|
|
277
|
+
```bash
|
|
278
|
+
k6 run --vus 30 --duration 15m steady-load.js
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Step 3: Collect snapshots at t=0, t=5min, t=10min, t=15min**
|
|
282
|
+
You should have: `heap-t0.heapsnapshot`, `heap-t5.heapsnapshot`, `heap-t10.heapsnapshot`, `heap-t15.heapsnapshot`
|
|
283
|
+
|
|
284
|
+
**Step 4: Analyze in Chrome DevTools**
|
|
285
|
+
1. Open Chrome → F12 → Memory tab.
|
|
286
|
+
2. Load each `.heapsnapshot` file via "Load" button.
|
|
287
|
+
3. Switch to "Comparison" view between snapshots.
|
|
288
|
+
4. Sort by "Size Delta" descending.
|
|
289
|
+
5. Objects growing monotonically are leak candidates.
|
|
290
|
+
|
|
291
|
+
**Interpreting the comparison:**
|
|
292
|
+
```
|
|
293
|
+
Object | t0 count | t5 count | t10 count | t15 count | Delta
|
|
294
|
+
---------------|----------|----------|-----------|-----------|-------
|
|
295
|
+
EventEmitter | 150 | 156 | 163 | 171 | +21 ← growing
|
|
296
|
+
Promise | 200 | 198 | 201 | 199 | stable
|
|
297
|
+
UserSession | 450 | 890 | 1340 | 1800 | +1350 ← LEAK
|
|
298
|
+
Buffer | 80 | 82 | 81 | 80 | stable
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
`UserSession` growing from 450 to 1800 objects over 15 minutes indicates sessions are not being cleaned up.
|
|
302
|
+
|
|
303
|
+
#### clinic.js Heap Profiling
|
|
304
|
+
```bash
|
|
305
|
+
clinic heapprofile -- node server.js
|
|
306
|
+
# Apply load
|
|
307
|
+
# Ctrl+C → generates heap profile HTML
|
|
308
|
+
# Shows allocation flame graph: which code paths are allocating memory
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### 2.2 Python Memory Profiling
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
pip install memory-profiler tracemalloc
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**tracemalloc (built-in, no install needed):**
|
|
318
|
+
```python
|
|
319
|
+
import tracemalloc
|
|
320
|
+
tracemalloc.start()
|
|
321
|
+
|
|
322
|
+
# --- run the suspect code ---
|
|
323
|
+
result = process_data(large_dataset)
|
|
324
|
+
# ---
|
|
325
|
+
|
|
326
|
+
snapshot = tracemalloc.take_snapshot()
|
|
327
|
+
top_stats = snapshot.statistics('lineno')
|
|
328
|
+
for stat in top_stats[:10]:
|
|
329
|
+
print(stat) # Shows: filename:line_number: size_kb KiB (count blocks)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**memory_profiler decorator:**
|
|
333
|
+
```python
|
|
334
|
+
from memory_profiler import profile
|
|
335
|
+
|
|
336
|
+
@profile
|
|
337
|
+
def suspect_function(data):
|
|
338
|
+
# memory usage shown line by line
|
|
339
|
+
result = [transform(x) for x in data] # ← if this line shows big growth
|
|
340
|
+
return result
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 2.3 Go Memory Profiling
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
# Capture heap profile
|
|
347
|
+
curl -o heap.pprof http://localhost:6060/debug/pprof/heap
|
|
348
|
+
|
|
349
|
+
# Analyze
|
|
350
|
+
go tool pprof -http=:8080 heap.pprof
|
|
351
|
+
# Navigate to "Flame Graph" and switch to "alloc_space" view
|
|
352
|
+
# Look for your code allocating large amounts of memory
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Goroutine leak detection:**
|
|
356
|
+
```bash
|
|
357
|
+
# Check goroutine count over time
|
|
358
|
+
curl http://localhost:6060/debug/pprof/goroutine?debug=1 | head -50
|
|
359
|
+
# If goroutine count grows over time, you have a goroutine leak
|
|
360
|
+
# The output shows the stack trace of each goroutine — look for stuck goroutines
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Section 3: Database Query Analysis
|
|
366
|
+
|
|
367
|
+
### 3.1 PostgreSQL: EXPLAIN ANALYZE
|
|
368
|
+
|
|
369
|
+
**Step 1: Identify slow queries from the slow query log**
|
|
370
|
+
```sql
|
|
371
|
+
-- Enable slow query logging (in postgresql.conf or via ALTER SYSTEM):
|
|
372
|
+
ALTER SYSTEM SET log_min_duration_statement = '100'; -- log queries > 100ms
|
|
373
|
+
SELECT pg_reload_conf();
|
|
374
|
+
|
|
375
|
+
-- Or use pg_stat_statements to find the worst queries:
|
|
376
|
+
SELECT
|
|
377
|
+
query,
|
|
378
|
+
calls,
|
|
379
|
+
total_time,
|
|
380
|
+
total_time / calls AS avg_time_ms,
|
|
381
|
+
rows / calls AS avg_rows
|
|
382
|
+
FROM pg_stat_statements
|
|
383
|
+
ORDER BY total_time DESC
|
|
384
|
+
LIMIT 20;
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
**Step 2: Run EXPLAIN ANALYZE on the worst query**
|
|
388
|
+
```sql
|
|
389
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
|
|
390
|
+
SELECT u.*, p.avatar_url, p.bio
|
|
391
|
+
FROM users u
|
|
392
|
+
JOIN profiles p ON u.id = p.user_id
|
|
393
|
+
WHERE u.tenant_id = $1
|
|
394
|
+
AND u.status = 'active'
|
|
395
|
+
ORDER BY u.created_at DESC
|
|
396
|
+
LIMIT 50;
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
**Step 3: Interpret the output**
|
|
400
|
+
```
|
|
401
|
+
Limit (cost=1234.5..1235.0 rows=50 width=240) (actual time=456.7..456.9 rows=50 loops=1)
|
|
402
|
+
-> Sort (cost=1234.5..1259.5 rows=10000 width=240) (actual time=456.6..456.7 rows=50 loops=1)
|
|
403
|
+
Sort Key: u.created_at DESC
|
|
404
|
+
Sort Method: external merge Disk: 8192kB ← PROBLEM: sorting to disk
|
|
405
|
+
-> Hash Join (cost=500.0..800.0 rows=10000 width=240) (actual time=120.0..300.0 rows=10000 loops=1)
|
|
406
|
+
Hash Cond: (p.user_id = u.id)
|
|
407
|
+
-> Seq Scan on profiles p ... ← PROBLEM: sequential scan
|
|
408
|
+
-> Seq Scan on users u ... ← PROBLEM: sequential scan
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Red flags in EXPLAIN output:**
|
|
412
|
+
- `Seq Scan` on large tables → Missing index. Add index on filter/join columns.
|
|
413
|
+
- `Sort Method: external merge Disk:` → Sort overflowing to disk. Add index on sort column or increase `work_mem`.
|
|
414
|
+
- `Rows Removed by Filter:` very high → Index not selective enough or query not using best index.
|
|
415
|
+
- `Loops:` > 1 on expensive steps → N+1 problem. Rewrite as a single JOIN.
|
|
416
|
+
- `actual time` much higher than `cost` estimate → Stale statistics. Run `ANALYZE tablename`.
|
|
417
|
+
|
|
418
|
+
**Step 4: Fix and verify**
|
|
419
|
+
```sql
|
|
420
|
+
-- Add composite index
|
|
421
|
+
CREATE INDEX CONCURRENTLY idx_users_tenant_status_created
|
|
422
|
+
ON users(tenant_id, status, created_at DESC);
|
|
423
|
+
|
|
424
|
+
-- Re-run EXPLAIN ANALYZE and confirm:
|
|
425
|
+
-- Seq Scan changed to Index Scan
|
|
426
|
+
-- actual time decreased significantly
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### 3.2 MySQL: EXPLAIN + Slow Query Log
|
|
430
|
+
|
|
431
|
+
```sql
|
|
432
|
+
-- Enable slow query log
|
|
433
|
+
SET GLOBAL slow_query_log = 'ON';
|
|
434
|
+
SET GLOBAL long_query_time = 0.1; -- log queries > 100ms
|
|
435
|
+
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
|
|
436
|
+
|
|
437
|
+
-- Analyze slow query
|
|
438
|
+
EXPLAIN FORMAT=JSON
|
|
439
|
+
SELECT * FROM users
|
|
440
|
+
WHERE tenant_id = 1 AND status = 'active'
|
|
441
|
+
ORDER BY created_at DESC LIMIT 50;
|
|
442
|
+
|
|
443
|
+
-- Check for missing indexes (type = ALL = full table scan)
|
|
444
|
+
-- key = NULL means no index used
|
|
445
|
+
-- rows = high number means scanning many rows
|
|
446
|
+
|
|
447
|
+
-- Add index
|
|
448
|
+
ALTER TABLE users ADD INDEX idx_tenant_status_created (tenant_id, status, created_at);
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### 3.3 MongoDB: Explain and Index Analysis
|
|
452
|
+
|
|
453
|
+
```javascript
|
|
454
|
+
// Find slow queries using explain
|
|
455
|
+
db.users.find({
|
|
456
|
+
tenant_id: ObjectId("..."),
|
|
457
|
+
status: "active"
|
|
458
|
+
}).sort({created_at: -1}).limit(50).explain("executionStats")
|
|
459
|
+
|
|
460
|
+
// Look for in executionStats:
|
|
461
|
+
// totalDocsExamined >> nReturned → inefficient scan
|
|
462
|
+
// executionTimeMillis → total query time
|
|
463
|
+
// winningPlan.stage = "COLLSCAN" → no index used (bad)
|
|
464
|
+
// winningPlan.stage = "IXSCAN" → index used (good)
|
|
465
|
+
|
|
466
|
+
// Add compound index
|
|
467
|
+
db.users.createIndex(
|
|
468
|
+
{ tenant_id: 1, status: 1, created_at: -1 },
|
|
469
|
+
{ background: true } // non-blocking in older MongoDB; use createIndex in 4.2+
|
|
470
|
+
)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## Section 4: Network I/O Bottleneck Detection
|
|
476
|
+
|
|
477
|
+
### 4.1 Connection Pool Analysis
|
|
478
|
+
|
|
479
|
+
**Node.js (using pg pool):**
|
|
480
|
+
```javascript
|
|
481
|
+
const { Pool } = require('pg');
|
|
482
|
+
const pool = new Pool({ max: 20, idleTimeoutMillis: 30000 });
|
|
483
|
+
|
|
484
|
+
// Instrument pool events
|
|
485
|
+
pool.on('connect', () => metrics.increment('db.connections.new'));
|
|
486
|
+
pool.on('acquire', () => metrics.increment('db.connections.acquire'));
|
|
487
|
+
pool.on('remove', () => metrics.increment('db.connections.remove'));
|
|
488
|
+
|
|
489
|
+
// Log when pool is exhausted (waiters > 0)
|
|
490
|
+
setInterval(() => {
|
|
491
|
+
const stats = pool.totalCount + ' total, ' + pool.idleCount + ' idle, ' + pool.waitingCount + ' waiting';
|
|
492
|
+
if (pool.waitingCount > 0) console.warn('Pool pressure: ' + stats);
|
|
493
|
+
}, 5000);
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
If `waitingCount` is consistently > 0 under load: the pool is a bottleneck. Solutions:
|
|
497
|
+
1. Increase pool size (if DB can handle more connections).
|
|
498
|
+
2. Reduce query duration (so connections are released sooner).
|
|
499
|
+
3. Add read replicas and route reads to them (separate pool).
|
|
500
|
+
|
|
501
|
+
### 4.2 TLS Handshake Overhead
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
# Measure TLS overhead vs. plain HTTP
|
|
505
|
+
# Time a single HTTPS request showing breakdown
|
|
506
|
+
curl -w "dns: %{time_namelookup}s | connect: %{time_connect}s | tls: %{time_appconnect}s | ttfb: %{time_starttransfer}s | total: %{time_total}s\n" \
|
|
507
|
+
-o /dev/null -s https://api.example.com/api/health
|
|
508
|
+
|
|
509
|
+
# High time_appconnect = TLS handshake is expensive
|
|
510
|
+
# Fix: Enable TLS session resumption / HTTP/2 connection reuse
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### 4.3 DNS Resolution Profiling
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
# Measure DNS resolution time
|
|
517
|
+
time dig api.example.com
|
|
518
|
+
|
|
519
|
+
# If DNS is slow (> 50ms), solutions:
|
|
520
|
+
# 1. Use internal DNS (private hosted zone)
|
|
521
|
+
# 2. Cache DNS responses in service (respect TTL)
|
|
522
|
+
# 3. Use connection keep-alive (avoid repeated DNS per request)
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
## Section 5: Real Example — Profiling a Slow REST API Endpoint
|
|
528
|
+
|
|
529
|
+
**Scenario**: `GET /api/users` is taking 450 ms (p95). SLA is 200 ms. Users are complaining.
|
|
530
|
+
|
|
531
|
+
### Step 1: Capture baseline
|
|
532
|
+
```bash
|
|
533
|
+
k6 run --vus 50 --duration 5m - <<EOF
|
|
534
|
+
import http from 'k6/http';
|
|
535
|
+
export default function() {
|
|
536
|
+
http.get('https://api.staging.example.com/api/users', {
|
|
537
|
+
headers: { 'Authorization': 'Bearer test-token' }
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
export let options = { thresholds: { 'http_req_duration': ['p(95)<200'] } };
|
|
541
|
+
EOF
|
|
542
|
+
# Result: p95=450ms (FAIL — 2.25× over SLA)
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Step 2: CPU profile (30 seconds under load)
|
|
546
|
+
```bash
|
|
547
|
+
clinic doctor -- node server.js &
|
|
548
|
+
k6 run --vus 30 --duration 30s load-test.js
|
|
549
|
+
# Result: clinic shows "I/O bottleneck" — not CPU bound
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Step 3: Database analysis
|
|
553
|
+
```sql
|
|
554
|
+
SELECT query, calls, total_time/calls as avg_ms
|
|
555
|
+
FROM pg_stat_statements ORDER BY avg_ms DESC LIMIT 5;
|
|
556
|
+
-- Result: "SELECT * FROM users WHERE tenant_id=$1" → 380ms avg
|
|
557
|
+
-- This query accounts for 84% of response time!
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
```sql
|
|
561
|
+
EXPLAIN ANALYZE SELECT * FROM users WHERE tenant_id = 1;
|
|
562
|
+
-- Result: Seq Scan on users (cost=0..45000) actual time=380ms
|
|
563
|
+
-- Table has 500,000 rows. No index on tenant_id!
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### Step 4: Fix
|
|
567
|
+
```sql
|
|
568
|
+
CREATE INDEX CONCURRENTLY idx_users_tenant_id ON users(tenant_id);
|
|
569
|
+
-- Also fix N+1: application was calling SELECT * FROM profiles WHERE user_id=$1 for each user
|
|
570
|
+
-- Fix: JOIN profiles in the main query
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
```javascript
|
|
574
|
+
// Before (N+1):
|
|
575
|
+
const users = await db.query('SELECT * FROM users WHERE tenant_id=$1', [tenantId]);
|
|
576
|
+
for (const user of users.rows) {
|
|
577
|
+
user.profile = await db.query('SELECT * FROM profiles WHERE user_id=$1', [user.id]);
|
|
578
|
+
// → 1 + N queries!
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// After (single JOIN):
|
|
582
|
+
const users = await db.query(`
|
|
583
|
+
SELECT u.*, p.avatar_url, p.bio
|
|
584
|
+
FROM users u
|
|
585
|
+
LEFT JOIN profiles p ON u.id = p.user_id
|
|
586
|
+
WHERE u.tenant_id = $1
|
|
587
|
+
`, [tenantId]);
|
|
588
|
+
// → 1 query total
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### Step 5: Verify
|
|
592
|
+
```bash
|
|
593
|
+
k6 run --vus 50 --duration 5m load-test.js
|
|
594
|
+
# Result: p95=42ms (PASS — 79% improvement, well under 200ms SLA)
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
**Summary of findings:**
|
|
598
|
+
- Root cause: Missing index on `users.tenant_id` + N+1 query pattern.
|
|
599
|
+
- Fix: Added index (1 migration), fixed N+1 (3 lines of code change).
|
|
600
|
+
- Before: p95=450 ms. After: p95=42 ms. **Improvement: 90.7%**.
|
|
601
|
+
- SLA compliance: ✅ PASS (42ms vs 200ms SLA).
|