1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
# Copyright (c) 2018-2019 Robin Jarry
# Copyright (c) 2020 6WIND S.A.
# SPDX-License-Identifier: MIT
from contextlib import contextmanager
import logging
from _libyang import ffi, lib
from .util import c2str
# -------------------------------------------------------------------------------------
LOG = logging.getLogger("libyang")
LOG.addHandler(logging.NullHandler())
LOG_LEVELS = {
lib.LY_LLERR: logging.ERROR,
lib.LY_LLWRN: logging.WARNING,
lib.LY_LLVRB: logging.INFO,
lib.LY_LLDBG: logging.DEBUG,
}
def get_libyang_level(py_level):
for ly_lvl, py_lvl in LOG_LEVELS.items():
if py_lvl == py_level:
return ly_lvl
return None
@contextmanager
def temp_log_options(opt: int = 0):
opts = ffi.new("uint32_t *", opt)
lib.ly_temp_log_options(opts)
yield
lib.ly_temp_log_options(ffi.NULL)
@ffi.def_extern(name="lypy_log_cb")
def libyang_c_logging_callback(level, msg, data_path, schema_path, line):
args = [c2str(msg)]
fmt = "%s"
if data_path:
fmt += ": %s"
args.append(c2str(data_path))
if schema_path:
fmt += ": %s"
args.append(c2str(schema_path))
if line != 0:
fmt += " line %u"
args.append(line)
LOG.log(LOG_LEVELS.get(level, logging.NOTSET), fmt, *args)
def configure_logging(enable_py_logger: bool, level: int = logging.ERROR) -> None:
"""
Configure libyang logging behaviour.
:arg enable_py_logger:
If False, configure libyang to store the errors in the context until they are
consumed when Context.error() is called. This is the default behaviour.
If True, libyang log messages will be sent to the python "libyang" logger and
will be processed according to the python logging configuration. Note that by
default, the "libyang" python logger is created with a NullHandler() which means
that all messages are lost until another handler is configured for that logger.
:arg level:
Python logging level. By default only ERROR messages are stored/logged.
"""
ly_level = get_libyang_level(level)
if ly_level is not None:
lib.ly_log_level(ly_level)
if enable_py_logger:
lib.ly_log_options(lib.LY_LOLOG | lib.LY_LOSTORE)
lib.ly_set_log_clb(lib.lypy_log_cb)
else:
lib.ly_log_options(lib.LY_LOSTORE)
lib.ly_set_log_clb(ffi.NULL)
configure_logging(False, logging.ERROR)
|