Support structlog within libraries, redux
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 38/100
Research direction
Start with the linked reader implementation in src/reader/_logging.py and the issue’s requirements for switching library loggers between standard logging and native structlog. Review structlog’s logger factories and existing tests to assess what public support is feasible; done means agreeing on an API and implementing and testing the required logger reset and stacklevel behavior. The discussion has not reached a decision, so check with maintainers before starting.
Written by the indexing model from the issue text.
Description
Hi @hynek,
This is a follow-up to https://github.com/hynek/structlog/issues/179 – I have a recipe for library support, but it could be made less brittle with support from structlog.
To summarize the requirements:
- the library MUST NOT configure
loggingnorstructlog(that's for the user to do) - the library MUST be able to use
structloginternally - if the user configures
logging, they MUST getloggingoutput from the library (there's a sensibleevent k=v ...default formatter; the library MAY offer a way to configure that, but it seems YAGNI) - if the user opts in, they MUST get
structlogoutput from the library - it is acceptable for the user opt in to work only before the library is used, threads are started, structlog is configured, etc. (the library can document this accordingly)
The code is here; in short:
- the library keeps a registry of its loggers
- by default, it wraps a
logginglogger - during the opt-in, existing loggers are reset (details below)
- after the opt-in, loggers are created with
structlog.get_logger
Usage looks this:
# library.py
_registry = WrappedLoggerFactory(... wrap_logger() kwargs ...)
# library uses this exclusively to create its loggers
get_logger = _registry.get_logger
# users call this to opt in
enable_native_structlog = _registry.enable_native_structlog
# user code
import library, structlog
library.enable_native_structlog()
structlog.configure(...)
library.do_stuff(...)
Minimal support from structlog would require:
-
A (public) way to "reset" loggers created by
wrap_loggerandget_logger.My current code assumes both return the same type of object, which holds the entire state in its
__dict__, so I can do:logger.__dict__.update(structlog.get_logger(name).__dict__)This is currently true (BoundLoggerLazyProxy), but it's obviously brittle.
(More complicated alternatives that do not require structlog cooperation: wrap the returned object in another proxy; record the call site, and during opt in go in
sys.modulesand replace the loggers.) -
A (public) way to fix the stacklevel per
logginglogger.In
WLF.get_logger, I'm temporarily doinglogging.setLoggerClass(_FixedFindCallerLogger). This is still brittle, since stdlib loggers for my library could be created before the library callsWLF.get_logger(e.g. bylogging.config.dictConfig).I guess an alternative would be for
WLF.get_loggerto patch thefindCallerof the stdlib logger, instead of bothering withlogging.setLoggerClass. Update: yup, seems to work fine.(This is optional, a library should be able to implement this without making assumptions about structlog internals.)
structlog could also provide something higher level like WrappedLoggerFactory; in this case, the stuff above doesn't need to be public API anymore, just possible.
What do you think? (If the overall direction is acceptable, I can draft a PR.)
- Dominant language
- Python
- Stars
- 5k
- Forks
- 302
- Avg merge
- 17m
- Merged PRs (30d)
- 4
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from hynek/structlog
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Transform examples in docs into included source filesPossibly taken @alexchen-sys claimed this 97 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 25/100
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
waiting for feedback
Difficulty 3/5 1-2 days Newbie friendliness 48/100
-
`CallsiteParameterAdder` use `additional_ignores` for foreign eventsPossibly taken @hynek claimed this 146 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 25/100
Similar issues
-
infrastructure
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
khuisman/mcp-gee-sweet#1152 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
backroom bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
ditto-assistant/ditto-subnet#3069 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
open-webui/open-webui#32901 · 1 comment ·
Maintainers usually reply within 1 day
-
0.3.3 bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day