# Case catalogue

The cases that come up in GFiber services and the level each one takes. If a case is not here, run the decision list in [levels.md](levels.md) and add a row.

## Work intake and results

| Case | Level | Note |
|------|-------|------|
| Request, batch or message arrived | INFO | counts and the values that identify the scope, such as alarm names, severities, OLT, HUT; no payload and no id list |
| Batch finished | INFO if ok, ERROR otherwise | one summary line with in, out, duration and status, written from a defer registered before any recover so a panic still produces it |
| Result of one work item | INFO | one per item, with its identifier and outcome; this is the line support greps for, and the one line that must never be demoted |
| Payload of the work item | DEBUG | or behind on-demand troubleshooting |
| Decision that ends the item | INFO | only when it is not already visible in that item's result message |
| Intermediate lookup or filter result | DEBUG | log the count at INFO if it matters, the members at DEBUG |
| Anything inside a loop over domain objects | DEBUG | plus one count after the loop |

## Rejections and failures

| Case | Level | Note |
|------|-------|------|
| Input malformed, null or failed validation | WARN | carry the identifiers that survived parsing, and the body size |
| Rejected for capacity or backpressure | WARN | one line per rejected request, never per item |
| No handler or policy matched the work | WARN | carry the identifiers, because no result line will be written |
| Upstream call failed, will be retried | DEBUG | the attempt is not yet a failure |
| Upstream call failed after retries | ERROR | carry the identifiers and the step that stopped |
| Some items succeeded, some failed | ERROR | on the summary line, with the split |
| Panic recovered | ERROR | log the recovered value and the stack, and keep serving |

## Service lifecycle

| Case | Level | Note |
|------|-------|------|
| Started, listeners bound, dependencies resolved | INFO | a handful of lines, once per process |
| Effective configuration | DEBUG | never secrets, tokens or credentials |
| Graceful shutdown | INFO | |
| Cannot start at all | FATAL | the only place FATAL is allowed |
| Database connection established | INFO | once at startup; per query is DEBUG |

## Background work

| Case | Level | Note |
|------|-------|------|
| Scheduled tick that found nothing to do | DEBUG | a tick every few seconds at INFO is one of the cheapest ways to burn retention |
| Scheduled tick that did work | INFO | one line with counts, not one per item |
| Kafka batch consumed | INFO | one summary per batch, same shape as an HTTP batch |
| One Kafka message processed | DEBUG | the per-item result line already covers what support needs |
| Message that cannot be parsed | ERROR | carry the message key and raise a metric; it will never parse, so it is lost work |
| Consumer rebalance or lag | none | leave it to the client library and to metrics |

## Keep out

| Case | Level | Note |
|------|-------|------|
| Health, liveness and readiness probes | none on success | probe traffic is constant; log only a failing probe |
| Every outbound HTTP request and response | DEBUG | rates and durations belong in metrics |
| Upstream returned an empty result | DEBUG | unless it changes the outcome, and then it belongs in the item's result message |
| Third-party library output | set it explicitly | do not let a dependency inherit DEBUG in production |
| Secrets, tokens, passwords | never | at any level |
| ONT serial, account id, hostname | not at INFO | on high-volume paths; fine in a bounded projection or at DEBUG |

If a line has to be INFO and is still too frequent, sample it: log one in N with the count of what was skipped. Demoting it to DEBUG removes it from production entirely, which is usually not the intent.

## Reference implementations

Read these before writing a new one; both were reviewed against this policy.

| What | Where |
|------|-------|
| Per-batch summary line, `key=value`, INFO on ok and ERROR otherwise | `gfiber-policy-executor`, `pkg/faultstatus/stats.go` |
| Per-alarm result line, the one support greps for | `gfiber-policy-executor`, `pkg/policies/executor.go` |
| Ingress line with counts, ids on a DEBUG companion | `gfiber-policy-executor`, `pkg/policies/executor.go` |
| Per-item result line from a defer, covering every failure path | `gfiber-ticketing-proxy`, `pkg/ticket/executor.go` |
| Rejection lines with a fixed reason vocabulary plus a counter | `gfiber-ticketing-proxy`, `pkg/ticket/routes.go` |
