Skip to content

feat: local dev stack (20 profiles), observability, metrics, load testing#31

Merged
ankurs merged 17 commits intomainfrom
feat/docker-compose-local-stack
Apr 9, 2026
Merged

feat: local dev stack (20 profiles), observability, metrics, load testing#31
ankurs merged 17 commits intomainfrom
feat/docker-compose-local-stack

Conversation

@ankurs
Copy link
Copy Markdown
Member

@ankurs ankurs commented Apr 8, 2026

Summary

Adds complete local development infrastructure, observability, application metrics, and load testing to the cookiecutter template.

Docker Compose local stack (docker-compose.local.yml)

  • 20 per-service profiles: postgres, mysql, cockroachdb, mongodb, redis, valkey, memcached, kafka (apache/kafka), nats, elasticsearch, ministack, dynamodb, spanner, pubsub, bigtable, firestore, alloydb, adminer
  • User selects services during generation via local_services prompt (options shown inline)
  • PROFILES default in Makefile rendered from user's selection
  • make local-stack starts selected services, make local-stack-obs adds observability
  • make local-stack-down stops everything, make local-exec SVC=... CMD=... for any service
  • --remove-orphans cleans up stale containers, --wait with health checks for real readiness
  • Health checks for postgres, mysql, redis, elasticsearch
  • extra_hosts: host.docker.internal:host-gateway for Linux compatibility
  • include_docker_compose flag (default: true) removes compose + deploy when false

Full observability stack (obs profile)

  • Prometheus scraping app on host + Grafana with pre-built ColdBrew dashboard (RED overview, status codes, latency by method, Go runtime)
  • Jaeger all-in-one with OTLP receiver — traces flow automatically via OTLP_ENDPOINT in local.env
  • Grafana datasource UID matches dashboard panels for zero-config first-run experience

Application metrics (service/metrics/)

  • Interface-based Metrics package — mockable via mockery
  • promauto registration: echo_total (counter), echo_duration_seconds (histogram)
  • Uses seconds for durations (Prometheus convention)
  • Wired into Echo handler with defer pattern for timing + outcome tracking
  • Service tests use mock metrics with expecter pattern

Load testing (misc/loadtest/)

  • ghz config targeting Echo RPC via gRPC reflection
  • make loadtest runs 10s load test at concurrency 10
  • Results visible in Grafana dashboard when running with obs profile

Other

  • All local dev infra under deploy/local/ (room for future k8s/helm in deploy/)
  • Fixed Dockerfile LABEL app= prefix
  • Removed misc from .gitignore (mocks + loadtest should be committed)
  • COOKIECUTTER_SKIP_PROTO_INIT env var for fast hook testing (prints warning when active)
  • Post-gen hook reordered: mock before tidy (mocks must exist for import resolution)
  • Updated README.md, AGENTS.md with all new features

Test plan

  • 58 cookiecutter pytest tests pass
  • Grafana datasource UID matches dashboard — panels show data on first run
  • Health checks on postgres, mysql, redis, elasticsearch — --wait blocks until ready
  • Linux: extra_hosts ensures Prometheus can scrape host app
  • ghz config renders with correct service/method via reflection
  • Metrics interface, promauto usage, and _seconds suffix verified
  • Service test uses mock metrics with EXPECT() assertions
  • include_docker_compose=false removes compose + deploy files (tested with hooks)
  • Custom local_services input renders correct PROFILES in Makefile
  • No unrendered cookiecutter variables
  • End-to-end: local-stack + make run + make loadtest -> metrics in Grafana, traces in Jaeger

Adds docker-compose.local.yml to the cookiecutter template with
compose profiles for optional dependencies and observability.

- Default: service only (builds from Dockerfile)
- PROFILES="deps": adds Postgres, Redis, Adminer
- PROFILES="deps obs": adds Prometheus, Grafana
- Makefile targets: local-stack, local-stack-down, local-stack-logs,
  local-stack-rm, local-stack-reset, local-psql
- PROFILES variable flows through all targets
- deploy/prometheus.yml for obs profile scrape config
- AGENTS.md documents all targets and endpoint URLs
- 4 new tests + updated expected files list (49 tests pass)
Copilot AI review requested due to automatic review settings April 8, 2026 06:49
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an optional Docker Compose local dev stack with many service profiles (DBs, messaging, observability, Alloy), Makefile targets and loadtest config, Prometheus/Grafana provisioning and dashboards, a Go metrics package and wiring into the service, test assertions for generated artifacts, and template hooks to conditionally include/remove these artifacts.

Changes

