一键导入
charm-logging
Charm logging conventions — log levels, message formatting, tense, printf-style templating, common pitfalls
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Charm logging conventions — log levels, message formatting, tense, printf-style templating, common pitfalls
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Known-good Juju bundle shapes (COS Lite, 12-Factor + COS, Identity Platform, Charmed Kubeflow) — canonical app lists and relation edges
Implementing Juju actions for operational tasks in charms. WHEN: add Juju actions to a charm, implement backup / rotate-credentials / restore actions, declare actions in charmcraft.yaml, write action handlers, test actions with Scenario, run actions with juju run.
Adding and validating charm configuration options. WHEN: add charm configuration options, declare config in charmcraft.yaml, validate config values in config-changed, apply config to a Pebble layer, apply config to a machine charm, write Scenario tests for config.
End-to-end workflow for building ops-framework charms for custom applications (K8s and machine). WHEN: build a custom Juju charm, write src/charm.py with Pebble, write a machine charm with systemd, decide K8s vs machine substrate, scaffold a non-paas-charm with charmcraft init, customise the ops framework charm lifecycle.
Workflow for charming infrastructure software (databases, caches, message brokers, proxies, monitoring). WHEN: charm infrastructure software, charm a database / cache / message broker / proxy / monitoring system, implement peer relations, leader election, primary/replica failover, backup and restore actions, clustering.
Expert guidance for developing, building, testing, and publishing Juju charms using charmcraft. WHEN: edit charmcraft.yaml, run charmcraft pack, run charmcraft init, manage charm libraries, publish a charm to Charmhub, set up multi-base builds, configure relations / config options, set up storage or containers.
| name | charm-logging |
| description | Charm logging conventions — log levels, message formatting, tense, printf-style templating, common pitfalls |
| globs | ["src/**/*.py","lib/**/*.py"] |
These guidelines standardise logging patterns across the charm
ecosystem so logs are useful both at development time and during
production operation. Logging levels follow the Python logging
module. Based on Canonical spec OB061.
Adapted from the
charm-loggingskill intonyandrewmeyer/charming-with-claude, CC BY 4.0 (Tony Meyer, 2025). Reformatted for cantrip's bundled-skill frontmatter; content otherwise unchanged. See Provenance at the foot of this skill for the source link.
Purpose: detailed information for debugging or troubleshooting.
debug-log level is INFO, so DEBUG messages are typically not seen.Examples:
Purpose: record of the normal operation of the charm. This is the default Juju debug-log level.
Examples:
Purpose: potential issues that may lead to errors if not addressed.
Examples:
Purpose: a failure preventing part of the workload from working properly, without completely breaking its core service.
Examples:
logger.exception).Purpose: a severe error breaking the charm's core service, requiring immediate attention.
Examples:
Use warnings.warn rather than logging.warn — both appear in Juju logs, but warnings provides more control and is designed for this use case.
Avoid ambiguity. Messages should be understood without additional context.
# BAD — unclear what "bad response" means
logger.error("failed to obtain status: bad response")
# GOOD — actionable context
logger.error("failed to obtain status: server returned HTTP 503")
# GOOD
logger.info("restarting service %s", self._service_name)
# BAD
logger.info("Restarting service %s.", self._service_name)
| When | Tense | Example |
|---|---|---|
| Before an action | Future simple | "alertmanager service will be restarted" |
| After an action | Past simple | "alertmanager service restarted" |
| During an action (sequence) | Present continuous | "updating ingress for relation 'ingress:10'" — only if a follow-up message is guaranteed |
Avoid present continuous unless it is part of a guaranteed sequence with a clear reference between start and end messages.
The meaning of a log line should not depend on previous or subsequent lines. Include enough context to be useful during debugging or auditing.
Explain not only what happened, but why:
# BAD
logger.error("the setup of some ingress relation failed, see previous logs")
# GOOD
logger.error("failed processing ingress relation %s: provider is not ready", relation)
Operation IDs, unit names, resource paths:
"unit mysql/1 failed health check: probe timed out"
Always use printf-style percentage formatting, never f-strings.
# BAD
logger.debug(f"updating configuration file {filename}")
logger.debug("updating configuration file {}".format(filename))
# GOOD
logger.debug("updating configuration file %s", filename)
The logging module formats lazily, so the expensive string only
materialises if the log line is actually emitted. f-strings build
the string eagerly regardless of level.
Adapted from the charm-logging skill
in tonyandrewmeyer/charming-with-claude,
CC BY 4.0 (Tony Meyer, 2025). Content reformatted for cantrip's
bundled-skill frontmatter; otherwise unchanged.