Nobody has started this yet — be first.
Business impact
GET /metrics exposes one unlabeled counter for every notification ever published, regardless of what kind it was. A single number can tell ops that traffic went up; it can't tell them which feature is generating that traffic -- which matters the moment more than one part of the product publishes through this same endpoint. app/metrics.py already defines a per-event-type counter for exactly this purpose, but nothing increments it, so capacity planning and anomaly detection have no signal to work with.
Problem
app/metrics.py already defines events_published_by_type_total, a counter labeled by event, but nothing in app/publisher.py::publish_event ever calls .labels(...).inc() on it, so it sits permanently at zero regardless of traffic.
Current behavior
Calling publish_event(..., event="order_shipped") three times and then reading events_published_by_type_total.labels(event="order_shipped")._value.get() returns 0.0, not 3.0.
Expected behavior
Every call to publish_event() should increment events_published_by_type_total with the event label set to that call's event argument, in addition to the existing unlabeled events_published_total counter.
Steps to reproduce
pytest practice_tickets/tests/test_ticket_06_event_type_metrics.py -vWhy this matters
A single unlabeled counter can tell you traffic went up; it can't tell you which feature is generating that traffic. This is a small, mechanical change, but it's the kind of thing that's much cheaper to add before there's an incident that needed it than after.
Suggested approach
Look at how events_published_total.inc() is already called in app/publisher.py::publish_event, and how events_delivered_total.labels(source=...).inc() is called in app/streaming.py -- events_published_by_type_total needs the same .labels(...) treatment, keyed by this call's event value.
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket_06_event_type_metrics.py -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
Sign in to create it automatically, or do it yourself:
$git checkout -b feat/per-event-type-metricsFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/per-event-type-metricsSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inhttp://localhost:8000http://localhost:8001Authorization: Bearer <user_id>X-User-Id: <user_id>curl localhost:8000/healthz
curl -N -H "Authorization: Bearer alice" localhost:8000/notifications/stream
# watch `: heartbeat` lines arrive roughly every 15s with no other traffic
Work the tickets in practice_tickets/tickets/ (ordered easy → hard); each names one dedicated pytest test in practice_tickets/tests/:
pytest practice_tickets/tests/test_ticket_01_heartbeat_default_margin.py -v # a single ticket
./practice_tickets/run_tickets.sh # all 15, clean pass/fail summary
Tickets 14 and 15 need genuinely concurrent, long-lived streams, which the ASGI test transport used everywhere else in this project can't represent -- their tests spin up a real (short-lived) uvicorn server on a loopback socket instead (LiveServer in practice_tickets/tests/conftest.py).
Level 2
Implement a feature
Extend the system within its own patterns.