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 `<subsys>._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
Gud Boi 2026-02-11 16:38:59 -05:00
parent 89dba3c76a
commit 7756c3a603
20 changed files with 178 additions and 67 deletions

View File

@ -19,9 +19,11 @@
for tendiez. for tendiez.
''' '''
from ..log import get_logger from piker.log import (
get_console_log,
from .calc import ( get_logger,
)
from piker.calc import (
iter_by_dt, iter_by_dt,
) )
from ._ledger import ( from ._ledger import (
@ -51,6 +53,12 @@ from ._allocate import (
log = get_logger(__name__) log = get_logger(__name__)
# ?TODO, enable console on import
# [ ] necessary? or `open_brokerd_dialog()` doing it is sufficient?
#
# get_console_log(
# name=__name__,
# )
__all__ = [ __all__ = [
'Account', 'Account',

View File

@ -60,12 +60,17 @@ from ..clearing._messages import (
BrokerdPosition, BrokerdPosition,
) )
from piker.types import Struct from piker.types import Struct
from piker.log import get_logger from piker.log import (
get_console_log,
get_logger,
)
if TYPE_CHECKING: if TYPE_CHECKING:
from piker.data._symcache import SymbologyCache from piker.data._symcache import SymbologyCache
log = get_logger(__name__) log = get_logger(
name=__name__,
)
class Position(Struct): class Position(Struct):

View File

@ -25,15 +25,16 @@ from types import ModuleType
from tractor.trionics import maybe_open_context from tractor.trionics import maybe_open_context
from piker.log import (
get_logger,
)
from ._util import ( from ._util import (
log,
BrokerError, BrokerError,
SymbolNotFound, SymbolNotFound,
NoData, NoData,
DataUnavailable, DataUnavailable,
DataThrottle, DataThrottle,
resproc, resproc,
get_logger,
) )
__all__: list[str] = [ __all__: list[str] = [
@ -43,7 +44,6 @@ __all__: list[str] = [
'DataUnavailable', 'DataUnavailable',
'DataThrottle', 'DataThrottle',
'resproc', 'resproc',
'get_logger',
] ]
__brokers__: list[str] = [ __brokers__: list[str] = [
@ -65,6 +65,10 @@ __brokers__: list[str] = [
# bitso # bitso
] ]
log = get_logger(
name=__name__,
)
def get_brokermod(brokername: str) -> ModuleType: def get_brokermod(brokername: str) -> ModuleType:
''' '''

View File

@ -33,12 +33,18 @@ import exceptiongroup as eg
import tractor import tractor
import trio import trio
from piker.log import (
get_logger,
get_console_log,
)
from . import _util from . import _util
from . import get_brokermod from . import get_brokermod
if TYPE_CHECKING: if TYPE_CHECKING:
from ..data import _FeedsBus from ..data import _FeedsBus
log = get_logger(name=__name__)
# `brokerd` enabled modules # `brokerd` enabled modules
# TODO: move this def to the `.data` subpkg.. # TODO: move this def to the `.data` subpkg..
# NOTE: keeping this list as small as possible is part of our caps-sec # 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) # any further (level) configuration on their own B)
actor: tractor.Actor = tractor.current_actor() actor: tractor.Actor = tractor.current_actor()
tll: str = actor.loglevel tll: str = actor.loglevel
log = _util.get_console_log( log = get_console_log(
level=loglevel or tll, level=loglevel or tll,
name=f'{_util.subsys}.{brokername}', name=f'{_util.subsys}.{brokername}',
with_tractor_log=bool(tll), with_tractor_log=bool(tll),
) )
assert log.name == _util.subsys 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 # further, set the log level on any broker broker specific
# logger instance. # logger instance.
@ -253,7 +256,7 @@ async def spawn_brokerd(
async def maybe_spawn_brokerd( async def maybe_spawn_brokerd(
brokername: str, brokername: str,
loglevel: str | None = None, loglevel: str|None = None,
**pikerd_kwargs, **pikerd_kwargs,
@ -268,6 +271,11 @@ async def maybe_spawn_brokerd(
''' '''
from piker.service import maybe_spawn_daemon from piker.service import maybe_spawn_daemon
# if (
# loglevel != 'info'
# ):
# await tractor.pause()
async with maybe_spawn_daemon( async with maybe_spawn_daemon(
f'brokerd.{brokername}', f'brokerd.{brokername}',

View File

@ -19,15 +19,13 @@ Handy cross-broker utils.
""" """
from __future__ import annotations from __future__ import annotations
from functools import partial # from functools import partial
import json import json
import httpx import httpx
import logging import logging
from ..log import ( from piker.log import (
get_logger,
get_console_log,
colorize_json, colorize_json,
) )
subsys: str = 'piker.brokers' subsys: str = 'piker.brokers'
@ -35,12 +33,22 @@ subsys: str = 'piker.brokers'
# NOTE: level should be reset by any actor that is spawned # NOTE: level should be reset by any actor that is spawned
# as well as given a (more) explicit name/key such # as well as given a (more) explicit name/key such
# as `piker.brokers.binance` matching the subpkg. # as `piker.brokers.binance` matching the subpkg.
log = get_logger(subsys) # log = get_logger(subsys)
get_console_log = partial( # ?TODO?? we could use this approach, but we need to be able
get_console_log, # to pass multiple `name=` values so for example we can include the
name=subsys, # 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): class BrokerError(Exception):

View File

@ -37,8 +37,9 @@ import trio
from piker.accounting import ( from piker.accounting import (
Asset, Asset,
) )
from piker.brokers._util import ( from piker.log import (
get_logger, get_logger,
get_console_log,
) )
from piker.data._web_bs import ( from piker.data._web_bs import (
open_autorecon_ws, open_autorecon_ws,
@ -69,7 +70,9 @@ from .venues import (
) )
from .api import Client from .api import Client
log = get_logger('piker.brokers.binance') log = get_logger(
name=__name__,
)
# Fee schedule template, mostly for paper engine fees modelling. # Fee schedule template, mostly for paper engine fees modelling.
@ -245,9 +248,16 @@ async def handle_order_requests(
@tractor.context @tractor.context
async def open_trade_dialog( async def open_trade_dialog(
ctx: tractor.Context, ctx: tractor.Context,
loglevel: str = 'warning',
) -> AsyncIterator[dict[str, Any]]: ) -> 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 # TODO: how do we set this from the EMS such that
# positions are loaded from the correct venue on the user # positions are loaded from the correct venue on the user
# stream at startup? (that is in an attempt to support both # stream at startup? (that is in an attempt to support both

View File

@ -64,9 +64,9 @@ from piker.data._web_bs import (
open_autorecon_ws, open_autorecon_ws,
NoBsWs, NoBsWs,
) )
from piker.log import get_logger
from piker.brokers._util import ( from piker.brokers._util import (
DataUnavailable, DataUnavailable,
get_logger,
) )
from .api import ( from .api import (
@ -78,7 +78,7 @@ from .venues import (
get_api_eps, get_api_eps,
) )
log = get_logger('piker.brokers.binance') log = get_logger(name=__name__)
class L1(Struct): class L1(Struct):

View File

@ -27,14 +27,12 @@ import click
import trio import trio
import tractor import tractor
from ..cli import cli from piker.cli import cli
from .. import watchlists as wl from piker import watchlists as wl
from ..log import ( from piker.log import (
colorize_json, colorize_json,
)
from ._util import (
log,
get_console_log, get_console_log,
get_logger,
) )
from ..service import ( from ..service import (
maybe_spawn_brokerd, maybe_spawn_brokerd,
@ -45,12 +43,15 @@ from ..brokers import (
get_brokermod, get_brokermod,
data, data,
) )
DEFAULT_BROKER = 'binance'
log = get_logger(
name=__name__,
)
DEFAULT_BROKER = 'binance'
_config_dir = click.get_app_dir('piker') _config_dir = click.get_app_dir('piker')
_watchlists_data_path = os.path.join(_config_dir, 'watchlists.json') _watchlists_data_path = os.path.join(_config_dir, 'watchlists.json')
OK = '\033[92m' OK = '\033[92m'
WARNING = '\033[93m' WARNING = '\033[93m'
FAIL = '\033[91m' FAIL = '\033[91m'
@ -345,7 +346,10 @@ def contracts(ctx, loglevel, broker, symbol, ids):
''' '''
brokermod = get_brokermod(broker) brokermod = get_brokermod(broker)
get_console_log(loglevel) get_console_log(
level=loglevel,
name=__name__,
)
contracts = trio.run(partial(core.contracts, brokermod, symbol)) contracts = trio.run(partial(core.contracts, brokermod, symbol))
if not ids: if not ids:

View File

@ -28,12 +28,14 @@ from typing import (
import trio import trio
from ._util import log from piker.log import get_logger
from . import get_brokermod from . import get_brokermod
from ..service import maybe_spawn_brokerd from ..service import maybe_spawn_brokerd
from . import open_cached_client from . import open_cached_client
from ..accounting import MktPair from ..accounting import MktPair
log = get_logger(name=__name__)
async def api(brokername: str, methname: str, **kwargs) -> dict: async def api(brokername: str, methname: str, **kwargs) -> dict:
''' '''
@ -147,6 +149,7 @@ async def search_w_brokerd(
async def symbol_search( async def symbol_search(
brokermods: list[ModuleType], brokermods: list[ModuleType],
pattern: str, pattern: str,
loglevel: str = 'warning',
**kwargs, **kwargs,
) -> dict[str, dict[str, dict[str, Any]]]: ) -> dict[str, dict[str, dict[str, Any]]]:
@ -176,6 +179,7 @@ async def symbol_search(
'_infect_asyncio', '_infect_asyncio',
False, False,
), ),
loglevel=loglevel
) as portal: ) as portal:
results.append(( results.append((

View File

@ -41,12 +41,15 @@ import tractor
from tractor.experimental import msgpub from tractor.experimental import msgpub
from async_generator import asynccontextmanager from async_generator import asynccontextmanager
from ._util import ( from piker.log import(
log, get_logger,
get_console_log, get_console_log,
) )
from . import get_brokermod from . import get_brokermod
log = get_logger(
name='piker.brokers.binance',
)
async def wait_for_network( async def wait_for_network(
net_func: Callable, net_func: Callable,
@ -243,7 +246,10 @@ async def start_quote_stream(
''' '''
# XXX: why do we need this again? # 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 # pull global vars from local actor
symbols = list(symbols) symbols = list(symbols)

View File

@ -34,7 +34,7 @@ import subprocess
import tractor import tractor
from piker.brokers._util import get_logger from piker.log import get_logger
if TYPE_CHECKING: if TYPE_CHECKING:
from .api import Client from .api import Client

View File

@ -50,7 +50,10 @@ from ib_insync.objects import (
) )
from piker import config 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.types import Struct
from piker.accounting import ( from piker.accounting import (
Position, Position,
@ -95,7 +98,9 @@ from .ledger import (
update_ledger_from_api_trades, update_ledger_from_api_trades,
) )
log = get_logger(name=__name__) log = get_logger(
name=__name__,
)
def pack_position( def pack_position(
@ -538,9 +543,15 @@ class IbAcnt(Struct):
@tractor.context @tractor.context
async def open_trade_dialog( async def open_trade_dialog(
ctx: tractor.Context, ctx: tractor.Context,
loglevel: str = 'warning',
) -> AsyncIterator[dict[str, Any]]: ) -> AsyncIterator[dict[str, Any]]:
get_console_log(
level=loglevel,
name=__name__,
)
# task local msg dialog tracking # task local msg dialog tracking
flows = OrderDialogs() flows = OrderDialogs()
accounts_def = config.load_accounts(['ib']) accounts_def = config.load_accounts(['ib'])

View File

@ -62,9 +62,12 @@ from piker.clearing._messages import (
from piker.brokers import ( from piker.brokers import (
open_cached_client, open_cached_client,
) )
from piker.log import (
get_console_log,
get_logger,
)
from piker.data import open_symcache from piker.data import open_symcache
from .api import ( from .api import (
log,
Client, Client,
BrokerError, BrokerError,
) )
@ -78,6 +81,8 @@ from .ledger import (
verify_balances, verify_balances,
) )
log = get_logger(name=__name__)
MsgUnion = Union[ MsgUnion = Union[
BrokerdCancel, BrokerdCancel,
BrokerdError, BrokerdError,
@ -431,9 +436,15 @@ def trades2pps(
@tractor.context @tractor.context
async def open_trade_dialog( async def open_trade_dialog(
ctx: tractor.Context, ctx: tractor.Context,
loglevel: str = 'warning',
) -> AsyncIterator[dict[str, Any]]: ) -> AsyncIterator[dict[str, Any]]:
get_console_log(
level=loglevel,
name=__name__,
)
async with ( async with (
# TODO: maybe bind these together and deliver # TODO: maybe bind these together and deliver
# a tuple from `.open_cached_client()`? # a tuple from `.open_cached_client()`?

View File

@ -50,13 +50,19 @@ from . import open_cached_client
from piker._cacheables import async_lifo_cache from piker._cacheables import async_lifo_cache
from .. import config from .. import config
from ._util import resproc, BrokerError, SymbolNotFound from ._util import resproc, BrokerError, SymbolNotFound
from ..log import ( from piker.log import (
colorize_json, colorize_json,
)
from ._util import (
log,
get_console_log, get_console_log,
) )
from piker.log import (
get_logger,
)
log = get_logger(
name=__name__,
)
_use_practice_account = False _use_practice_account = False
_refresh_token_ep = 'https://{}login.questrade.com/oauth2/' _refresh_token_ep = 'https://{}login.questrade.com/oauth2/'
@ -1205,7 +1211,10 @@ async def stream_quotes(
# feed_type: str = 'stock', # feed_type: str = 'stock',
) -> AsyncGenerator[str, Dict[str, Any]]: ) -> AsyncGenerator[str, Dict[str, Any]]:
# XXX: required to propagate ``tractor`` loglevel to piker logging # 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: async with open_cached_client('questrade') as client:
if feed_type == 'stock': if feed_type == 'stock':

View File

@ -30,9 +30,16 @@ import asks
from ._util import ( from ._util import (
resproc, resproc,
BrokerError, 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' _service_ep = 'https://api.robinhood.com'

View File

@ -59,9 +59,9 @@ from piker.data import (
open_symcache, open_symcache,
) )
from piker.types import Struct from piker.types import Struct
from ._util import ( from piker.log import (
log, # sub-sys logger
get_console_log, get_console_log,
get_logger,
) )
from ._messages import ( from ._messages import (
BrokerdCancel, BrokerdCancel,
@ -73,6 +73,8 @@ from ._messages import (
BrokerdError, BrokerdError,
) )
log = get_logger(name=__name__)
class PaperBoi(Struct): class PaperBoi(Struct):
''' '''
@ -550,16 +552,18 @@ _sells: defaultdict[
@tractor.context @tractor.context
async def open_trade_dialog( async def open_trade_dialog(
ctx: tractor.Context, ctx: tractor.Context,
broker: str, 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', loglevel: str = 'warning',
) -> None: ) -> None:
# enable piker.clearing console log for *this* subactor # enable piker.clearing console log for *this* `brokerd` subactor
get_console_log(loglevel) get_console_log(
level=loglevel,
name=__name__,
)
symcache: SymbologyCache symcache: SymbologyCache
async with open_symcache(get_brokermod(broker)) as symcache: async with open_symcache(get_brokermod(broker)) as symcache:

View File

@ -278,7 +278,7 @@ async def allocate_persistent_feed(
# ``stream_quotes()``, a required broker backend endpoint. # ``stream_quotes()``, a required broker backend endpoint.
init_msgs: ( init_msgs: (
list[FeedInit] # new 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 # TODO: probably make a struct msg type for this as well
@ -481,13 +481,16 @@ async def open_feed_bus(
''' '''
if loglevel is None: if loglevel is None:
loglevel = tractor.current_actor().loglevel loglevel: str = tractor.current_actor().loglevel
# XXX: required to propagate ``tractor`` loglevel to piker # XXX: required to propagate ``tractor`` loglevel to piker
# logging # logging
get_console_log( get_console_log(
loglevel level=(loglevel
or tractor.current_actor().loglevel or
tractor.current_actor().loglevel
),
name=__name__,
) )
# local state sanity checks # local state sanity checks

View File

@ -30,8 +30,9 @@ from contextlib import (
import tractor import tractor
from trio.lowlevel import current_task from trio.lowlevel import current_task
from ._util import ( from piker.log import (
log, # sub-sys logger get_console_log,
get_logger,
) )
from ._mngr import ( from ._mngr import (
Services, Services,
@ -39,6 +40,8 @@ from ._mngr import (
from ._actor_runtime import maybe_open_pikerd from ._actor_runtime import maybe_open_pikerd
from ._registry import find_service from ._registry import find_service
log = get_logger(name=__name__)
@acm @acm
async def maybe_spawn_daemon( async def maybe_spawn_daemon(
@ -48,7 +51,7 @@ async def maybe_spawn_daemon(
spawn_args: dict[str, Any], spawn_args: dict[str, Any],
loglevel: str | None = None, loglevel: str|None = None,
singleton: bool = False, singleton: bool = False,
**pikerd_kwargs, **pikerd_kwargs,
@ -66,6 +69,10 @@ async def maybe_spawn_daemon(
clients. clients.
''' '''
get_console_log(
level=loglevel,
name=__name__,
)
# serialize access to this section to avoid # serialize access to this section to avoid
# 2 or more tasks racing to create a daemon # 2 or more tasks racing to create a daemon
lock = Services.locks[service_name] lock = Services.locks[service_name]

View File

@ -54,10 +54,10 @@ from ..log import (
# for "time series processing" # for "time series processing"
subsys: str = 'piker.tsp' subsys: str = 'piker.tsp'
log = get_logger(subsys) log = get_logger(name=__name__)
get_console_log = partial( get_console_log = partial(
get_console_log, get_console_log,
name=subsys, name=subsys, # activate for subsys-pkg "downward"
) )
# NOTE: union type-defs to handle generic `numpy` and `polars` types # NOTE: union type-defs to handle generic `numpy` and `polars` types

View File

@ -96,7 +96,9 @@ if TYPE_CHECKING:
# from .feed import _FeedsBus # from .feed import _FeedsBus
log = get_logger(__name__) log = get_logger(
name=__name__,
)
# `ShmArray` buffer sizing configuration: # `ShmArray` buffer sizing configuration:
@ -550,7 +552,7 @@ async def start_backfill(
) )
# ?TODO, check against venue closure hours # ?TODO, check against venue closure hours
# if/when provided by backend? # if/when provided by backend?
await tractor.pause() # await tractor.pause()
expected_dur: Interval = ( expected_dur: Interval = (
last_start_dt.subtract( last_start_dt.subtract(