Cohort / File(s) Summary
Docker Compose & Observability
{{cookiecutter.app_name}}/docker-compose.local.yml, {{cookiecutter.app_name}}/deploy/local/prometheus.yml, {{cookiecutter.app_name}}/deploy/local/grafana/provisioning/datasources/prometheus.yml, {{cookiecutter.app_name}}/deploy/local/grafana/provisioning/dashboards/dashboards.yml, {{cookiecutter.app_name}}/deploy/local/grafana/dashboards/coldbrew-service.json, {{cookiecutter.app_name}}/deploy/local/alloy/config.alloy
Adds docker-compose.local.yml with many optional service profiles (postgres/mysql/cockroachdb/mongodb/redis/valkey/memcached/kafka/nats/elasticsearch/ministack/dynamodb/spanner/pubsub/bigtable/firestore/adminer and obs group), Prometheus config, Grafana datasource/provisioning, dashboard JSON, and Alloy config.
Makefile & Loadtest
{{cookiecutter.app_name}}/Makefile, misc/loadtest/echo.json
Introduces local-stack* targets, local-psql, local-stack-logs, local-stack-reset, loadtest, COMPOSE_FILE/PROFILE_FLAGS variables, and a ghz loadtest JSON.
Metrics package & service wiring
{{cookiecutter.app_name}}/service/metrics/types.go, {{cookiecutter.app_name}}/service/metrics/labels.go, {{cookiecutter.app_name}}/service/metrics/metrics.go, {{cookiecutter.app_name}}/service/metrics/metrics_test.go, {{cookiecutter_app_name}}/service/service.go
Adds metrics interface, outcome label constants, Prometheus-backed implementation (CounterVec, HistogramVec, Gauge using promauto), tests validating metrics, and wires a monitoring metrics.Metrics field into service with Echo handler metric recording (named returns + deferred outcome handling).
Template hooks & tests
hooks/post_gen_project.py, tests/conftest.py, tests/test_cookiecutter_generation.py
Makes proto init conditional on COOKIECUTTER_SKIP_PROTO_INIT, adds remove_docker_compose() and conditional removal of docker-compose.local.yml+deploy/ when include_docker_compose disabled, exposes bake_project(..., with_hooks) to control hook execution, and extends tests to assert presence/absence and contents of compose/observability artifacts.
Docs, template config & repo files
{{cookiecutter.app_name}}/AGENTS.md, {{cookiecutter.app_name}}/README.md, cookiecutter.json, {{cookiecutter_app_name}}/.gitignore, {{cookiecutter_app_name}}/local.env.example, {{cookiecutter_app_name}}/Dockerfile
Documents local-stack usage and loadtest, adds include_docker_compose and local_services cookiecutter options and _copy_without_render tweaks, removes misc from .gitignore requirement, adds OTLP env vars to local.env.example, and adjusts Dockerfile build label.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Make as Makefile
    participant Compose as docker-compose
    participant Host as Host FS
    participant Service as App (gRPC)
    participant Prom as Prometheus
    participant Graf as Grafana

    Dev->>Make: run `make local-stack PROFILES=deps,obs`
    Make->>Compose: set COMPOSE_FILE & PROFILE_FLAGS, invoke `docker-compose up -d --wait --remove-orphans`
    Compose->>Host: bind-mount `deploy/local/...` (prometheus.yml, grafana provisioning, dashboards)
    Compose->>Service: start app container (expose metrics endpoint)
    Compose->>Prom: start Prometheus (mount config)
    Compose->>Graf: start Grafana (mount provisioning + dashboards)
    Prom->>Service: scrape metrics from host.docker.internal:9091
    Graf->>Host: load dashboards from `/var/lib/grafana/dashboards`
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • fajran
  • kevinjom
  • svetha-cvl
  • wdevarshi
  • rahulpr22

Poem

🐰 I found a stack in a cozy nest,
With Postgres, Grafana, all dressed—
Makefile hops and compose in tow,
Metrics count as requests flow.
Hop in, devs — let observability grow! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main changes: adding a local development stack with 20 profiles, observability features, metrics support, and load testing capabilities.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/docker-compose-local-stack

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a local-development Docker Compose stack to generated Go services (including optional dependency and observability profiles) and updates template tests/docs to ensure the stack is consistently generated and discoverable.

Changes:

  • Add docker-compose.local.yml with Compose profiles for dependencies (deps) and observability (obs).
  • Add Makefile local-stack* targets (including profile passthrough) and a local-psql helper.
  • Add Prometheus scrape config and document the local stack in AGENTS.md, with tests covering the new outputs.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_cookiecutter_generation.py Extends generation tests to assert new compose/dev-stack files, Makefile targets, and docs are present.
{{cookiecutter.app_name}}/Makefile Adds local-stack lifecycle targets and local-psql helper for the new Compose stack.
{{cookiecutter.app_name}}/docker-compose.local.yml Defines the local dev stack services and profiles (deps/obs).
{{cookiecutter.app_name}}/deploy/prometheus.yml Adds Prometheus scrape config targeting the service in the Compose network.
{{cookiecutter.app_name}}/AGENTS.md Documents how to run the local stack and lists local endpoints/credentials.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread {{cookiecutter.app_name}}/Makefile Outdated
Comment thread {{cookiecutter.app_name}}/Makefile Outdated
Comment thread {{cookiecutter.app_name}}/Makefile Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/test_cookiecutter_generation.py (1)

361-386: Consider moving test_agents_md_local_stack to TestConfigFiles.

