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
126
127
|
#!/usr/bin/env python3
# GNUNET_FORCE_LOG format [component];[file];[function];[from line [to line]];loglevel
import os
import logging
class LogDefinition:
def __init__(self, component, forced, loglevel):
self.component = component
self.forced = forced
# string here, comes from env after all.
self.loglevel = loglevel
class GnunetLoglevel:
def __init__(self, string, level, function):
self.string = string
self.level = level
self.function = function
def __str__(self):
return self.string
def getLevel(self):
return self.level
def getFunction(self):
return self.function
class GnunetLogger:
def __init__(self, component):
self.logger = logging.getLogger(component)
self.ERROR = GnunetLoglevel("ERROR", logging.ERROR, self.logger.error)
self.WARNING = GnunetLoglevel("WARNING", logging.WARNING, self.logger.warning)
self.INFO = GnunetLoglevel("INFO", logging.INFO, self.logger.info)
self.DEBUG = GnunetLoglevel("DEBUG", logging.DEBUG, self.logger.debug)
self.component = component
self.loglevel = None
# Setting the *logging* loglevel in order to have the
# chance of changing the *logger* (object) loglevel along the
# execution. So this particular loglevel has no relevance
# (might have been any other loglevel).
logging.basicConfig(level=logging.INFO)
self.no_forced_definitions = True
self.definitions = list()
if os.environ.get("GNUNET_LOG"):
self.__parse_definitions(os.environ.get("GNUNET_LOG"), False)
if os.environ.get("GNUNET_FORCE_LOG"):
self.no_forced_definitions = False
self.__parse_definitions(os.environ.get("GNUNET_FORCE_LOG"), True)
def string_to_loglevel(self, level):
level_map = {
"ERROR": self.ERROR,
"WARNING": self.WARNING,
"INFO": self.INFO,
"DEBUG": self.DEBUG}
# Defaults to INFO.
return level_map.get(level, self.INFO)
def setup(self, loglevel):
self.loglevel = loglevel
def log(self, message, message_loglevel):
# Ordinary case (level setup + nothing forced).
if self.loglevel and self.no_forced_definitions:
self.logger.setLevel(level=self.loglevel.getLevel())
message_loglevel.getFunction()(message)
return
# We crawl through GNUNET_FORCE_LOG definitions,
# or GNUNET_LOG (in case of non-forced definition
# and non-given loglevel at object creation time)
for defi in self.definitions:
if defi.forced or not self.loglevel:
# Temporarily checking only the component name.
# To be extended with all the others definition-parts.
if self.component == defi.component:
self.logger.setLevel(
level=self.string_to_loglevel(defi.loglevel).getLevel())
message_loglevel.getFunction()(message)
return
# If the flow got here, then one of the following
# may hold.
#
# (1) GNUNET_FORCE_LOG was given and no definition was
# found for this component (neither forced nor unforced).
# Possibly, there also exists a default loglevel.
if self.loglevel:
self.logger.setLevel(
level=self.loglevel.getLevel())
# (2) GNUNET_FORCE_LOG was NOT given and neither was
# a default loglevel, and also a unforced definition
# wasn't found. Must assign a made-up loglevel.
else:
self.logger.setLevel(level=logging.INFO)
message_loglevel.getFunction()(message)
def __parse_definitions(self, line, forced):
gfl_split = line.split("/")
for component in gfl_split:
gfl_split_split = component.split(";")
if 5 != len(gfl_split_split):
print("warning: GNUNET_(FORCE_)LOG is malformed")
return
definition = LogDefinition(gfl_split_split[0],
forced,
loglevel=gfl_split_split[4])
self.definitions.append(definition)
|