Skip to content

A flexible message logger for your MATLAB scripts and programs

License

Notifications You must be signed in to change notification settings

ismet55555/Logging-For-MATLAB

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Logger For MATLAB 📓

If you have ever wanted a nice message logger for your MATLAB scripts and programs, well my friend, you may be in luck!

Logger (logger.m) provides a lot of functionalities and flexibility which regular fprintf() or disp() commands cannot. Such added functionalities include:

  • Specifiying log message urgency levels
  • Log message formatting (red color, bold font)
  • Setting a default urgency level
  • Logging to a log file
  • Logging accross multiple files
  • and more ...

Logger was inspired by phython's logging package.

Very Basically ...

  1. Every time you want to log/show/save a message in the command window or in a file, you can do that with this message logger.
  2. The logger can display a message with different levels such as debug, error, or fatal.
  3. There are many other things this logger can do, that a simple fprintf() command cannot.

Buy Me A Coffee

👓 Overview

⏩ Quick Start

% Creating a logger
log = logger();

% Setting some logger options
log.show_time = true;
log.show_ms = true;

% Logging some Messages
log.info("Hello sweet, sweet world!")
log.warning("Hey watch out! A bus!")
log.fatal("Goodbye, crewl, crewl world ...")

Command Window Output

[23:38:58.619][INFO    ] : Hello sweet sweet world!
[23:38:58.671][WARNING ] : Hey watch out! A bus!
[23:38:58.681][FATAL   ] : Goodbye, crewl crewl world ...

NOTE: The warning log message is in red color. The fatal log message is red color and bold

👍 Compatibility

This logger was created and tested on MATLAB R2017b and R2018b on a Windows 10 operating system. Although this logger was created within those software versions and operating systems, it may work in other environments as well.

I would love to hear about usage on earlier or later MATLAB versions and other operating systems.

🚀 Installing and Setup

  1. Download/copy the logger.m file into your working directory
    • Git: Use the ol' git to clone the repo onto your computer
    • Download: Use the "Clone or Download" button GitHub provides to download this entire repo as a .zip file
    • Copy/Paste: Visit logger.m, and copy/paste all code into a new .m file script called logger.m
  2. In your script, create the logger object and store it in a variable
    • log = logger()
    • Please don't use logger = logger()
  3. Use the assigned variable to use the logger
    • log.info("This is a log message")
    • log.warning("This is a warning log message")
    • etc

💥 Usage

Logging

Obviously logging messages is the most fundemental thing to this logger thing. There are two different ways to log a message with a specific log level.

  1. Use the predefined logging methods that correspond to the specific logging level

    % Create a logger
    log = logger();
    log.default_level = 1;
    
    % Log messages with different log levels
    log.debug("This is a debug level message");
    log.info("This is a info level message");
    log.warning("This is a warning level message");
    log.error("This is a error level message");
    log.critical("This is a critical level message");
    log.fatal("This is a fatal level message");

    Command Window Output

    [INFO    ] : This is a info level message
    [WARNING ] : This is a warning level message
    [ERROR   ] : This is a error level message
    [CRITICAL] : This is a critical level message
    [FATAL   ] : This is a fatal level message
    
  2. Use the .log() method to specify a log level using an integer instead of the name of the log level

    % Create a logger
    log = logger();
    log.default_level = 1;
    
    % Log messages with different log levels
    log.log(1, "This is a debug level message");
    log.log(2, "This is a info level message");
    log.log(3, "This is a warning level message");
    log.log(4, "This is a error level message");
    log.log(5, "This is a critical level message");
    log.log(6, "This is a fatal level message");

    Command Window Output

    [INFO    ] : This is a info level message
    [WARNING ] : This is a warning level message
    [ERROR   ] : This is a error level message
    [CRITICAL] : This is a critical level message
    [FATAL   ] : This is a fatal level message
    

Changing Default Log Level

