2 # Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
3 # This file is part of OSM
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 # For those usages not covered by the Apache License, Version 2.0 please
20 # contact with: nfvlabs@tid.es
29 import threading
# only for logging purposes (not for using threads)
37 log_to_console
: bool = False,
41 self
._last
_log
_time
= None # used for time increment in logging
42 self
._log
_to
_console
= log_to_console
47 self
.log
= logging
.getLogger(__name__
)
49 def debug(self
, msg
: str):
50 self
._log
_msg
(log_level
='DEBUG', msg
=msg
)
52 def info(self
, msg
: str):
53 self
._log
_msg
(log_level
='INFO', msg
=msg
)
55 def warning(self
, msg
: str):
56 self
._log
_msg
(log_level
='WARNING', msg
=msg
)
58 def error(self
, msg
: str):
59 self
._log
_msg
(log_level
='ERROR', msg
=msg
)
61 def critical(self
, msg
: str):
62 self
._log
_msg
(log_level
='CRITICAL', msg
=msg
)
64 ##################################################################################################
66 def _log_msg(self
, log_level
: str, msg
: str):
67 """Generic log method"""
68 msg
= self
._format
_log
(
75 include_coroutine
=True
77 if self
._log
_to
_console
:
80 if self
.log
is not None:
81 if log_level
== 'DEBUG':
83 elif log_level
== 'INFO':
85 elif log_level
== 'WARNING':
87 elif log_level
== 'ERROR':
89 elif log_level
== 'CRITICAL':
90 self
.log
.critical(msg
)
98 include_path
: bool = False,
99 include_thread
: bool = False,
100 include_coroutine
: bool = True
103 # time increment from last log
104 now
= time
.perf_counter()
105 if self
._last
_log
_time
is None:
106 time_str
= ' (+0.000)'
108 diff
= round(now
- self
._last
_log
_time
, 3)
109 time_str
= ' (+{})'.format(diff
)
110 self
._last
_log
_time
= now
116 fi
= inspect
.stack()[level
]
117 filename
= fi
.filename
120 # filename without path
122 i
= filename
.rfind('/')
124 filename
= filename
[i
+1:]
127 dt
= datetime
.datetime
.now().strftime('%Y-%m-%d %H:%M:%S.%f')
129 # dt = time_str # logger already shows datetime
133 thread_name
= 'th:{}'.format(threading
.current_thread().getName())
140 if include_coroutine
:
142 if asyncio
.Task
.current_task() is not None:
143 def print_cor_name(c
):
146 for m
in inspect
.getmembers(c
):
147 if m
[0] == '__name__':
151 coro
= asyncio
.Task
.current_task()._coro
152 coroutine_id
= 'coro-{} {}()'.format(hex(id(coro
))[2:], print_cor_name(coro
))
158 obj_type
= obj
.__class
__.__name
__ # type: str
160 '{} {} {} {} {}::{}.{}():{}\n{}'\
161 .format(self
._prefix
, dt
, thread_name
, coroutine_id
, filename
, obj_type
, func
, lineno
, str(msg
))
164 '{} {} {} {} {}::{}():{}\n{}'\
165 .format(self
._prefix
, dt
, thread_name
, coroutine_id
, filename
, func
, lineno
, str(msg
))