userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
servicelogs.py
1
import
asyncio
2
import
io
3
import
logging
4
import
pathlib
5
6
import
pytest
7
8
from
testsuite._internal
import
logreader
9
10
logger = logging.getLogger(__name__)
11
12
13
class
LogFileReporter
(
logreader.LogFile
):
14
def
__init__(self, path: pathlib.Path, *, formatter_factory):
15
super().__init__(path)
16
self.
_formatter_factory
= formatter_factory
17
18
def
make_report(self):
19
formatter = self.
_formatter_factory
()
20
log = io.StringIO()
21
for
line
in
self.
readlines
(limit_position=
True
):
22
line = line.rstrip(b
'\r\n'
)
23
line = formatter(line)
24
if
line
is
not
None
:
25
log.write(line)
26
log.write(
'\n'
)
27
return
log.getvalue()
28
29
30
class
ServiceLogsPlugin
:
31
_live_logs =
None
32
33
def
__init__(self, *, config):
34
self.
_config
= config
35
self.
_logs
= {}
36
self.
_flushers
= []
37
38
def
pytest_sessionstart(self, session):
39
if
_live_logs_enabled(self.
_config
):
40
self.
_live_logs
=
logreader.LiveLogHandler
()
41
else
:
42
self.
_live_logs
=
None
43
44
def
pytest_sessionfinish(self, session):
45
if
self.
_live_logs
:
46
self.
_live_logs
.join()
47
48
def
pytest_runtest_setup(self, item):
49
self.
_flushers
.clear()
50
self.
update_position
()
51
52
@pytest.hookimpl(wrapper=True, tryfirst=True)
53
def
pytest_runtest_makereport(self, item, call):
54
report =
yield
55
if
report.failed
and
not
self.
_live_logs
:
56
self.
_userver_report_attach
(report)
57
return
report
58
59
def
register_flusher(self, func):
60
loop = asyncio.get_running_loop()
61
self.
_flushers
.append((loop, func))
62
63
def
register_logfile(
64
self, path: pathlib.Path, title: str, formatter_factory
65
):
66
logger.info(
'Watching service log file: %s'
, path)
67
self.
_logs
[path, title] =
LogFileReporter
(
68
path, formatter_factory=formatter_factory
69
)
70
if
self.
_live_logs
:
71
self.
_live_logs
.register_logfile(
72
path, formatter=formatter_factory()
73
)
74
75
def
update_position(self):
76
for
logfile
in
self.
_logs
.values():
77
logfile.update_position()
78
79
def
_userver_report_attach(self, report):
80
self.
_run_flushers
()
81
for
(_, title), logfile
in
self.
_logs
.items():
82
self.
_userver_report_attach_log
(logfile, report, title)
83
84
def
_userver_report_attach_log(self, logfile, report, title):
85
value = logfile.make_report()
86
if
value:
87
report.sections.append((f
'Captured {title} {report.when}'
, value))
88
89
def
_run_flushers(self):
90
try
:
91
for
loop, flusher
in
self.
_flushers
:
92
if
not
loop.is_closed():
93
loop.run_until_complete(flusher())
94
except
Exception:
95
logger.exception(
'failed to run logging flushers:'
)
96
97
98
def
pytest_addoption(parser) -> None:
99
parser.addoption(
100
'--service-livelogs-disable'
,
101
action=
'store_true'
,
102
help=
'Disable service live logs (enabled with -s)'
,
103
)
104
105
106
def
pytest_configure(config):
107
config.pluginmanager.register(
108
ServiceLogsPlugin
(config=config),
109
'service_logs_plugin'
,
110
)
111
112
113
@pytest.fixture(scope='session')
114
def
servicelogs_register_logfile(_servicelogs_logging_plugin):
115
def
register(path: pathlib.Path, *, title: str, formatter_factory):
116
_servicelogs_logging_plugin.register_logfile(
117
path, title, formatter_factory
118
)
119
120
return
register
121
122
123
@pytest.fixture
124
def
servicelogs_register_flusher(
125
_servicelogs_logging_plugin: ServiceLogsPlugin,
126
):
127
def
register(func):
128
_servicelogs_logging_plugin.register_flusher(func)
129
130
return
register
131
132
133
@pytest.fixture(scope='session')
134
def
service_logs_update_position(
135
_servicelogs_logging_plugin: ServiceLogsPlugin,
136
):
137
def
update_position():
138
return
_servicelogs_logging_plugin.update_position()
139
140
return
update_position
141
142
143
@pytest.fixture(scope='session')
144
def
_servicelogs_logging_plugin(pytestconfig) -> ServiceLogsPlugin:
145
return
pytestconfig.pluginmanager.get_plugin(
'service_logs_plugin'
)
146
147
148
def
_live_logs_enabled(config):
149
if
not
config.option.service_livelogs_disable:
150
return
bool(
151
config.option.capture ==
'no'
152
and
config.option.showcapture
in
(
'all'
,
'log'
),
153
)
154
return
False
en
testsuite
plugins
servicelogs.py
Generated on
for userver by
Doxygen
1.17.0