See first: Juju | Log, Juju | How to manage logs > Manage the logging configuration
To log a message in a charm, import Python’s logging
module, then use the getLogger()
function with the desired level. For example:
import logging
# ...
logger = logging.getLogger(__name__)
class HelloOperatorCharm(ops.CharmBase):
# ...
def _on_config_changed(self, _):
current = self.config["thing"]
if current not in self._stored.things:
# Note the use of the logger here
logger.debug("found a new thing: %r", current)
self._stored.things.append(current)
See more:
Juju automatically picks up logs from charm code that uses the Python logging facility, so we can use the Juju debug-log
command to display logs for a model. Note that it shows logs from the charm code (charm container), but not the workload container. Read “Use juju debug-log
” for more information.
Besides logs, stderr
is also captured by Juju. So, if a charm generates a warning, it will also end up in Juju’s debug log. This behaviour is consistent between K8s charms and machine charms.
Tips for good practice:
-
Note that some logging is performed automatically by the Juju controller, for example when an event handler is called. Try not to replicate this behaviour in your own code.
-
Keep developer specific logging to a minimum, and use
logger.debug()
for such output. If you are debugging a problem, ensure you comment out or remove large information dumps (such as config files, etc.) from the logging once you are finished. -
When passing messages to the logger, do not build the strings yourself. Allow the logger to do this for you as required by the specified log level. That is:
# Do this!
logger.info("Got some information %s", info)
# Don't do this
logger.info("Got some information {}".format(info))
# Or this ...
logger.info(f"Got some more information {more_info}")