From 50ffc1095bb0394922abf1a4c7f12afa62d67a13 Mon Sep 17 00:00:00 2001 From: goodboy Date: Wed, 11 Feb 2026 16:38:59 -0500 Subject: [PATCH] Use `__name__` for loggers across most sub-mods Change most sub-modules to use `get_logger(name=__name__)` for per-leaf-module `log` instances vs previous subpkg-level/shared refs. Primary changes, - import `get_[console_]logger()` from top-level `piker.log` across leaf mods. - change any `._util.log` logger-instances as well (though this approach should no longer be used since it masks the endpoint module's emissions. Also, - add a defaulted `loglevel: str` param to all `open_trade_dialog()` endpoints, anticipating it being passed in by `.clearing`-engine. - call `get_console_log(level=loglevel, name=__name__)` in each trade dialog ep to enable per-`brokerd`-backend console writing. - drop `get_logger` from `.brokers.__all__` exports - fix type annotations: `str|None` vs `str | None` - add TODOs for, * comments in `._util` about multi-subsys logging * `.accounting.__init__` about console log setup (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- piker/accounting/__init__.py | 14 +++++++++++--- piker/accounting/_pos.py | 9 +++++++-- piker/brokers/__init__.py | 10 +++++++--- piker/brokers/_daemon.py | 18 +++++++++++++----- piker/brokers/_util.py | 26 +++++++++++++++++--------- piker/brokers/binance/broker.py | 14 ++++++++++++-- piker/brokers/binance/feed.py | 4 ++-- piker/brokers/cli.py | 22 +++++++++++++--------- piker/brokers/core.py | 6 +++++- piker/brokers/data.py | 12 +++++++++--- piker/brokers/ib/_util.py | 2 +- piker/brokers/ib/broker.py | 15 +++++++++++++-- piker/brokers/kraken/broker.py | 13 ++++++++++++- piker/brokers/questrade.py | 19 ++++++++++++++----- piker/brokers/robinhood.py | 11 +++++++++-- piker/clearing/_paper_engine.py | 16 ++++++++++------ piker/data/feed.py | 11 +++++++---- piker/service/_daemon.py | 13 ++++++++++--- piker/tsp/_anal.py | 4 ++-- piker/tsp/_history.py | 6 ++++-- 20 files changed, 178 insertions(+), 67 deletions(-) diff --git a/piker/accounting/__init__.py b/piker/accounting/__init__.py index 72b883df..f95c5b65 100644 --- a/piker/accounting/__init__.py +++ b/piker/accounting/__init__.py @@ -19,9 +19,11 @@ for tendiez. ''' -from ..log import get_logger - -from .calc import ( +from piker.log import ( + get_console_log, + get_logger, +) +from piker.calc import ( iter_by_dt, ) from ._ledger import ( @@ -51,6 +53,12 @@ from ._allocate import ( log = get_logger(__name__) +# ?TODO, enable console on import +# [ ] necessary? or `open_brokerd_dialog()` doing it is sufficient? +# +# get_console_log( +# name=__name__, +# ) __all__ = [ 'Account', diff --git a/piker/accounting/_pos.py b/piker/accounting/_pos.py index 64c56ba1..bf26c23b 100644 --- a/piker/accounting/_pos.py +++ b/piker/accounting/_pos.py @@ -60,12 +60,17 @@ from ..clearing._messages import ( BrokerdPosition, ) from piker.types import Struct -from piker.log import get_logger +from piker.log import ( + get_console_log, + get_logger, +) if TYPE_CHECKING: from piker.data._symcache import SymbologyCache -log = get_logger(__name__) +log = get_logger( + name=__name__, +) class Position(Struct): diff --git a/piker/brokers/__init__.py b/piker/brokers/__init__.py index 94e4cbe1..b64231a5 100644 --- a/piker/brokers/__init__.py +++ b/piker/brokers/__init__.py @@ -25,15 +25,16 @@ from types import ModuleType from tractor.trionics import maybe_open_context +from piker.log import ( + get_logger, +) from ._util import ( - log, BrokerError, SymbolNotFound, NoData, DataUnavailable, DataThrottle, resproc, - get_logger, ) __all__: list[str] = [ @@ -43,7 +44,6 @@ __all__: list[str] = [ 'DataUnavailable', 'DataThrottle', 'resproc', - 'get_logger', ] __brokers__: list[str] = [ @@ -65,6 +65,10 @@ __brokers__: list[str] = [ # bitso ] +log = get_logger( + name=__name__, +) + def get_brokermod(brokername: str) -> ModuleType: ''' diff --git a/piker/brokers/_daemon.py b/piker/brokers/_daemon.py index eb5c2021..0362b4bd 100644 --- a/piker/brokers/_daemon.py +++ b/piker/brokers/_daemon.py @@ -33,12 +33,18 @@ import exceptiongroup as eg import tractor import trio +from piker.log import ( + get_logger, + get_console_log, +) from . import _util from . import get_brokermod if TYPE_CHECKING: from ..data import _FeedsBus +log = get_logger(name=__name__) + # `brokerd` enabled modules # TODO: move this def to the `.data` subpkg.. # NOTE: keeping this list as small as possible is part of our caps-sec @@ -74,16 +80,13 @@ async def _setup_persistent_brokerd( # any further (level) configuration on their own B) actor: tractor.Actor = tractor.current_actor() tll: str = actor.loglevel - log = _util.get_console_log( + log = get_console_log( level=loglevel or tll, name=f'{_util.subsys}.{brokername}', with_tractor_log=bool(tll), ) assert log.name == _util.subsys - # set global for this actor to this new process-wide instance B) - _util.log = log - # further, set the log level on any broker broker specific # logger instance. @@ -253,7 +256,7 @@ async def spawn_brokerd( async def maybe_spawn_brokerd( brokername: str, - loglevel: str | None = None, + loglevel: str|None = None, **pikerd_kwargs, @@ -268,6 +271,11 @@ async def maybe_spawn_brokerd( ''' from piker.service import maybe_spawn_daemon + # if ( + # loglevel != 'info' + # ): + # await tractor.pause() + async with maybe_spawn_daemon( f'brokerd.{brokername}', diff --git a/piker/brokers/_util.py b/piker/brokers/_util.py index 3588a87a..47b10ad0 100644 --- a/piker/brokers/_util.py +++ b/piker/brokers/_util.py @@ -19,15 +19,13 @@ Handy cross-broker utils. """ from __future__ import annotations -from functools import partial +# from functools import partial import json import httpx import logging -from ..log import ( - get_logger, - get_console_log, +from piker.log import ( colorize_json, ) subsys: str = 'piker.brokers' @@ -35,12 +33,22 @@ subsys: str = 'piker.brokers' # NOTE: level should be reset by any actor that is spawned # as well as given a (more) explicit name/key such # as `piker.brokers.binance` matching the subpkg. -log = get_logger(subsys) +# log = get_logger(subsys) -get_console_log = partial( - get_console_log, - name=subsys, -) +# ?TODO?? we could use this approach, but we need to be able +# to pass multiple `name=` values so for example we can include the +# emissions in `.accounting._pos` and others! +# [ ] maybe we could do the `log = get_logger()` above, +# then cycle through the list of subsys mods we depend on +# and then get all their loggers and pass them to +# `get_console_log(logger=)`?? +# [ ] OR just write THIS `get_console_log()` as a hook which does +# that based on who calls it?.. i dunno +# +# get_console_log = partial( +# get_console_log, +# name=subsys, +# ) class BrokerError(Exception): diff --git a/piker/brokers/binance/broker.py b/piker/brokers/binance/broker.py index 919e8152..13eebea0 100644 --- a/piker/brokers/binance/broker.py +++ b/piker/brokers/binance/broker.py @@ -37,8 +37,9 @@ import trio from piker.accounting import ( Asset, ) -from piker.brokers._util import ( +from piker.log import ( get_logger, + get_console_log, ) from piker.data._web_bs import ( open_autorecon_ws, @@ -69,7 +70,9 @@ from .venues import ( ) from .api import Client -log = get_logger('piker.brokers.binance') +log = get_logger( + name=__name__, +) # Fee schedule template, mostly for paper engine fees modelling. @@ -245,9 +248,16 @@ async def handle_order_requests( @tractor.context async def open_trade_dialog( ctx: tractor.Context, + loglevel: str = 'warning', ) -> AsyncIterator[dict[str, Any]]: + # enable piker.clearing console log for *this* `brokerd` subactor + get_console_log( + level=loglevel, + name=__name__, + ) + # TODO: how do we set this from the EMS such that # positions are loaded from the correct venue on the user # stream at startup? (that is in an attempt to support both diff --git a/piker/brokers/binance/feed.py b/piker/brokers/binance/feed.py index ff5f6ec0..ba02634e 100644 --- a/piker/brokers/binance/feed.py +++ b/piker/brokers/binance/feed.py @@ -64,9 +64,9 @@ from piker.data._web_bs import ( open_autorecon_ws, NoBsWs, ) +from piker.log import get_logger from piker.brokers._util import ( DataUnavailable, - get_logger, ) from .api import ( @@ -78,7 +78,7 @@ from .venues import ( get_api_eps, ) -log = get_logger('piker.brokers.binance') +log = get_logger(name=__name__) class L1(Struct): diff --git a/piker/brokers/cli.py b/piker/brokers/cli.py index 626b4ff8..96f4e2de 100644 --- a/piker/brokers/cli.py +++ b/piker/brokers/cli.py @@ -27,14 +27,12 @@ import click import trio import tractor -from ..cli import cli -from .. import watchlists as wl -from ..log import ( +from piker.cli import cli +from piker import watchlists as wl +from piker.log import ( colorize_json, -) -from ._util import ( - log, get_console_log, + get_logger, ) from ..service import ( maybe_spawn_brokerd, @@ -45,12 +43,15 @@ from ..brokers import ( get_brokermod, data, ) -DEFAULT_BROKER = 'binance' +log = get_logger( + name=__name__, +) + +DEFAULT_BROKER = 'binance' _config_dir = click.get_app_dir('piker') _watchlists_data_path = os.path.join(_config_dir, 'watchlists.json') - OK = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' @@ -345,7 +346,10 @@ def contracts(ctx, loglevel, broker, symbol, ids): ''' brokermod = get_brokermod(broker) - get_console_log(loglevel) + get_console_log( + level=loglevel, + name=__name__, + ) contracts = trio.run(partial(core.contracts, brokermod, symbol)) if not ids: diff --git a/piker/brokers/core.py b/piker/brokers/core.py index c1aa88ac..60623f85 100644 --- a/piker/brokers/core.py +++ b/piker/brokers/core.py @@ -28,12 +28,14 @@ from typing import ( import trio -from ._util import log +from piker.log import get_logger from . import get_brokermod from ..service import maybe_spawn_brokerd from . import open_cached_client from ..accounting import MktPair +log = get_logger(name=__name__) + async def api(brokername: str, methname: str, **kwargs) -> dict: ''' @@ -147,6 +149,7 @@ async def search_w_brokerd( async def symbol_search( brokermods: list[ModuleType], pattern: str, + loglevel: str = 'warning', **kwargs, ) -> dict[str, dict[str, dict[str, Any]]]: @@ -176,6 +179,7 @@ async def symbol_search( '_infect_asyncio', False, ), + loglevel=loglevel ) as portal: results.append(( diff --git a/piker/brokers/data.py b/piker/brokers/data.py index 6d178b51..12010ede 100644 --- a/piker/brokers/data.py +++ b/piker/brokers/data.py @@ -41,12 +41,15 @@ import tractor from tractor.experimental import msgpub from async_generator import asynccontextmanager -from ._util import ( - log, +from piker.log import( + get_logger, get_console_log, ) from . import get_brokermod +log = get_logger( + name='piker.brokers.binance', +) async def wait_for_network( net_func: Callable, @@ -243,7 +246,10 @@ async def start_quote_stream( ''' # XXX: why do we need this again? - get_console_log(tractor.current_actor().loglevel) + get_console_log( + level=tractor.current_actor().loglevel, + name=__name__, + ) # pull global vars from local actor symbols = list(symbols) diff --git a/piker/brokers/ib/_util.py b/piker/brokers/ib/_util.py index 690f6c22..10b3dde1 100644 --- a/piker/brokers/ib/_util.py +++ b/piker/brokers/ib/_util.py @@ -34,7 +34,7 @@ import subprocess import tractor -from piker.brokers._util import get_logger +from piker.log import get_logger if TYPE_CHECKING: from .api import Client diff --git a/piker/brokers/ib/broker.py b/piker/brokers/ib/broker.py index f6f7d123..e8514958 100644 --- a/piker/brokers/ib/broker.py +++ b/piker/brokers/ib/broker.py @@ -50,7 +50,10 @@ from ib_insync.objects import ( ) from piker import config -from piker.log import get_logger +from piker.log import ( + get_logger, + get_console_log, +) from piker.types import Struct from piker.accounting import ( Position, @@ -95,7 +98,9 @@ from .ledger import ( update_ledger_from_api_trades, ) -log = get_logger(name=__name__) +log = get_logger( + name=__name__, +) def pack_position( @@ -538,9 +543,15 @@ class IbAcnt(Struct): @tractor.context async def open_trade_dialog( ctx: tractor.Context, + loglevel: str = 'warning', ) -> AsyncIterator[dict[str, Any]]: + get_console_log( + level=loglevel, + name=__name__, + ) + # task local msg dialog tracking flows = OrderDialogs() accounts_def = config.load_accounts(['ib']) diff --git a/piker/brokers/kraken/broker.py b/piker/brokers/kraken/broker.py index 0aaf5730..c2bdada4 100644 --- a/piker/brokers/kraken/broker.py +++ b/piker/brokers/kraken/broker.py @@ -62,9 +62,12 @@ from piker.clearing._messages import ( from piker.brokers import ( open_cached_client, ) +from piker.log import ( + get_console_log, + get_logger, +) from piker.data import open_symcache from .api import ( - log, Client, BrokerError, ) @@ -78,6 +81,8 @@ from .ledger import ( verify_balances, ) +log = get_logger(name=__name__) + MsgUnion = Union[ BrokerdCancel, BrokerdError, @@ -431,9 +436,15 @@ def trades2pps( @tractor.context async def open_trade_dialog( ctx: tractor.Context, + loglevel: str = 'warning', ) -> AsyncIterator[dict[str, Any]]: + get_console_log( + level=loglevel, + name=__name__, + ) + async with ( # TODO: maybe bind these together and deliver # a tuple from `.open_cached_client()`? diff --git a/piker/brokers/questrade.py b/piker/brokers/questrade.py index 97ef5a3a..69c888cb 100644 --- a/piker/brokers/questrade.py +++ b/piker/brokers/questrade.py @@ -50,13 +50,19 @@ from . import open_cached_client from piker._cacheables import async_lifo_cache from .. import config from ._util import resproc, BrokerError, SymbolNotFound -from ..log import ( +from piker.log import ( colorize_json, -) -from ._util import ( - log, get_console_log, ) +from piker.log import ( + get_logger, +) + + +log = get_logger( + name=__name__, +) + _use_practice_account = False _refresh_token_ep = 'https://{}login.questrade.com/oauth2/' @@ -1205,7 +1211,10 @@ async def stream_quotes( # feed_type: str = 'stock', ) -> AsyncGenerator[str, Dict[str, Any]]: # XXX: required to propagate ``tractor`` loglevel to piker logging - get_console_log(loglevel) + get_console_log( + level=loglevel, + name=__name__, + ) async with open_cached_client('questrade') as client: if feed_type == 'stock': diff --git a/piker/brokers/robinhood.py b/piker/brokers/robinhood.py index 8fc5739f..e3ac75ea 100644 --- a/piker/brokers/robinhood.py +++ b/piker/brokers/robinhood.py @@ -30,9 +30,16 @@ import asks from ._util import ( resproc, BrokerError, - log, ) -from ..calc import percent_change +from piker.calc import percent_change +from piker.log import ( + get_logger, +) + +log = get_logger( + name=__name__, +) + _service_ep = 'https://api.robinhood.com' diff --git a/piker/clearing/_paper_engine.py b/piker/clearing/_paper_engine.py index e9daf1a5..9b49508e 100644 --- a/piker/clearing/_paper_engine.py +++ b/piker/clearing/_paper_engine.py @@ -59,9 +59,9 @@ from piker.data import ( open_symcache, ) from piker.types import Struct -from ._util import ( - log, # sub-sys logger +from piker.log import ( get_console_log, + get_logger, ) from ._messages import ( BrokerdCancel, @@ -73,6 +73,8 @@ from ._messages import ( BrokerdError, ) +log = get_logger(name=__name__) + class PaperBoi(Struct): ''' @@ -550,16 +552,18 @@ _sells: defaultdict[ @tractor.context async def open_trade_dialog( - ctx: tractor.Context, broker: str, - fqme: str | None = None, # if empty, we only boot broker mode + fqme: str|None = None, # if empty, we only boot broker mode loglevel: str = 'warning', ) -> None: - # enable piker.clearing console log for *this* subactor - get_console_log(loglevel) + # enable piker.clearing console log for *this* `brokerd` subactor + get_console_log( + level=loglevel, + name=__name__, + ) symcache: SymbologyCache async with open_symcache(get_brokermod(broker)) as symcache: diff --git a/piker/data/feed.py b/piker/data/feed.py index 48d284ba..89b360ba 100644 --- a/piker/data/feed.py +++ b/piker/data/feed.py @@ -278,7 +278,7 @@ async def allocate_persistent_feed( # ``stream_quotes()``, a required broker backend endpoint. init_msgs: ( list[FeedInit] # new - | dict[str, dict[str, str]] # legacy / deprecated + |dict[str, dict[str, str]] # legacy / deprecated ) # TODO: probably make a struct msg type for this as well @@ -481,13 +481,16 @@ async def open_feed_bus( ''' if loglevel is None: - loglevel = tractor.current_actor().loglevel + loglevel: str = tractor.current_actor().loglevel # XXX: required to propagate ``tractor`` loglevel to piker # logging get_console_log( - loglevel - or tractor.current_actor().loglevel + level=(loglevel + or + tractor.current_actor().loglevel + ), + name=__name__, ) # local state sanity checks diff --git a/piker/service/_daemon.py b/piker/service/_daemon.py index 89d7f28d..ef110fc3 100644 --- a/piker/service/_daemon.py +++ b/piker/service/_daemon.py @@ -30,8 +30,9 @@ from contextlib import ( import tractor from trio.lowlevel import current_task -from ._util import ( - log, # sub-sys logger +from piker.log import ( + get_console_log, + get_logger, ) from ._mngr import ( Services, @@ -39,6 +40,8 @@ from ._mngr import ( from ._actor_runtime import maybe_open_pikerd from ._registry import find_service +log = get_logger(name=__name__) + @acm async def maybe_spawn_daemon( @@ -48,7 +51,7 @@ async def maybe_spawn_daemon( spawn_args: dict[str, Any], - loglevel: str | None = None, + loglevel: str|None = None, singleton: bool = False, **pikerd_kwargs, @@ -66,6 +69,10 @@ async def maybe_spawn_daemon( clients. ''' + get_console_log( + level=loglevel, + name=__name__, + ) # serialize access to this section to avoid # 2 or more tasks racing to create a daemon lock = Services.locks[service_name] diff --git a/piker/tsp/_anal.py b/piker/tsp/_anal.py index 30cc6b59..46bee231 100644 --- a/piker/tsp/_anal.py +++ b/piker/tsp/_anal.py @@ -54,10 +54,10 @@ from ..log import ( # for "time series processing" subsys: str = 'piker.tsp' -log = get_logger(subsys) +log = get_logger(name=__name__) get_console_log = partial( get_console_log, - name=subsys, + name=subsys, # activate for subsys-pkg "downward" ) # NOTE: union type-defs to handle generic `numpy` and `polars` types diff --git a/piker/tsp/_history.py b/piker/tsp/_history.py index a47e8e9d..86f60610 100644 --- a/piker/tsp/_history.py +++ b/piker/tsp/_history.py @@ -96,7 +96,9 @@ if TYPE_CHECKING: # from .feed import _FeedsBus -log = get_logger(__name__) +log = get_logger( + name=__name__, +) # `ShmArray` buffer sizing configuration: @@ -550,7 +552,7 @@ async def start_backfill( ) # ?TODO, check against venue closure hours # if/when provided by backend? - await tractor.pause() + # await tractor.pause() expected_dur: Interval = ( last_start_dt.subtract(