The test_agents_md_local_stack method (lines 380-385) tests AGENTS.md content but is placed in TestDockerCompose. For consistency with existing tests, consider moving it to TestConfigFiles where test_agents_md already exists, or merge the assertions into that existing test.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_cookiecutter_generation.py` around lines 361 - 386, The test
method test_agents_md_local_stack currently lives in the TestDockerCompose class
but asserts on AGENTS.md content; move test_agents_md_local_stack out of
TestDockerCompose into the TestConfigFiles class (or merge its assertions into
the existing test_agents_md) so AGENTS.md-related assertions are grouped
together; update any references to bake_project within TestConfigFiles as needed
and remove the duplicate from TestDockerCompose to keep tests consistent.
{{cookiecutter.app_name}}/docker-compose.local.yml (1)

8-9: Consider documenting required environment variables for database connectivity.

The service references local.env but based on the context snippet, local.env.example only contains ENVIRONMENT="dev". When running with the deps profile, users will need database connection variables (e.g., DATABASE_URL, PGHOST, PGPORT) to connect to the Postgres and Redis services.

Consider updating local.env.example with the connection strings for the local stack, or document this in AGENTS.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/docker-compose.local.yml around lines 8 - 9, Add
documentation and example env entries so users running the docker-compose local
stack have the DB/Redis connection vars required by the deps profile; update
local.env.example to include sample variables such as DATABASE_URL, PGHOST,
PGPORT, PGUSER, PGPASSWORD, PGDATABASE and REDIS_URL (or alternatively add a
short section in AGENTS.md) and ensure the values point to the local compose
services (e.g., host names used in docker-compose) and include brief comments
explaining which variables are required for Postgres and Redis connectivity.
{{cookiecutter.app_name}}/Makefile (1)

133-134: Use docker-compose exec instead of hardcoded container name.

The hardcoded container name {{cookiecutter.app_name}}-db-1 relies on Docker Compose's auto-generated naming convention, which depends on the project name (defaults to directory name). This can break if users rename their project directory or set a custom COMPOSE_PROJECT_NAME.

Using docker-compose exec is more robust as it resolves the service name dynamically.

♻️ Proposed fix
 local-psql:
-	docker exec -ti {{cookiecutter.app_name}}-db-1 bash -c 'PGPASSWORD=postgres psql -U postgres -d {{cookiecutter.app_name}}_dev'
+	docker-compose -f $(COMPOSE_FILE) exec db bash -c 'PGPASSWORD=postgres psql -U postgres -d {{cookiecutter.app_name}}_dev'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/Makefile around lines 133 - 134, The Makefile
target local-psql uses a hardcoded container name
"{{cookiecutter.app_name}}-db-1"; replace that docker exec invocation with a
docker-compose exec that targets the DB service (use the service name, e.g. "db"
or the service defined in compose) so Compose resolves the correct container
regardless of project name; update the local-psql rule to call docker-compose
exec -T <service> bash -c 'PGPASSWORD=postgres psql -U postgres -d
{{cookiecutter.app_name}}_dev' (ensure to use the Makefile target name
local-psql and the existing psql invocation).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 17-19: The POSTGRES_DB environment value in the
docker-compose.local.yml environment block (the POSTGRES_DB:
{{cookiecutter.app_name}}_dev line) must be quoted so template rendering can't
produce invalid YAML; update the POSTGRES_DB value to be a quoted string that
concatenates the cookiecutter variable (e.g., wrap the entire value in double
quotes) and also quote any other environment values that combine templates with
text (such as POSTGRES_PASSWORD if needed) to ensure valid YAML after rendering.

---

Nitpick comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 8-9: Add documentation and example env entries so users running
the docker-compose local stack have the DB/Redis connection vars required by the
deps profile; update local.env.example to include sample variables such as
DATABASE_URL, PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE and REDIS_URL (or
alternatively add a short section in AGENTS.md) and ensure the values point to
the local compose services (e.g., host names used in docker-compose) and include
brief comments explaining which variables are required for Postgres and Redis
connectivity.

In @{{cookiecutter.app_name}}/Makefile:
- Around line 133-134: The Makefile target local-psql uses a hardcoded container
name "{{cookiecutter.app_name}}-db-1"; replace that docker exec invocation with
a docker-compose exec that targets the DB service (use the service name, e.g.
"db" or the service defined in compose) so Compose resolves the correct
container regardless of project name; update the local-psql rule to call
docker-compose exec -T <service> bash -c 'PGPASSWORD=postgres psql -U postgres
-d {{cookiecutter.app_name}}_dev' (ensure to use the Makefile target name
local-psql and the existing psql invocation).

In `@tests/test_cookiecutter_generation.py`:
- Around line 361-386: The test method test_agents_md_local_stack currently
lives in the TestDockerCompose class but asserts on AGENTS.md content; move
test_agents_md_local_stack out of TestDockerCompose into the TestConfigFiles
class (or merge its assertions into the existing test_agents_md) so
AGENTS.md-related assertions are grouped together; update any references to
bake_project within TestConfigFiles as needed and remove the duplicate from
TestDockerCompose to keep tests consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b1e352a9-5b78-4a63-a301-19c196ae560f

📥 Commits

Reviewing files that changed from the base of the PR and between 4e4fc36 and 1d238fd.

📒 Files selected for processing (5)
  • tests/test_cookiecutter_generation.py
  • {{cookiecutter.app_name}}/AGENTS.md
  • {{cookiecutter.app_name}}/Makefile
  • {{cookiecutter.app_name}}/deploy/prometheus.yml
  • {{cookiecutter.app_name}}/docker-compose.local.yml

Comment thread {{cookiecutter.app_name}}/docker-compose.local.yml Outdated
ankurs added 2 commits April 8, 2026 15:52
…l/ layout

- Pre-built ColdBrew gRPC dashboard (RED overview, status codes, latency
  by method, Go runtime) auto-provisioned in Grafana via obs profile
- Grafana datasource auto-configured to Prometheus
- All local dev infra moved to deploy/local/ (prometheus.yml, grafana/)
- include_docker_compose flag in cookiecutter.json (default: true)
- Post-gen hook removes docker-compose files when flag is false
- COOKIECUTTER_SKIP_PROTO_INIT env var skips heavy Go toolchain steps
  in hooks, enabling fast test execution with hooks enabled
- 52 tests pass including new: grafana provisioning, volumes, flag=false
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
{{cookiecutter.app_name}}/docker-compose.local.yml (1)

17-19: ⚠️ Potential issue | 🟡 Minor

Quote YAML environment values to prevent syntax errors.

The environment value {{cookiecutter.app_name}}_dev needs to be quoted to ensure valid YAML after template rendering. The static analysis tool correctly flagged this as a syntax error.

🔧 Proposed fix
     environment:
-      POSTGRES_DB: {{cookiecutter.app_name}}_dev
-      POSTGRES_PASSWORD: postgres
+      POSTGRES_DB: "{{cookiecutter.app_name}}_dev"
+      POSTGRES_PASSWORD: "postgres"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/docker-compose.local.yml around lines 17 - 19, The
POSTGRES_DB environment value uses an unquoted template string
({{cookiecutter.app_name}}_dev) which can produce invalid YAML after rendering;
update the docker-compose.local.yml environment block by quoting the POSTGRES_DB
value (e.g., wrap the {{cookiecutter.app_name}}_dev template in double or single
quotes) so the POSTGRES_DB entry is a valid YAML string while leaving
POSTGRES_PASSWORD unchanged.
🧹 Nitpick comments (1)
{{cookiecutter.app_name}}/docker-compose.local.yml (1)

35-45: Consider pinning image versions for reproducibility.

Using :latest tags for prom/prometheus and grafana/grafana can lead to unexpected behavior when images are updated. For a local development stack this is often acceptable, but pinning to specific versions (e.g., prom/prometheus:v2.51.0, grafana/grafana:10.4.0) would improve reproducibility across team members.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/docker-compose.local.yml around lines 35 - 45, The
docker-compose services prometheus and grafana currently use floating :latest
tags; update the docker-compose.local.yml to pin those images to specific stable
versions (e.g., prom/prometheus:v2.51.0 and grafana/grafana:10.4.0 or your
chosen team-approved tags) so builds are reproducible — replace the image values
for the prometheus and grafana services with the chosen versioned tags and
verify the compose file still starts correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@hooks/post_gen_project.py`:
- Around line 86-102: The hook remove_docker_compose() currently deletes
docker-compose.local.yml and deploy/ but leaves Makefile targets (local-stack*,
targets referencing docker-compose.local.yml) and the "Local Development Stack"
section in AGENTS.md, causing broken commands; update remove_docker_compose() to
also patch or remove those references: open the generated Makefile and remove
any lines/targets that reference "docker-compose.local.yml" or match target
names starting with "local-stack" (and any dependent recipe blocks), and update
AGENTS.md to remove the entire "Local Development Stack" section (or replace it
with a short note) so no docs reference the removed local stack; alternatively,
if you prefer template-time handling, add Jinja2 conditionals around the
local-stack targets in the Makefile template and around the "Local Development
Stack" section in AGENTS.md to exclude them when "{{
cookiecutter.include_docker_compose }}".lower() not in ("true","1","yes").

