Informative Logging
do-informative-logging · always_apply: no
Content
Mimir metadata (required on apply): always_apply: true (currently false). This rule absorbs and replaces add-logging.
Every service call or controller action must log to logs/app.log (or the project’s designated app log) at INFO. Configure logging if missing: logger + file handler that rotates / clears on every app relaunch so diagnosis starts clean.
Use logs/app.log to troubleshoot who was doing what with which data when error X occurred. For UI / HTMX flows use console.log for decisions, actions, and results (map to the same story beats below).
Ban deferred-logging slices. Logging ships in the same green slice as behavior — never a final “informative logging pass” after tests are green.
Ask yourself before writing each log line:
- What information will I need to precisely pinpoint where the error is occurring?
- What context will I need in the logs to understand why it happened?
- What data transformations or validations occurred?
- Which decisions led to the current point?
Story beats (minimum narrative)
On each major step emit the applicable beats so a reader can reconstruct the path:
entry → config → validation → processing → branch → exit → error
Preferred line format (grep / caplog friendly)
{logger_name} | {Class.method} | {beat} | key=value ...
Legacy Class.method: message | key=value is acceptable if where + beat intent remain searchable.
Logging setup
import logging
import io
from pprint import pformat
from tabulate import tabulate
logger = logging.getLogger(__name__)
buffer = io.StringIO() # structured dumps
Buffers: use StringIO; log buffer.getvalue(), then truncate(0) (and seek(0) if reusing). Summaries: include shape/types, head/tail/describe, null counts where useful.
Patterns (examples)
1. Entry
def method_name(self, param1, param2):
logger.info(
f'{self.__class__.__name__}.method_name | entry | param1={param1} param2_shape={getattr(param2, "shape", type(param2))}'
)
2. Structures
df.info(buf=buffer)
logger.info(f'{dataset_name}:\n{buffer.getvalue()}')
buffer.truncate(0)
logger.info(f'Config:\n{pformat(config_dict)}')
logger.info(f'Preview:\n{tabulate(df.head(), headers=df.columns.tolist())}')
3. Branches
if condition:
logger.info(f'{self.__class__.__name__}.method_name | branch | column={column_name} present=true')
else:
logger.warning(f'{self.__class__.__name__}.method_name | branch | column={column_name} missing default={default}')
4. Validation / transforms
logger.debug(f'Input dtypes: {df.dtypes.to_dict()}')
logger.info(f'{operation_name}:\n{result.describe()}')
5. Errors
try:
logger.info(f'{operation_name} | exit | status=ok')
except Exception as e:
logger.error(f'{operation_name} | error | err={e} param1={param1} data_shape={getattr(data, "shape", None)}')
logger.info('Attempting recovery...')
Minimum on each major step
- Method entry: operation name, key parameters, data shapes/types
- Configuration: setup decisions, rule books, parameters used
- Data validation: input validation results, type conversions, missing data handling
- Processing steps: each major transformation with before/after summaries
- Conditional logic: why paths were taken
- Results / exit: success/failure indicators, output shapes
- Error context: full parameter context, data state, recovery attempts
Levels
- DEBUG: flow, dtypes, internal state; sample values when feasible
- INFO: entry/exit, config, main steps, outcomes
- WARNING: recoverable issues, fallbacks, data quality
- ERROR: failures needing attention
Every INFO line must answer (when relevant)
- Who triggered the action (user or AI agent)
- What the action did (inputs, affected models/records)
- Why the action occurred (intent, rule, or logic)
- Where it happened (class, method/function)
- Key identifiers (never raw secrets/tokens/passwords)
- Unexpected condition (if any)
- Relevant context (user ID, request/run ID, environment)
Design messages so you can find root cause without reproducing the problem blindly.
Prove the story in tests — see rule do-assert-log-story and skill Pytest Log Story Assertions.
Details
- Slug:
do-informative-logging- Always apply:
- No
- Created:
- Apr 20, 2026
- Updated:
- Jul 24, 2026
Playbook
Activities 6
- Configure Observability & Logging Bootstrap Project
- Plan Feature Build Feature
- Implement Backend Build Feature
- Implement Frontend Build Feature
- Check Definition of Done Build Feature
- TL Dispatches Workers to Build Manage Iteration