Default log level means the lowest log level which the logger will display and save to file. For example, if the default log level of a logger is set to 3 (warning), that logger will only print out and save logs that are at level 3 (warning) or above.

Changing the default log level comes in handy when, for example, you create a few debug (level 1) level logs to troubleshoot your code in key places and would like to turn these debug messages on and off depending on if you are troubleshooting or not. This turning on and off can be easily done by setting the log level from 1 (debug) to 2 (info) or vice versa.

You can change default log level by using the .default_level logger property, which takes a positive integer. Note that you can display all log levels and see the default log level using the .get_logger_levels() method.

The following is an example of changing a default log level for a logger.

% Creating the logger
log = logger();

% Logging a info and warning log
log.info("This is an info log message");
log.warning("This is a warning log message");

% Changing the default log level for logger to level 3 (warning);
log.default_level = 3;

% Logging the same info and warning log
log.info("This is an info log message");      % <-- Will not be displayed
log.warning("This is a warning log message");

Command Window Output

[INFO    ] : This is an info log message
[WARNING ] : This is a warning log message
[WARNING ] : This is a warning log message

Logging Within a Script

Using the logger within the same script file is fairly straightforward.

% Creating a logger object with default options and assigning to a variable
log = logger();

% Logging a message
log.info("This a logging message");

Logging Accross Functions

If you want to use the same logger accross multiple different functions within the same script, you can do one of the following:

  1. Pass the logger object variable into the function
    log = logger();
    log.info("This is a logging message");
    someFunction(log);
    
    function someFunction(log)
        log.info("Logging a message inside this function with same logger");
    end
  2. Declare the logger object variable a global variable
    global log
    log = logger();
    log.info("This is a logging message");
    someFunction();
    
    function someFunction()
        global log;
        log.info("Logging a message inside this function with sameN logger");
    end
  3. Create another logger with the exact same logger name. The logger is smart enough to combine duplicate logger names into one single logger group.
    log = logger("Nice Logger");
    log.info("This is a logging message");
    someFunction();
    
    function someFunction()
        log = logger("Nice Logger");
        log.info("Logging a message inside this function with same logger");
    end

Logging Accross Files

Logging accross different files is done the exact same as logging accross different functions. See the previous section for the different ways and details. For example, this shows method 3:

firstFile.m

log = logger("Nice Logger");
log.info("This a logging message");
secondFile;

secondFile.m

log = logger("Nice Logger");
log.info("Logging a message inside this function with same logger");

Using Multiple Loggers

You can assign different loggers for different purposes. For example, let's say you would like one logger to log all things related to one part of the program like maybe the data acquisition, while another logger logs all messages related to the graphical interface of the program.

In this case you can specify that each logger has its own message formatting and each logger saves its messages into seperate log files. In such a case you would also be able to seperately enable and disable each logger if needed.

Here is a short example of using two loggers in the same script.

% Creating a default logger for general program logs
logDefault = logger();
logDefault.show_date = true;
logDefault.log_to_file = true;

% Creating a logger for any data acquisition (DAQ)
logDAQ = logger("DAQ");
logDAQ.show_time = true;
logDAQ.show_ms = true;
logDAQ.log_to_file = true;

logDefault.info("Program start ...");

