Intro to evaluating logs
Options For Viewing Logs
cat
There are a couple quick options for looking at logs.
-
$ dmesg
(contents of the kernel ring buffer. Also sent to syslog.) -
$ cat /var/log/syslog
(can always$ cat /var/log/syslog | grep 'keyword'
)
on Rpi -
$ cat /var/log/messages
Another option with more functionality is journald
journalctl
Some quick journalctl commands to get started
-
$ journalctl -b
(current boot) -
$ journalctl -b -1
(previous boot)
To list the boots of the system $ journalctl --list-boots
$ journalctl --since "1 hour ago"
$ journalctl --since "7 days ago"
$ journalctl --since "2019-01-01 00:00:00" --until "2019-02-01 00:00:00"
By services (can add options at the end. “-r” to reverse sort, “-o json-pretty” format)
$ journalctl -u ssh.service -u bluetooth.service
To follow add ‘f
$ journalctl -u bluetooth.service -f
To send to a file
$ journalctl > dump.log
Examples
$ journalctl --unit=systemd-networkd
$ journalctl --unit=wpa_supplicant
Python Logging (including journal)
Logging libraries give useful functions in your python script for logging (info, debugging, errors). And you can add a journal option to output to the journal.
Couple approaches I use
- basicConfig(). Quick, simple logging with basicConfig(). With basicConfig() you can configure the root logger but you can not configure custom loggers. Have to use handlers and formatters.
- RotatingFileHandler/JournalHandler. When you want to output to multiple places (console/standard output stream, a log file, and the journal) it is better to use Handlers. RotatingFileHandler lets you specify the max size of the log and enables rolling log files.
RotatingFileHandler
Using RotatingFileHandler for logging will create 3 loggers in this example for three outputs
- console
- regular log
- error log
#!/usr/bin/env python3
import logging, sys, os
from logging.handlers import RotatingFileHandler
def setup_logging(log_dir):
# Main logger
#main_logger = logging.getLogger()
main_logger = logging.getLogger(__name__)
main_logger.setLevel(logging.INFO)
log_file_format = logging.Formatter("[%(levelname)s] - %(asctime)s - %(name)s - : %(message)s in %(pathname)s:%(lineno)d")
log_console_format = logging.Formatter("[%(levelname)s]: %(message)s")
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(log_console_format)
exp_file_handler = RotatingFileHandler('{}/exp_debug.log'.format(log_dir), maxBytes=10**6, backupCount=5) # 10MB file
exp_file_handler.setLevel(logging.DEBUG)
exp_file_handler.setFormatter(log_file_format)
exp_errors_file_handler = RotatingFileHandler('{}/exp_error.log'.format(log_dir), maxBytes=10**6, backupCount=5)
exp_errors_file_handler.setLevel(logging.WARNING)
exp_errors_file_handler.setFormatter(log_file_format)
main_logger.addHandler(console_handler)
main_logger.addHandler(exp_file_handler)
main_logger.addHandler(exp_errors_file_handler)
return main_logger
if __name__ == "__main__":
main_logger = setup_logging(os.path.dirname(os.path.abspath(__file__)))
main_logger.info("setup logging module")
mylist = [1, 2]
try:
print(mylist[4])
except Exception as e:
main_logger.error("exception error", exc_info=True)
Add JournalHandler
Add JournalHandler for outputting logs to journal (useful with boot)
$ sudo apt install python3-systemd
#!/usr/bin/env python3
import logging, sys, os, systemd.daemon
from systemd.journal import JournalHandler
from logging.handlers import RotatingFileHandler
def setup_logging(log_dir):
# Main logger
# If main/journal=INFO then ALL (both loggers) info's get journal'd and logged
# If main=CRIT,journ=INFO then only journal.info's get journal'd
# If main=INFO,journ=CRIT then nothing journal'd but main info is logged
# Use $ journalctl --since "1 hour ago" to check
main_logger = logging.getLogger(__name__)
journal_logger = logging.getLogger('journal')
main_logger.setLevel(logging.CRITICAL)
journal_logger.setLevel(logging.INFO) # use logging.CRITICAL to turn logging off
log_file_format = logging.Formatter("[%(levelname)s] - %(asctime)s - %(name)s - : %(message)s in %(pathname)s:%(lineno)d")
log_console_format = logging.Formatter("[%(levelname)s]: %(message)s")
journal_format = logging.Formatter("[%(levelname)s] - %(name)s - : %(message)s in %(pathname)s:%(lineno)d")
journal_logger.addHandler(JournalHandler())
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(log_console_format)
exp_file_handler = RotatingFileHandler('{}/exp_debug.log'.format(log_dir), maxBytes=10**6, backupCount=5) # 10MB file
exp_file_handler.setLevel(logging.DEBUG)
exp_file_handler.setFormatter(log_file_format)
exp_errors_file_handler = RotatingFileHandler('{}/exp_error.log'.format(log_dir), maxBytes=10**6, backupCount=5)
exp_errors_file_handler.setLevel(logging.WARNING)
exp_errors_file_handler.setFormatter(log_file_format)
main_logger.addHandler(console_handler)
main_logger.addHandler(exp_file_handler)
main_logger.addHandler(exp_errors_file_handler)
return main_logger, journal_logger
if __name__ == "__main__":
main_logger, journal_logger = setup_logging(os.path.dirname(os.path.abspath(__file__)))
main_logger.info("Testing logger output")
journal_logger.info(__file__ + ' Marking journal')
mylist = [1, 2]
try:
print(mylist[4])
except Exception as e:
main_logger.error("exception error", exc_info=True)
journal_logger.error("exception error", exc_info=True)
Short method
from systemd import journal
journal.write("Test outputting to journal")