---

Duplicate comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 17-19: The POSTGRES_DB environment value uses an unquoted template
string ({{cookiecutter.app_name}}_dev) which can produce invalid YAML after
rendering; update the docker-compose.local.yml environment block by quoting the
POSTGRES_DB value (e.g., wrap the {{cookiecutter.app_name}}_dev template in
double or single quotes) so the POSTGRES_DB entry is a valid YAML string while
leaving POSTGRES_PASSWORD unchanged.

---

Nitpick comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 35-45: The docker-compose services prometheus and grafana
currently use floating :latest tags; update the docker-compose.local.yml to pin
those images to specific stable versions (e.g., prom/prometheus:v2.51.0 and
grafana/grafana:10.4.0 or your chosen team-approved tags) so builds are
reproducible — replace the image values for the prometheus and grafana services
with the chosen versioned tags and verify the compose file still starts
correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e325b700-2c29-46f0-8bf1-d7b3d2cf56e4

📥 Commits

Reviewing files that changed from the base of the PR and between 1d238fd and 3f37915.

📒 Files selected for processing (10)
  • cookiecutter.json
  • hooks/post_gen_project.py
  • tests/conftest.py
  • tests/test_cookiecutter_generation.py
  • {{cookiecutter.app_name}}/Dockerfile
  • {{cookiecutter.app_name}}/deploy/local/grafana/dashboards/coldbrew-service.json
  • {{cookiecutter.app_name}}/deploy/local/grafana/provisioning/dashboards/dashboards.yml
  • {{cookiecutter.app_name}}/deploy/local/grafana/provisioning/datasources/prometheus.yml
  • {{cookiecutter.app_name}}/deploy/local/prometheus.yml
  • {{cookiecutter.app_name}}/docker-compose.local.yml
