Structured logging
Skill Amey-Thakur/AI-SKILLS/skills/debugging/structured-logging
Plug-and-play skills and prompts for every AI coding agent
npx -y skills add Amey-Thakur/AI-SKILLS --skill structured-loggingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 19 days oldThe repository was created 19 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Emit machine-readable key-value events instead of prose sentences, with a stable schema and controlled field cardinality. Use when logs need to be queried and aggregated, not just read one line at a time by a person.
SKILL.md
2.9 KB, as published. Nobody here has run it
Structured logging
log.info("user " + id + " failed to pay $" + amt) reads fine to a human and
tells a machine nothing. You cannot filter it, group it, or count it without a
regex that shatters the next time the sentence changes. Structured logging
emits events as fields so a query engine can answer questions the author never
thought to ask.
Method
- Emit an event with fields, not an interpolated string. Write
log.info("payment_failed", user_id=id, amount=amt, currency="usd")and let the logger render JSON. Nowamount>100 and currency="usd"is a query, not a grep: the message becomes a stable name and the variables become searchable fields. - Keep the event name constant and move nouns to fields. The first argument
is a fixed token like
order_placedordb_timeout, identical on every emit. Everything that varies, ids, counts, durations, lands in fields. Constant names let you count occurrences without matching free text. - Pin a schema and reuse names across services. Agree that the user is
always
user_id, latency is alwaysduration_ms, the request key is alwaysrequest_id. When every service spells them alike, one query joins them all;uid,userId, anduserfragment the same data into three. - Control cardinality: bounded values are fields, unbounded ones get
sampled. A
statuswith a dozen values is a fine group-by. A raw SQL string or full stack trace as a field explodes index size and cost. Keep high-cardinality blobs in an unindexed message field, or sample them. - Bind context once at the entry point. Attach
request_idanduser_idwithlogger.bind(request_id=rid)so every line in that request carries them without repeating arguments. Correlation turns automatic instead of a field you forget on the one line that mattered. - Log durations and counts as numbers. Emit
duration_ms=214as an integer, never"took 214ms". Numeric fields let the backend compute averages, percentiles, and thresholds; a number wrapped in a sentence has to be parsed back out before it is usable.
Checks
- Can you answer a new question with a field filter, touching no logging code?
- Do the same concepts carry the same field name in every service?
- Is any field's value unbounded, and if so is it unindexed or sampled?
Boundaries
Structure fixes the shape of a line, not its urgency: which level it fires at is log-levels. Chasing the id across services once it is logged is distributed-tracing. Match the field names the project already uses over a tidier scheme of your own, because a shared schema is the entire point.