User Guide¶
Import library¶
All commands are run from the logset namespace:
import logset
Log to Console¶
You can use the console module to set up logs that emit messages to the console’s sys.stderr stream. The module includes functions that set up console logging at a given log level: debug, info, warning, error, or critical. At their most basic, each command only requires the name of the logger that should be configured. For example, to log INFO-level messages to the console (perhaps to inform a CLI user of a command’s progress), you could use:
logset.console.info("my-logger")
Analogously, if you only want to log ERROR-level messages, you could use:
logset.console.error("my-logger")
Note
By default, logset will attempt to prevent a logger from having duplicate targets. As such, when you call a function from console module, the function will remove any pre-existing sys.stderr StreamHandlers for that logger. You can disable this behavior by setting clear_existing = False.
Log to File¶
Logs are often written to file to enable monitoring and later inspection of applications. You can use the file module to set up logs that write messages to file. Like the console module, the file module includes a function for each log level. However, in addition to a logger name, these functions also require the path to the file where the logs will be writting. For example, to log DEBUG-level messages to my-file.log, you could use:
logset.file.debug("my-logger", "my-file.log")
Analogously, if you only want to log ERROR-level messages, you could use:
logset.file.error("my-logger", "my-file.log")
Note
By default, logset will attempt to prevent a logger from having duplicate targets. As such, when you call a function from file module, the function will remove any pre-existing FileHandler, RotatingFileHandler, or TimedRotatingFileHandler objects that target the same file for that logger. You can disable this behavior by setting clear_existing = False.
By default, logset will open/create the log file immediately. Set delay = True to defer opening/creating the log file until the first log message is emitted:
logset.file.debug("my-logger", "my-file.log", delay=True)
Also by default, logset will raise an error if the log file’s parent folder does not exist. Set make_parents = True to create parent folders as needed:
logset.file.debug("my-logger", "my-file.log", make_parents=True)
Log Format¶
Often, you may want to customize the logging format to include more than just the logging message. For example, to include the timestamp and/or sub-logger associated with the message. You can use the optional format argument to set the logging format. For example, to include a timestamp, sub-logger name, and log message in a file log, you could use:
logset.file.debug(
"my-logger", "my-file.log", format="%(asctime)s - %(name)s - %(message)s"
)
Here, the %(asctime)s is the timestamp, %(name)s is the sub-logger name, and %(message)s is the logged message. Consult the Python docs for a full list of supported logging format string values.
If you do not specify a logging format, then the default format will depend on whether the logger had any pre-existing handlers with the same logging target. If there are pre-existing handlers with the same target, then logset will default to the format of the first such handler that has a formatter. If there are no such handlers, then logset will use the value of fallback_format as the format. This defaults to "%(message)s" (equivalent to the log message), or you can specify a different fallback format:
# Format will default to "%(asctime)s - %(message)s"
# if there are no pre-existing handlers with the same target
logset.file.debug(
"my-logger", "my-file.log", fallback_format="%(asctime)s - %(message)s"
)
Rotating File Logs¶
Many applications will want to periodically rotate their log files. This prevents log files from becoming bloated with out-of-date information, and can help with log searchability. Logset supports two types of rotating files:
Files that rotate based on a maximum allowed size, and
Files that rotate on a fixed time interval
Size Rotation¶
You can use the rotate_bytes argument to implement a file log that rotates after reaching a maximum allowed number of bytes. For example, to rotate the log file after reaching 1MB:
logset.file.debug("my-logger", "my-file.log", rotate_bytes=1000000)
By default, a rotating file will save 1 backup log, which is the most recent log file prior to the rotation of the current log. You can use backup_count to save a different number of backups. For example, to save the latest 3 logs, you could use:
logset.file.debug("my-logger", "my-file.log", rotate_bytes=1000000, backup_count=3)
Backup files follow the name of the log file, but with .1, .2, .3, etc appended to the file name. For example:
my-file.log(current log)my-file.log.1(previous log)my-file.log.2(second most recent log)etc
Timed Rotation¶
You can use the rotate_when and rotate_interval arguments to implement a file log that rotates on a fixed time interval. The rotate_when argument specifies the type of interval - consult the Python docs for its supported values. The rotate_interval argument is the interval length. For example, to rotate the logs every 3 days, you could use:
logset.file.debug("my-logger", "my-file.log", rotate_when="D", rotate_interval=3)
Like files that rotate on size, timed rotating files will save 1 backup log. As discussed in the section above, you can use backup_count to save a different number of backup logs. For example, if you want to rotate files daily, and save one week (7 days) of backups, you could use:
logset.file.debug(
"my-logger", "my-file.log", rotate_when="D", rotate_interval=1, backup_count=7
)
Warning
Timed rotating files will rotate based on when the logger was started, rather than the time on the clock. This means that timed rotation is best suited for long running processes that maintain the logger continuously.
Critically, if you are writing a CLI, then the logger is usually restarted with each new command call. Thus, if your commands take less time to run than the rotation interval, then the log file will never rotate, as the logger will be restarted with each new CLI call. For CLIs with short-running commands, size rotation is usually a better option than timed rotation.
Advanced¶
Event Propagation¶
By default, logset stops a logger from propagating events to ancestor loggers. This is to prevent ancestors from logging to the same target, which could cause duplicate messages. Advanced users can disable this by setting propagate = True. For example:
logset.file.debug("my-logger", "my-file.log", propagate=True)