✅ Files skipped from review due to trivial changes (6)
  • {{cookiecutter.app_name}}/deploy/local/prometheus.yml
  • {{cookiecutter.app_name}}/deploy/local/grafana/provisioning/dashboards/dashboards.yml
  • cookiecutter.json
  • {{cookiecutter.app_name}}/Dockerfile
  • {{cookiecutter.app_name}}/deploy/local/grafana/provisioning/datasources/prometheus.yml
  • {{cookiecutter.app_name}}/deploy/local/grafana/dashboards/coldbrew-service.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_cookiecutter_generation.py

Comment thread hooks/post_gen_project.py
ankurs added 3 commits April 8, 2026 18:19
- Remove app from docker-compose (use make run instead — faster native build)
- Prometheus scrapes host.docker.internal:9091 (app runs on host)
- local-stack prints running container endpoints after startup
- Add ghz load test config (misc/loadtest/echo.json) with gRPC reflection
- make loadtest target runs 10s load test at concurrency 10
- Update README.md and AGENTS.md with local stack and load testing docs
- 53 tests pass
misc/ contained generated mocks but also now has loadtest configs.
Neither should be gitignored — mocks are useful to commit for CI.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
{{cookiecutter.app_name}}/docker-compose.local.yml (1)

8-10: ⚠️ Potential issue | 🔴 Critical

Quote templated environment values to keep rendered YAML valid.

Line 9 can break YAML parsing after template rendering ({{...}}_dev should be a quoted scalar).

🔧 Proposed fix
     environment:
-      POSTGRES_DB: {{cookiecutter.app_name}}_dev
-      POSTGRES_PASSWORD: postgres
+      POSTGRES_DB: "{{cookiecutter.app_name}}_dev"
+      POSTGRES_PASSWORD: "postgres"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/docker-compose.local.yml around lines 8 - 10, The
POSTGRES_DB templated value (POSTGRES_DB: {{cookiecutter.app_name}}_dev) may
produce invalid YAML after rendering; change the Docker Compose environment
entry so the POSTGRES_DB value is a quoted scalar (wrap the rendered template
expression in quotes) to ensure the final YAML stays valid; update the
environment key where POSTGRES_DB is set in the docker-compose.local.yml to use
a quoted value for {{cookiecutter.app_name}}_dev.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 41-43: Replace the hardcoded GF_SECURITY_ADMIN_PASSWORD value in
the docker-compose "environment" block with an environment-variable reference
(e.g., GF_SECURITY_ADMIN_PASSWORD: "${GF_SECURITY_ADMIN_PASSWORD}") so
credentials are provided from the runtime environment or a .env file rather than
committed in source; update .env.example or documentation to show how to set
GF_SECURITY_ADMIN_PASSWORD for local dev and ensure no default plaintext
password remains in the docker-compose "environment" section or other committed
files.

