Logging¶
Introduction¶
Arjuna’s logging features as provided by log
module, give you precise control over what is included in console display and log file.
For each test run, Arjuna creates a log file with the name arjuna.log in <Test Project Directory>/report/<run report dir>/log directory.
Arjuna’s Logging Functions to Support Python Logging Levels¶
Arjuna provides individual logging functions to support the default Python logging levels:
DEBUG -
log_debug
INFO -
log_info
WARNING -
log_warning
ERROR -
log_error
FATAL -
log_fatal
The levels work just like Python logging levels. FATAL has the top priority and DEBUG has the least.
Controlling Which Log Messages Are Included on Console and in Log File¶
When you set a log level, only the log messages that are of same or higher priority get logged.
For example, setting a log level to WARNING would mean:
Calls to log_warning, log_error and log_fatal will be entertained.
Calls to log_info and log_debug will be ignored.
Default Logging Levels¶
Default logging level for console is INFO.
Default logging level for log file (arjuna.log) is DEBUG.
Arjuna’s TRACE Log Level¶
Arjuna adds an additional level of logging - TRACE - which is of lower priority than DEBUG.
This is parimarily added so that Arjuna’s internal logging is kept to a minimum even when the logging is taking place at DEBUG level.
You can use it in your test project with a similar goal by using log_trace
call.
Overriding Logging Level Defaults¶
You can change Arjuna’s logging level defaults using the following commands in command line:
–display-level: Set level for console logging.
–logger-level: Set level for file logging (arjuna.log)
Contextual Logging¶
This is an advanced feature provided by Arjuna.
You can set one or more contexts (strings) to log messages.
log_info("test context 2", contexts="test2") log_info("test context 4", contexts={"test3", "test4"})
A log message with a context(s) set for it does not get logged by default in Arjuna. It is only logged when ArjunaOption.LOG_ALLOWED_CONTEXTS has been accordingly set to include the context string. This can be done by any of the following means:
Passing
--ao LOG_ALLOWED_CONTEXTS <comma separated context strings>
to the command line.Overrding LOG_ALLOWED_CONTEXTS in the reference configuration.
Note: Log messages without contexts set for them will work as usual and are not impacted by the LOG_ALLOWED_CONTEXTS option.
Auto-Logging using @track Decorator¶
Many a times, you want to log messages at the beginning and end of a Python function/method call.
This is a primary use case and usually depends on test author’s commitment to logging (and needs conscious efforts.)
Tracking Methods, Functions, Properties¶
Arjuna’s solves this by provding auto-logging using its @track
decorator. It will log:
Beginning of the call with provided arguments.
End of the call with return value (Long return values are truncated for brevity.)
Exceptions and exception trace if any exception is raised in calling the given function/method/property.
- You can use @track with:
Functions
Bound Methods in a class
Class Methods in a class
Static Methods in a class
Properties in a class
Following are some samples:
# Function @track def test1(self, a, *vargs, b=None, **kwargs): log_debug("in test1") class MethodTrack: # Bound Method @track def test1(self, a, *vargs, b=None, **kwargs): log_debug("in test1") # Class method @track @classmethod def cls_method_1(cls, a): log_debug("in cls_method") # Static Method @track @staticmethod def stat_method_1(a): log_debug("in stat_method") # Property getter @track @property def prop1(self): log_debug("prop1 getter") return self._p # Property setter. Note that just setting this will also decorate the getter. @track @prop1.setter def prop1(self, value): log_debug("prop1 setter") self._p = value
Tracking All Methods in a Class¶
If you want to track all methods in a class, you can decorate the class with @track rather than decorating all individual methods.
This will:
- Track all
Bound Methods in a class
Class Methods in a class
Static Methods in a class
- NOT track:
properties (They still need to be individually decorated.)
Following is a sample:
@track class ClassTrack: def __init__(self, a, *vargs, b=None, **kwargs): log_debug("in __init__") def test1(self, a, *vargs, b=None, **kwargs): log_debug("in test1") @classmethod def cls_method(cls, a): log_debug("in cls_method") @staticmethod def stat_method(a): log_debug("in stat_method")
Default Logging Level for @track¶
To control verbosity of logging, @track uses the following default logging levels:
DEBUG for all public methods.
TRACE for all protected (begin with “_”), private (begin with “__”) and magic methods (the dunder methods begin and end with “__”)
Changing Logging Level for @track¶
You can change the logging level for an object decorated with @track by providing the level as argument:
@track("info") class ClassTrackInfo: pass
Note: This does not impact logging level for non-public methods.