aboutsummaryrefslogtreecommitdiffstats
path: root/efl/utils/logger.pyx
blob: d4a1335a220f35d889daec3eeb4890816cb6a9bd (plain) (blame)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Copyright (C) 2007-2013 various contributors (see AUTHORS)
#
# This file is part of Python-EFL.
#
# Python-EFL is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# Python-EFL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this Python-EFL.  If not, see <http://www.gnu.org/licenses/>.

from libc.string cimport const_char
from efl.eina cimport Eina_Log_Domain, const_Eina_Log_Domain, Eina_Log_Level, \
    eina_log_print_cb_set, eina_log_domain_register, eina_log_level_set, \
    eina_log_level_get, eina_log_domain_level_get, eina_log_domain_level_set, \
    eina_log_print, EINA_LOG_DOM_DBG, EINA_LOG_DOM_INFO, EINA_LOG_DOM_WARN, \
    EINA_LOG_DOM_ERR, EINA_LOG_DOM_CRIT
from cpython cimport PyUnicode_AsUTF8String, PY_VERSION_HEX

import logging
import types

cdef extern from "stdarg.h":
    ctypedef struct va_list:
        pass

cdef extern from "stdio.h":
    int vsprintf(char *, const_char *fmt, va_list args)

cdef extern from "Python.h":
    void PyEval_InitThreads()

cdef tuple log_levels = (
    50,
    40,
    30,
    20,
    10
)

cdef dict loggers = dict()

cdef char log_buf[1024]


PyEval_InitThreads()

cdef void py_eina_log_print_cb(const_Eina_Log_Domain *d, Eina_Log_Level level,
    const_char *file, const_char *fnc, int line,
    const_char *fmt, void *data, va_list args) with gil:

    cdef:
        unicode msg, name
        object rec, logger

    vsprintf(log_buf, fmt, args)

    msg = log_buf.decode("utf-8")
    name = d.name.decode("utf-8")

    rec = logging.LogRecord(
        name, log_levels[level], file, line, msg, None, None, fnc)
    logger = loggers.get(name, loggers["efl"])
    logger.handle(rec)

eina_log_print_cb_set(py_eina_log_print_cb, NULL)

def setLevel(self, lvl):
    cname = self.name
    if isinstance(cname, unicode): cname = PyUnicode_AsUTF8String(cname)
    eina_log_domain_level_set(cname, log_levels.index(lvl))
    logging.Logger.setLevel(self, lvl)

class PyEFLLogger(logging.Logger):

    def __init__(self, name):
        cname = name
        if isinstance(cname, unicode): cname = PyUnicode_AsUTF8String(cname)
        self.eina_log_domain = eina_log_domain_register(cname, NULL)
        loggers[name] = self
        logging.Logger.__init__(self, name)
        if PY_VERSION_HEX < 0x03000000:
            self.setLevel = types.MethodType(setLevel, self, type(self))
        else:
            self.setLevel = types.MethodType(setLevel, self)

cdef object add_logger(object name):
    logging.setLoggerClass(PyEFLLogger)

    log = logging.getLogger(name)
    if not isinstance(log, PyEFLLogger):
        # The logger has been instantiated already so lets add our own
        # initialization for it.
        cname = name
        if isinstance(cname, unicode): cname = PyUnicode_AsUTF8String(cname)
        log.eina_log_domain = eina_log_domain_register(cname, NULL)
        loggers[name] = log
        lvl = log.getEffectiveLevel()
        eina_log_domain_level_set(cname, log_levels.index(lvl))
        if PY_VERSION_HEX < 0x03000000:
            log.setLevel = types.MethodType(setLevel, log, type(log))
        else:
            log.setLevel = types.MethodType(setLevel, log)
    else:
        log.propagate = True
        log.setLevel(logging.WARNING)
    log.addHandler(logging.NullHandler())

    logging.setLoggerClass(logging.Logger)

    return log

rootlog = add_logger("efl")
rootlog.propagate = False

cdef public int PY_EFL_LOG_DOMAIN = rootlog.eina_log_domain

def logger_test_dbg():
    EINA_LOG_DOM_DBG(PY_EFL_LOG_DOMAIN, "test message", NULL)