Logger: Python API - #1593
Logger: Python API#1593nitbharambe wants to merge 12 commits into
Conversation
ee1b59e to
468e367
Compare
| class LoggerType(IntEnum): | ||
| """Logger types for opt-in diagnostic output from calculations. | ||
|
|
||
| Output is non-conclusive and intended as debugging hints for advanced users. | ||
| """ | ||
|
|
||
| do_nothing = 0 | ||
| """Logger that discards all output (no-op). Useful as a typed placeholder.""" | ||
| text = 1 | ||
| """Logger that captures timestamped text messages, including sparse-matrix hints.""" | ||
| benchmark = 2 | ||
| """Logger that captures timing information per calculation phase.""" |
There was a problem hiding this comment.
let's follow the same conventions as for the C API
There was a problem hiding this comment.
This looks different from the C side enum PGM_LoggerType. Is that intentional?
There was a problem hiding this comment.
@Jerry-Jinfeng-Guo Naming you mean? Renamed to info and then will add benchmark later.
| self._active: bool = False | ||
|
|
||
| def __del__(self) -> None: | ||
| if self._active: |
There was a problem hiding this comment.
should be mutex'ed (or at least be atomic)
| def __enter__(self) -> "Logger": | ||
| get_pgc().register_logger(self._logger_ptr) | ||
| assert_no_error() | ||
| self._active = True |
| assert_no_error() | ||
| self._python_logger = python_logger | ||
| self._level = level | ||
| self._active: bool = False |
There was a problem hiding this comment.
Did the suggested way in the link.
| get_pgc().logger_clear(self._logger_ptr) | ||
| assert_no_error() | ||
|
|
||
| def flush_to_python_logger(self) -> None: |
There was a problem hiding this comment.
in the future, we will probably want to extend with an asynchronous watcher to obtain the logs on-the-fly while the calculation is running.
To do that, we can extend the MultiThreadedTextLogger with a second buffer or queue/hive of buffers
There was a problem hiding this comment.
to that extend, should we make this a private method instead? so that later we can choose to flush differently
There was a problem hiding this comment.
I guess so. Made it private. We can specially make it available later if needed
3e7516a to
d113cdd
Compare
9174b57 to
f0a8907
Compare
f0a8907 to
2e3f9d7
Compare
2f3ac47 to
1cddc94
Compare
| def __init__( | ||
| self, | ||
| logger_type: LoggerType = LoggerType.info, | ||
| *, | ||
| python_logger: _logging.Logger | None = None, | ||
| level: int = _logging.DEBUG, |
There was a problem hiding this comment.
I feel this would be a bit confusing for users.
Do i rename level -> python_logging_level?
There was a problem hiding this comment.
I feel this would be a bit confusing for users.
Do i rename level -> python_logging_level?
why not keep the same loglevel for both python and C++ where it makes sense?
LoggerType.info->_logging.INFOLoggerType.benchmark->_logging.DEBUG
or you can do something like override_python_log_level?
Also maybe we need to consider if in the future we decide to support multiple python log levels, then we can get something like
LoggerType.warning_only -> _logging.WARNING
LoggerType.info_only -> _logging.INFO
LoggerType.debug_only -> _logging.DEBUG
as opposed to one LoggerType.info that sends warning level C++ logs to _logging.INFO, which is not great, of course
There was a problem hiding this comment.
Please also do note that there may be multi-line C++ core logs all sent to the Python logger in one single event, so maybe we need to split the output
There was a problem hiding this comment.
Regarding 2nd comment, we already split at new lines when we flush to python logger. Is there a requirement to have multiline logs under a single log of python?
_flush_to_python_logger can also be customized in such a case
There was a problem hiding this comment.
Regarding 1st, Since there is a lot of logic involved with levels, lets just let user determine which PGM-internal logging levels map to which of python logging levels.
So we recommend them creating LoggerType.info with _logging.info but not restrict them from creating LoggerType.some_type -> _logging.info
There was a problem hiding this comment.
Regarding 2nd comment, we already split at new lines when we flush to python logger. Is there a requirement to have multiline logs under a single log of python?
_flush_to_python_logger can also be customized in such a case
ahhh sorry didn't realize that. i think it's fine. logs aren't meant to be fully stable anyways
| def __init__( | ||
| self, | ||
| logger_type: LoggerType = LoggerType.info, | ||
| *, | ||
| python_logger: _logging.Logger | None = None, | ||
| level: int = _logging.DEBUG, |
There was a problem hiding this comment.
Please also do note that there may be multi-line C++ core logs all sent to the Python logger in one single event, so maybe we need to split the output
| Output is non-conclusive and intended as debugging hints for advanced users. | ||
| """ | ||
|
|
||
| info = 3 |
There was a problem hiding this comment.
Adding. Was waiting on it being available in main. Now added.
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
fdb11d5 to
06384c7
Compare
|
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>



Summary of Python API of logger
Public import:
from power_grid_model import Logger, LoggerType, both exported from the package root in__init__.py.LoggerTypecurrently has one member:LoggerType.info = 3(enum.py). (Benchmark to be added when #1598 is available)Use
Loggeras a context manager to register it for calculations and unregister it on exit.outputreturns the accumulated text;clear()empties it. Ifpython_loggeris supplied, each non-empty output line is sent at the configuredlevelon exit, then the buffer is cleared. The implementation and detailed behavior are inlogger.py.