In @{{cookiecutter.app_name}}/Makefile:
- Around line 137-140: The Makefile target local-stack-rm currently runs
"docker-compose ... rm" which prompts for confirmation and can block
local-stack-reset; update the local-stack-rm recipe to run docker-compose rm
non-interactively by adding the force flag (e.g., --force or -f) so it does not
prompt (optionally include -v if you also want to remove anonymous volumes).
Ensure the change is applied to the local-stack-rm rule referenced by the
Makefile targets local-stack-rm and local-stack-reset.
- Around line 142-143: The local-psql Makefile target currently uses a hardcoded
container name; update the local-psql target to use docker-compose exec (same
pattern as other targets) instead of docker exec and reference the database
service name (e.g., db) so the command is resilient across environments; replace
the line in the local-psql target that calls "docker exec -ti
{{cookiecutter.app_name}}-db-1 ..." with a docker-compose exec invocation (e.g.,
"docker-compose exec -ti db bash -c 'PGPASSWORD=postgres psql -U postgres -d
{{cookiecutter.app_name}}_dev'") to remove the fragile container name
dependency.
- Around line 117-120: The Makefile target local-stack currently builds
PROFILE_FLAGS from PROFILES but PROFILES has no default so running make
local-stack selects no profiles; set a sensible default by defining PROFILES (or
PROFILE_FLAGS) with a fallback (e.g., include the common profiles like "deps
obs") so PROFILE_FLAGS expands to "--profile deps --profile obs" when PROFILES
is not exported, ensuring docker-compose -f $(COMPOSE_FILE) $(PROFILE_FLAGS) up
... will start the expected services; update the Makefile near the
PROFILE_FLAGS/PROFILES definitions (symbols: PROFILE_FLAGS, PROFILES,
local-stack, COMPOSE_FILE) to add this default assignment.

---

Duplicate comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 8-10: The POSTGRES_DB templated value (POSTGRES_DB:
{{cookiecutter.app_name}}_dev) may produce invalid YAML after rendering; change
the Docker Compose environment entry so the POSTGRES_DB value is a quoted scalar
(wrap the rendered template expression in quotes) to ensure the final YAML stays
valid; update the environment key where POSTGRES_DB is set in the
docker-compose.local.yml to use a quoted value for
{{cookiecutter.app_name}}_dev.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad79ceb1-1d19-4c73-b33b-3a5f038077f6

📥 Commits

Reviewing files that changed from the base of the PR and between 3f37915 and c0c6e0b.

📒 Files selected for processing (8)
  • tests/test_cookiecutter_generation.py
  • {{cookiecutter.app_name}}/.gitignore
  • {{cookiecutter.app_name}}/AGENTS.md
  • {{cookiecutter.app_name}}/Makefile
  • {{cookiecutter.app_name}}/README.md
  • {{cookiecutter.app_name}}/deploy/local/prometheus.yml
  • {{cookiecutter.app_name}}/docker-compose.local.yml
  • {{cookiecutter.app_name}}/misc/loadtest/echo.json
💤 Files with no reviewable changes (1)
  • {{cookiecutter.app_name}}/.gitignore
✅ Files skipped from review due to trivial changes (4)
  • {{cookiecutter.app_name}}/deploy/local/prometheus.yml
  • {{cookiecutter.app_name}}/misc/loadtest/echo.json
  • {{cookiecutter.app_name}}/README.md
  • {{cookiecutter.app_name}}/AGENTS.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_cookiecutter_generation.py

Comment thread {{cookiecutter.app_name}}/docker-compose.local.yml
Comment thread {{cookiecutter.app_name}}/Makefile Outdated
Comment thread {{cookiecutter.app_name}}/Makefile Outdated
Comment thread {{cookiecutter.app_name}}/Makefile Outdated
@ankurs ankurs changed the title feat: add docker-compose local dev stack with profiles feat: docker-compose local dev stack, Grafana dashboard, load testing Apr 8, 2026
- service/metrics/ package: Metrics interface, promauto implementation,
  label constants (types.go, metrics.go, labels.go, metrics_test.go)
- Sample metrics: echo_total counter, echo_duration_seconds histogram,
  active_requests gauge — shows counter/histogram/gauge patterns
- Uses seconds for durations (Prometheus convention)
- Wired into Echo handler with defer pattern for timing + outcome
- Interface enables mocking via mockery (already configured)
- 56 tests pass
@ankurs ankurs changed the title feat: docker-compose local dev stack, Grafana dashboard, load testing feat: local dev stack, Grafana dashboard, metrics package, load testing Apr 8, 2026
- Jaeger all-in-one in obs profile (UI on :16686, OTLP on :4317)
- local.env.example sets OTLP_ENDPOINT + OTLP_INSECURE for auto trace export
- Traces flow to Jaeger automatically when obs profile is running
- Added to Makefile endpoint display, AGENTS.md, README.md
@ankurs ankurs changed the title feat: local dev stack, Grafana dashboard, metrics package, load testing feat: local dev stack, observability (Grafana + Jaeger), metrics package, load testing Apr 8, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/test_cookiecutter_generation.py (1)

389-426: Prefer structured Compose assertions over raw string matching.

Checks like profiles: ["deps"] and the Grafana volume lines are locked to one YAML serialization, so whitespace- or quoting-only edits will fail this suite even when the rendered Compose config is still correct. Parsing the file once and asserting on the services / profiles / volumes structure would make these generation tests much less brittle.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_cookiecutter_generation.py` around lines 389 - 426, Replace
brittle raw-string assertions in tests like test_compose_profiles and
test_grafana_volumes_in_compose by parsing docker-compose.local.yml with a YAML
loader (e.g., yaml.safe_load) and asserting against the resulting dict: check
compose_data["services"] contains expected service keys
("db","redis","prometheus","grafana"), verify profiles exist on the appropriate
service entries or top-level compose_data["profiles"], and confirm grafana
service volumes include the provisioning and dashboards target paths by
inspecting compose_data["services"]["grafana"]["volumes"]; update
test_compose_infra_services/test_compose_db_name similarly to read structured
keys (POSTGRES_DB under compose_data["services"]["db"]["environment"]) instead
of substring matching.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @{{cookiecutter.app_name}}/service/metrics/metrics_test.go:
- Around line 11-61: The tests use manual if/t.Fatal checks and ignore errors
from prometheus.DefaultGatherer.Gather(); update gatherMetric to return
(*dto.MetricFamily, error) and surface the Gather() error instead of discarding
it, then refactor TestIncEchoTotal, TestObserveEchoDuration, and
TestSetActiveRequests to use testify's require/ assert (e.g., require.NoError
for gatherMetric errors, require.NotNil for the returned MetricFamily,
require.Greater/Len or assert.Equal for value checks) and avoid unchecked slice
access (use require.Len or require.Greater to ensure mf.GetMetric() has the
expected entries before indexing). Ensure you reference the New() constructor
and namespace metric names unchanged while replacing manual t.Fatal branches
with require/assert calls.

In @{{cookiecutter.app_name}}/service/service.go:
- Around line 46-55: Echo currently records totals and latency but never updates
the active_requests gauge; wrap the handler with balanced increment/decrement
calls to keep it accurate: at the start of svc.Echo call
s.monitoring.SetActiveRequests(...) to increment active requests, and in the
existing defer (alongside outcome/latency) call
s.monitoring.SetActiveRequests(...) to decrement; reference the svc.Echo method
and the metrics SetActiveRequests implementation and use a +1 before processing
and a -1 in the defer (or if SetActiveRequests takes an absolute value, read
current and set current+1 / current-1 accordingly).

---

Nitpick comments:
In `@tests/test_cookiecutter_generation.py`:
- Around line 389-426: Replace brittle raw-string assertions in tests like
test_compose_profiles and test_grafana_volumes_in_compose by parsing
docker-compose.local.yml with a YAML loader (e.g., yaml.safe_load) and asserting
against the resulting dict: check compose_data["services"] contains expected
service keys ("db","redis","prometheus","grafana"), verify profiles exist on the
appropriate service entries or top-level compose_data["profiles"], and confirm
grafana service volumes include the provisioning and dashboards target paths by
inspecting compose_data["services"]["grafana"]["volumes"]; update
test_compose_infra_services/test_compose_db_name similarly to read structured
keys (POSTGRES_DB under compose_data["services"]["db"]["environment"]) instead
of substring matching.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8be8a3fb-2157-4246-bc0d-1513d677afc6

📥 Commits

Reviewing files that changed from the base of the PR and between c0c6e0b and a8110cc.

📒 Files selected for processing (6)
  • tests/test_cookiecutter_generation.py
  • {{cookiecutter.app_name}}/service/metrics/labels.go
  • {{cookiecutter.app_name}}/service/metrics/metrics.go
  • {{cookiecutter.app_name}}/service/metrics/metrics_test.go
  • {{cookiecutter.app_name}}/service/metrics/types.go
  • {{cookiecutter.app_name}}/service/service.go
✅ Files skipped from review due to trivial changes (1)
  • {{cookiecutter.app_name}}/service/metrics/labels.go

Comment thread {{cookiecutter.app_name}}/service/metrics/metrics_test.go Outdated
Comment thread {{cookiecutter.app_name}}/service/service.go
ankurs added 2 commits April 8, 2026 19:56
…L quoting

- DOCKER_COMPOSE variable (default: docker-compose, override for v2 plugin)
- PROFILES defaults to "deps" so bare make local-stack works
- Drop local-stack-rm (down already removes containers)
- local-psql uses docker-compose exec + sh (not bash, not hardcoded name)
- Quote POSTGRES_DB value in compose YAML
- Update help text and usage comments
- Cookiecutter prompt shows all available services in the variable name:
  local_services (postgres,mysql,...,adminer) [postgres,redis]:
- Per-service profiles replace the old "deps" profile (20 services)
- PROFILES default in Makefile rendered from user's selection
- Added: mysql, cockroachdb, mongodb, valkey, memcached, kafka
  (apache/kafka), nats, elasticsearch, ministack, dynamodb, spanner,
  pubsub, bigtable, firestore, alloy (grafana/alloy OTEL collector)
- Removed bitnami/kafka (no longer free), localstack (sunset),
  minio (Docker images ended)
- Postgres bumped to 18
- Removed pre_gen_project.py (options inline in prompt now)
- 57 tests pass
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
{{cookiecutter.app_name}}/docker-compose.local.yml (1)

39-52: Note: Redis and Valkey share the same host port.

Both services map to 6379:6379. This is expected since Valkey is a Redis-compatible alternative—users would enable one profile or the other, not both simultaneously. Consider adding a brief comment to clarify they're mutually exclusive.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/docker-compose.local.yml around lines 39 - 52, The
docker-compose file defines two services, redis and valkey, that both map the
same host port "6379:6379" which is fine because they are mutually exclusive;
update the compose snippet by adding a brief clarifying comment above the valkey
or redis service (referencing service names redis and valkey and the port
mapping "6379:6379") that states Valkey is a Redis-compatible alternative and
only one profile should be enabled at a time so users understand the shared host
port is intentional.
{{cookiecutter.app_name}}/deploy/local/alloy/config.alloy (1)

1-12: Misleading comment: only traces are forwarded, not metrics.

Line 2 states "forwards to Prometheus + Jaeger" but the output block only routes traces to Jaeger. Prometheus scrapes the app directly (per prometheus.yml), so metrics don't flow through Alloy. Update the comment to avoid confusion:

 // Grafana Alloy configuration for local development
-// Receives OTLP telemetry and forwards to Prometheus + Jaeger
+// Receives OTLP traces and forwards to Jaeger
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @{{cookiecutter.app_name}}/deploy/local/alloy/config.alloy around lines 1 -
12, The top comment in config.alloy is inaccurate: the otelcol.receiver.otlp
"default" block only routes traces (output.traces ->
otelcol.exporter.otlp.jaeger.input) and does not forward metrics to Prometheus;
update the header comment to state that Alloy receives OTLP telemetry and
forwards traces to Jaeger while metrics are scraped directly by Prometheus (per
prometheus.yml) so readers aren’t misled.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 99-105: The ministack service currently references a non-existent
Docker image; update the ministack service definition to use the official
LocalStack image by replacing the image value "ministack/ministack:latest" with
"localstack/localstack:latest" (service name: ministack) and ensure the
ports/restart/profiles remain unchanged; also update any documentation strings
or comments that reference "ministack" to state that this service provides
LocalStack AWS emulation so readers know it's the LocalStack emulator.

---

Nitpick comments:
In @{{cookiecutter.app_name}}/deploy/local/alloy/config.alloy:
- Around line 1-12: The top comment in config.alloy is inaccurate: the
otelcol.receiver.otlp "default" block only routes traces (output.traces ->
otelcol.exporter.otlp.jaeger.input) and does not forward metrics to Prometheus;
update the header comment to state that Alloy receives OTLP telemetry and
forwards traces to Jaeger while metrics are scraped directly by Prometheus (per
prometheus.yml) so readers aren’t misled.

In @{{cookiecutter.app_name}}/docker-compose.local.yml:
- Around line 39-52: The docker-compose file defines two services, redis and
valkey, that both map the same host port "6379:6379" which is fine because they
are mutually exclusive; update the compose snippet by adding a brief clarifying
comment above the valkey or redis service (referencing service names redis and
valkey and the port mapping "6379:6379") that states Valkey is a
Redis-compatible alternative and only one profile should be enabled at a time so
users understand the shared host port is intentional.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a88a2e59-2d50-4f69-89cc-4680ab98b4e5

📥 Commits

Reviewing files that changed from the base of the PR and between a8110cc and a134364.

📒 Files selected for processing (8)
  • cookiecutter.json
  • tests/test_cookiecutter_generation.py
  • {{cookiecutter.app_name}}/AGENTS.md
  • {{cookiecutter.app_name}}/Makefile
  • {{cookiecutter.app_name}}/README.md
  • {{cookiecutter.app_name}}/deploy/local/alloy/config.alloy
  • {{cookiecutter.app_name}}/docker-compose.local.yml
  • {{cookiecutter.app_name}}/local.env.example
✅ Files skipped from review due to trivial changes (2)
  • {{cookiecutter.app_name}}/local.env.example
  • {{cookiecutter.app_name}}/AGENTS.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • {{cookiecutter.app_name}}/README.md
  • cookiecutter.json

Comment thread {{cookiecutter.app_name}}/docker-compose.local.yml
ankurs added 3 commits April 8, 2026 22:10
- Replace Grafana Alloy with AlloyDB Omni (GCP PostgreSQL-compatible DB)
- Remove SetActiveRequests gauge (counter + histogram suffice as examples)
- Add make local-stack-obs shortcut for obs profile discoverability
- Replace local-psql with generic local-exec SVC=... CMD=...
- Add input guards for SVC/CMD on local-exec
- local-stack-down uses plain down (stops all containers regardless of profile)
- Fix valkey port to 6380 (avoids conflict with redis on 6379)
- Add missing endpoint display for spanner, pubsub, bigtable, firestore, alloydb
- Remove SetReady() from TestEcho (not needed, avoids global state leak)
- Service tests use mockmetrics for proper unit testing with expectations
- Reorder post-gen hook: mock before tidy (mocks must exist for import resolution)
- Add ordering comment to init_proto explaining step dependencies
- 58 tests pass
- Fix Grafana datasource UID mismatch — add uid: PBFA97CFB590B2093 to
  provisioned datasource so dashboard panels find it
- Add health checks for postgres, mysql, redis, elasticsearch
  (--wait now actually waits for readiness)
- Add extra_hosts: host.docker.internal:host-gateway to Prometheus
  (fixes Linux where host.docker.internal doesn't resolve by default)
- Print warning when COOKIECUTTER_SKIP_PROTO_INIT skips proto init
- Fix AGENTS.md: "sends requests for 10 seconds" not "1000 requests"
- Add alloydb to README.md available profiles list
- 58 tests pass
@ankurs ankurs changed the title feat: local dev stack, observability (Grafana + Jaeger), metrics package, load testing feat: local dev stack (20 profiles), observability, metrics, load testing Apr 8, 2026
@ankurs ankurs requested a review from Copilot April 8, 2026 14:36
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread {{cookiecutter.app_name}}/service/metrics/metrics_test.go Outdated
Comment thread {{cookiecutter.app_name}}/Makefile Outdated
Comment thread {{cookiecutter.app_name}}/docker-compose.local.yml
Comment thread hooks/post_gen_project.py
ankurs added 3 commits April 8, 2026 23:02
…kefile comment

- Fix ministack Docker image: ministack/ministack → nahuelnucera/ministack
- gatherMetric now captures and reports Gather() errors instead of discarding
- Add alloydb to Makefile available profiles comment
…-profile "*"

- local-stack-obs delegates to local-stack via recursive make with obs
  appended to PROFILES — gets full endpoint display including Grafana/Jaeger
- local-stack-down uses --profile "*" to stop all profiled services
  (plain down without profiles didn't see profiled services)
- Move goprivate after project_short_description (project identity first)
- Add all 11 prompts to README example output
- Add to features: local dev stack, Grafana/Jaeger, metrics, load testing, protovalidate
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread {{cookiecutter.app_name}}/Makefile
Comment thread {{cookiecutter.app_name}}/Makefile
Comment thread {{cookiecutter.app_name}}/service/metrics/metrics.go Outdated
@ankurs ankurs merged commit e20ab4e into main Apr 9, 2026
8 checks passed
@ankurs ankurs deleted the feat/docker-compose-local-stack branch April 9, 2026 02:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants