Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when adding logging/observability to a new or existing service, module, or pipeline — or when a long-running job turned out to be unexplainable after the fact. Fires on: "add logging", "нужно логирование", "what do we log here", "structured logs", "ship logs to Kibana/Elasticsearch/Loki", "why did this run fail and we can't tell", "add metrics/tracing to this pass". Produces a logging design (event vocabulary, sink, levels, payload rule) written into the architecture doc first, then the wiri
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 37% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 40% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 55% | 0% |
Logging is a contract, not a scattering of log.info calls. Ad-hoc logging produces a stream nobody can query and everybody is afraid to delete. Decide the shape first, write it into the project's architecture doc, then implement against it.
Content does not go into logs. At any level. By design. Prompts, request and response bodies, document text, source code, personal data — none of it. Log names and metrics: the input's identifier, the output's identifier, sizes, counts, durations, outcome.
Why this is a rule and not a level:
index that far more people can read than can read the source data.
incident and forgets. There should be no switch.
disk, the request store). The log's job is to tell you which one to go read.
If you cannot debug from names + sizes + durations, add a field, not the payload — e.g. prompt_chars instead of the prompt, result_count instead of the results.
concern is documented (a ## Storage-style section). You are adding a sibling ## Observability section.
stdout is already spoken for — an MCP server, a CLI that pipes structured output, anything whose stdout is a protocol. If so, stderr is a correctness constraint, not a preference: one stray line corrupts the channel. Say that in the doc so nobody "tidies" it later.
ever reach a log stack (Elasticsearch/Kibana, Loki, Splunk), the answer is JSON Lines — one self-contained event per line, parseable with no custom grok pattern. Offer a text renderer for local terminal use; it renders the same events and is a display choice only.
event.action → emitter →fields. An event is a noun-ish area.thing (enrich.note, tool.search, embed.batch), not a sentence. This table is the artifact that stops the stream drifting into free-form prose.
Align with ECS where it costs nothing: @timestamp (ISO-8601 UTC), log.level, event.action, event.duration. Renaming a field later breaks every saved query and dashboard built on it — so decide once, in the doc.
run_id (or request/trace id) minted per process orper request, on every event, so one invocation groups into a trace. Add the tenant-ish dimension too (repo, service, customer) — several of them will share one index.
error.type +error.message on one line. A multi-line traceback gets split by the shipper into unrelated documents, and you lose the very failure you were chasing.
Elasticsearch client, no network calls on the logging path. A collector (Filebeat/Promtail/vector) ships it. This keeps the service runnable offline and independent of whether a log stack exists yet.
that raises nothing — a truncated prompt, a silently dropped batch, a fallback that quietly returns empty. Find it and emit a warning with the measurement that reveals it (e.g. prompt size vs the context window). This is usually the highest-value event in the whole stream.
INFO = start/finish, counts,warnings. DEBUG = per-item events with timings. Payload logging is not a level (see Rule 0). Level and format come from env — a new env var, so follow the project's change-propagation map: config + env example + README + architecture doc, same PR.
HTTP, DB batch), every per-item loop in a long pass, every tool/endpoint entry point, and the run itself. Use a timing context manager so event.duration and outcome=ok|error are automatic rather than remembered.
(a class name, a secret-looking token) through the logging path and asserts it does not appear in the serialized events, while its size does. The rule then survives the next person who wants to "just temporarily log the request".
Which items failed and where? Did anything approach a limit? How did this run compare to the last one? If not, add fields.
Should fire: "add logging to the new service" · "нужно логирование, потом в Kibana" · "we can't tell what this job did — add observability". Should NOT fire: "why is this test failing" (debugging, not designing a log stream) · "add a metrics dashboard" (visualization of an existing stream).
Other measured skills in the registry, with their headline benchmark lift.