logDAQ.info("Starting data acquisition ..."")
for i = 1 : 1000
    try
        logDAQ.info(sprintf("Measuring data point number %i", i);
        % Code for data acquisition (DAQ) here ..
    catch
        logDAQ.error("Failed to read data point");
    end
end
logDAQ.info("Data acquisition has completed");

logDefault.info("Program ended");

📘 Reference Docummentation

Log Levels

The following are the only available log levels for the logger. Each integer corresponds to a log level. You can display all log levels and see the default log level using the .get_logger_levels() method.

Level Name Typical Usage
1 DEBUG Diagnostic and fine-grained troubleshooting
2 INFO Normal program behavior
3 WARNING Notification of potential error, but program is still ok
4 ERROR Serious issue, requires attention, may allow program to continue
5 CRITICAL Issue will lead to a termination of the program
6 FATAL Catastrophic, severe, irrecoverable situation

Creation

The following command creats a logger object that is used to log messages:

log = logger(<logger_name>, <show_date>, <show_time>, <show_logging_filename>, <show_logging_function>, <show_logging_linenumber>, <log_filename>)

You then in turn use the log variable to execute logging functions (ie. log.warning("Watch out!"))

IMPORTANT: Do not use logger as your variable (ie. logger = logger()).

Although all of the creation/constructor logger parameters are optional with default values, you may use any of these constructor parameters in the above creation command. Note that any of these can be changed anytime after creation.

Parmeter Name Type Optional Default Value Description
1 logger_name String or Char Yes "Default" Name of the logger
2 show_date Boolean Yes false Show the current date in a log message
3 show_time Boolean Yes false Show the current time in the log message
4 show_logging_filename Boolean Yes false Show the file where the log message was made
5 show_logging_function Boolean Yes false Show the function where the log message was made
6 show_logging_linenumber Boolean Yes false Show the line number where the log message was made

Creation Example

% Creating a logger that logs messages with the current date, 
% current time, and the line number that send the log

log = logger("Badass Logger", true, true, false, false, true)

Methods

Logging Methods

Method Parameter Type Description
.debug(<Log Message>) String or Char Log a debug level message (Level 1)
.info(<Log Message>) String or Char Log an info level message (Level 2)
.warning(<Log Message>) String or Char Log a warning level message (Level 3)
.error(<Log Message>) String or Char Log an error level message (Level 4)
.critical(<Log Message>) String or Char Log a critical level message (Level 5)
.fatal(<Log Message>) String or Char Log a fatal level message (Level 6)
.log(<Log Level>, <Log Message>) Integer, String or Char Log a message with any available level

Utility Methods

Method Parameter Type Description
.get_logger_levels() - List the available logging levels
.time_the_logger(<Number of Messages>) Integer Performance/Timing test for the logger
.clear_log_file() - Clear log file for this logger
.delete_log_file() - Delete log file for this logger

Properties

Message Information and Formatting

Parameter Type Default Description
.show_logger_name Boolean false Show the name of the logger in the log message
.show_date Boolean false Show the current date in a log message
.show_time Boolean false Show the current time in the log message
.show_ms Boolean false Show milliseconds in log message
.show_logging_filename Boolean false Show the file name where the log message was logged
.show_logging_function Boolean false Show the function where the log message was logged
.show_logging_linenumber Boolean false Show the line number where the log message was logged

Logger Behavior

Parameter Type Default Description
.description String or Char Some filler Custom description of the logger object instance
.default_level Integer 2 Lowest log level to be logged
.log_to_command_window Boolean true Show the log messages in the command window
.log_to_file Boolean false Save log messages to the log file
.enabled Boolean true Enable or disable the logger
.log_directory String or Char pwd Directory where log file will be saved
.log_filename String or Char <logger_name>.log File name into which the logs will be saved

🕔 Notes on Performance and Speed

  • Understand that the time duration per log may vary with the following logger settings.
    • Logging formatting additions - A logger that only shows the logger name will be very slightly faster than a logger displaying the name, date, time, and/or line number.
    • Logging to file - Currently logging to file is slower than only logging to the command window.
    • Logging to command window - Obviously if nothing is printed out, it will be faster.
  • Remember that there is a .time_the_logger() method that you can use to measure the current logger settings and compare them to a simple fprintf() command.
  • Using simple disp() and fprintf() is faster than using this logger. However logger gives you lots of convenient ability and flexibility in return.

💔 Alternatives

If you really don't like this logger, this repo, or me, well you may be in luck again! There are a few alternatives you can look into.


👤 Author

Ismet Handžić - GitHub: @ismet55555

Licence

This project is licensed under the Apache 2.0 License - Please see the LICENSE file for details.