In [1]:
import dynamo as dyn
import time

from dynamo import LoggerManager, main_tqdm, main_critical,main_warning, main_info, Logger
from dynamo.dynamo_logger import main_tqdm, main_critical,main_warning, main_info, Logger
import dynamo.tools

Introduction to dynamo logger utilities for developers

"main_*" utility functions

Function names started with "main_" in dynamologger.py are utility functions for directly writing information in the main logger. We design these functions so that developers can avoid tedious Logger class creation. Under most circumstances , developers only need to use main* series functions. We build our logger upon Python's logging library and our main logger occupies "dynamo" namespace in Python's underlying logging library. Devlopers can create logger with different namespaces with Logger and LoggerManager class we will introduce later.

main_tqdm

A handy utility function to allow developers to time loops in TQDM library style.

In [2]:
for i in main_tqdm(range(1, 11), desc="using TQDM style logging"):
    time.sleep(0.1)
for i in LoggerManager.progress_logger(range(1, 11), progress_name="using LoggerManager's progress_logger", indent_level=2):
    time.sleep(0.1)
|-----> [using TQDM style logging] in progress: 100.0000%
|-----> [using TQDM style logging] finished [1.0725s]
|-----------> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [using LoggerManager's progress_logger] finished [1.0570s]

main_info, main_warning, main_critical

In [3]:
main_info("someInfoMessage")
main_info("someInfoMessage", indent_level=0)
main_warning("someWarningMessage", indent_level=2)
main_critical("someCriticalMessage", indent_level=3)
main_critical("someERRORMessage", indent_level=2)
|-----> someInfoMessage
|> someInfoMessage
|-----------? someWarningMessage
|-----------------!! someCriticalMessage
|-----------!! someERRORMessage

Log nested loops

To log nested loops, developers should pass different loggers to main_tqdm's logger argument, because each logger has its own small timer variable and thus the single logger cannot handle this case.

In [4]:
for i in main_tqdm(range(1, 11), desc="[Outer] using LoggerManager's progress_logger", logger=LoggerManager.get_main_logger()):
    for i in main_tqdm(range(1, 4), desc="[Inner] using LoggerManager's progress_logger", logger=LoggerManager.gen_logger("someLoggerSpace"), indent_level=2):
        time.sleep(0.1)
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3206s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3169s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3154s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3216s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3150s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3158s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3160s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3141s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3175s]
|-----------> [[Inner] using LoggerManager's progress_logger] in progress: 100.0000%
|-----------> [[Inner] using LoggerManager's progress_logger] finished [0.3152s]
|
|-----> [[Outer] using LoggerManager's progress_logger] finished [3.2337s]

LoggerManager class

We adopt Factory design pattern and create LoggerManager to create and manage important loggers.

LoggerManager's main_logger() getter

This getter function returns the main logger dynamo logger. The statements below basically do the same thing as the code block above with "main_*" functions.

In [5]:
main_logger = LoggerManager.get_main_logger()
test_logger = main_logger
test_logger.info("someInfoMessage")
test_logger.info("someInfoMessage", indent_level=0)
test_logger.warning("someWarningMessage", indent_level=2)
test_logger.critical("someCriticalMessage", indent_level=3)
test_logger.critical("someERRORMessage", indent_level=2)
|-----> someInfoMessage
|> someInfoMessage
|-----------? someWarningMessage
|-----------------!! someCriticalMessage
|-----------!! someERRORMessage

Logger class

Developers can create loggers with different namespace and set their own logging levels. For example, some important functions may have their own logger namespace. Each logger instance has an internal timer to record some code blocks' lapsed time. log_time() is for logging the current time and save the lapsed time amount from the last log_time() call. The Logger constructor calls log_time.

In [6]:
test_logger = Logger("someLoggerSpace")
total = 10
test_logger.log_time()
for i in range(total):
    # test_logger.report_progress(i / total * 100)
    test_logger.report_progress(count=i, total=total)
    time.sleep(0.1)
test_logger.finish_progress(progress_name="pytest simple progress logger test")
|-----> in progress: 90.0000%
|-----> [pytest simple progress logger test] finished [1.0609s]

Known issue main_tqdm currently does not support nested loops as mentioned above. This can be avoided by using two different loggers for now.

In [7]:
for i in main_tqdm(range(1, 11), desc="using LoggerManager's progress_logger"):
    for i in main_tqdm(range(1, 4), desc="using LoggerManager's progress_logger"):
        time.sleep(0.1)
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3182s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3198s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3225s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3133s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3161s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3154s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3138s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3186s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3188s]
|-----> [using LoggerManager's progress_logger] in progress: 100.0000%
|-----> [using LoggerManager's progress_logger] finished [0.3209s]
|
|-----> [using LoggerManager's progress_logger] finished [0.0045s]

As the above results show, the final result for the outer loop is incorrect.