Juju’s debug-log
feature is one of the most powerful tools you have as a Juju developer. It is extremely useful for debugging and finding the root cause of an issue.
There are two steps to successfully using debug logs:
- Set the
logging-config
- Use
juju debug-log
Setting logging-config
Juju saves or discards logs according to the value of the model config key logging-config
. Therefore, logging-config
needs to be set before the events you want to collect logs for (i.e. before attempting to reproduce a bug).
Note: since logging-config
is a model config key, it is scoped per model. You may have to set logging-config
on the controller
model as well as any workload models you’re interested in.
The general form of the logging-config
key is:
filter1=level1;...;filterN=levelN
Filters
filterX
can be any of the following:
-
<root>
- matches all machine agent logs -
unit
- matches all unit agent logs - a module name, e.g.
juju.worker.apiserver
- a label, e.g.
#charmhub
A module represents a single component of Juju, e.g. a worker. Generally, modules correspond one-to-one with Go packages in the Juju source tree. The module name is the value passed to loggo.GetLogger
or loggo.GetLoggerWithLabels
.
Modules have a nested tree structure - for example, the juju.api
module includes submodules juju.api.application
, juju.api.cloud
, etc. <root>
is the root of this module tree.
Labels cut across the module tree, grouping various modules which deal with a certain feature or information flow. For example, the #charmhub
label includes all modules involved in making a request to Charmhub.
Labels are defined in core/logger/labels.go. The currently supported labels are:
Label | Description |
---|---|
#http |
HTTP requests |
#metrics |
Metric outputs - use as a fallback when Prometheus isn’t available |
#charmhub |
Charmhub client and callers. |
#cmr |
Cross model relations |
#cmr-auth |
Authentication for cross model relations |
#secrets |
Juju secrets |
Levels
There are six severity levels in Juju. In decreasing order of severity:
Level | Description |
---|---|
CRITICAL |
Indicates a severe failure which could bring down the system. |
ERROR |
Indicates failure to complete a routine operation. |
WARNING |
Indicates something is not as expected, but this is not necessarily going to cause an error. |
INFO |
A regular log message intended for the user. |
DEBUG |
Information intended to assist developers in debugging. |
TRACE |
The lowest level - includes the full details of input args, return values, HTTP requests sent/received, etc. |
When you set logging-config
to module=level
, then Juju saves that module’s logs for the given severity level and above. For example, setting logging-config
to juju.worker.uniter=WARNING
will capture all CRITICAL
, ERROR
and WARNING
logs for the uniter, but discard logs for lower severity levels (INFO
, DEBUG
, TRACE
).
Examples
To collect debug logs for the dbaccessor
worker:
juju model-config -m controller logging-config="juju.worker.dbaccessor=DEBUG"
To collect debug logs for the mysql/0
unit:
juju model-config -m foo logging-config="unit.mysql/0=DEBUG"
To collect trace logs for Charmhub requests:
juju model-config -m controller logging-config="#charmhub=TRACE"
Using juju debug-log
After setting the logging-config
, you can view the logs using the juju debug-log
command. debug-log
has several different --include*
/ --exclude*
flags that you can use to filter the logs and extract the relevant log lines. These options are pretty well-covered in juju debug-log --help
, but in short:
-
--include
/--exclude
filters by entity (machine, unit, or application) -
--include-module
/--exclude-module
filters by module -
--include-label
/--exclude-label
filters by label
The individual --include*
/ --exclude*
values are ORed together, and then ANDed together for each different --include*
/ --exclude*
flag.