piker/tests/test_logging.py

113 lines
3.1 KiB
Python

'''
Package logger namespace regression tests.
'''
import logging
from types import SimpleNamespace
import pytest
import trio
from piker.log import (
get_console_log,
get_logger,
)
@pytest.mark.parametrize(
'factory',
[
get_logger,
get_console_log,
],
)
@pytest.mark.parametrize(
'name',
[
'piker.service._daemon',
'piker.paper',
],
)
def test_package_logger_name(
factory,
name: str,
):
'''
`str.lstrip('piker.')` treated the package prefix as a set of
removable characters. A submodule beginning with any of those
characters, such as `piker.paper`, was silently renamed to
`piker.aper`, while service code asserted a stale parent name.
Exercise both logger factories with service and prefix-sensitive
submodule names, proving they retain the exact requested package
namespace.
'''
log = factory(name=name)
assert log.name == name
def test_feed_startup_configures_transport_logger(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture,
) -> None:
'''
Daemon INFO did not enable websocket reconnection diagnostics.
Feed startup configured piker.data.feed, but ._util.log and
._web_bs.log emit on piker.data. Errors fell back to bare stderr
while connection-success INFO stayed hidden. Client verbosity
must also not demote that shared actor-wide transport logger.
Run production feed startup and logger configuration with an INFO
actor and ERROR client. Stop at feed-bus lookup before touching
any provider. Use real logging/console emission, not mocked logger
methods, to prove INFO from the websocket emitter is visible.
'''
from piker.data import feed, _web_bs
saved = {}
for name in ('piker.data', 'piker.data.feed', 'tractor'):
logger = logging.getLogger(name)
saved[logger] = (logger.level, list(logger.handlers))
boundary = RuntimeError('stop before provider lookup')
def stop_at_bus(brokername: str):
raise boundary
monkeypatch.setattr(
feed.tractor,
'current_actor',
lambda **kwargs: SimpleNamespace(
name='brokerd.binance', loglevel='info',
),
)
monkeypatch.setattr(feed, 'get_feed_bus', stop_at_bus)
async def main() -> None:
with pytest.raises(RuntimeError) as caught:
await feed.open_feed_bus(
ctx=None, brokername='binance', symbols=[],
loglevel='error',
)
assert caught.value is boundary
try:
logging.getLogger('piker.data').setLevel(logging.WARNING)
trio.run(main)
assert _web_bs.log.isEnabledFor(logging.INFO)
_web_bs.log.info('websocket INFO visibility probe')
assert 'websocket INFO visibility probe' in (
capsys.readouterr().err
)
finally:
for logger, (level, handlers) in saved.items():
for handler in list(logger.handlers):
if handler not in handlers:
logger.removeHandler(handler)
handler.close()
logger.setLevel(level)