-
Notifications
You must be signed in to change notification settings - Fork 699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filtering chatty libraries #148
Comments
Hi. Could you do this on the standard There is a way to to this with a Loguru |
i suppose I could, though i was originally hoping i'd be able to have my goal of a preconfigured importable logger, and the cake of a declarative what are the odds you'd wouldn't be opposed to (the equivalent of) My ideal interface would be (modulo names) logger.configure(
intercept_standard_logging=True,
log_level_overrides={
'foo': 'INFO',
'foo.bar': 'DEBUG',
}
)
logger.info('off to the races!') |
Well, I considered making I decided that standard Sorry, I'm quite conservative on this. How did you plan to use your "preconfigured importable logger"? Using a |
sorry, "preconfigured importable logger" a good think you have! I meant does |
Oh, yes, ok I see. :)
Yeah, as discussed this parameter would be entirely related to standard I know this is less convenient that using log_level_overrides = {
'foo': 'INFO',
'foo.bar': 'DEBUG',
}
for module, level in log_level_overrides.items():
logging.getLogger(module).setLevel(level) |
I can see how the log interceptor would be related to standard logging, but the log level portion seems like it'd be a more general feature. basically an extension to In fact, given the way you set if one sets try:
enabled_status = Logger._enabled[name]
except KeyError:
... # existing logic
if not enabled_status or enabled_status == level_id:
return Would that not give me the same behavior I'm looking for? |
Hi @DanCardin. I thought a little about your suggestion. This is not a bad idea per se, but there are several things that bother me. I know it's not what you want to hear, but I prefer not to add such option, sorry. :/ You see, the Basically, I like the current simplicity of The principal problem with this proposition is that it moves the level configuration away of the sinks setup. For example, There is also the possibility yo extend the |
I would personally consider The main issue I have with it not being part of the api, is that I can choose my own code's logging calls' levels, and i can choose the logging level for everything. But I can't choose the logging levels, or the location and relative frequency of logging calls external to my code. Ironically, using your suggestion, i'll see better ergonomics using a library written using std logging vs loguru.
this paragraph is the one i find the most convincing. It's definitely true that this would introduce the ability to change logging level outside of sinks. But, given the ease with which i (think i) could make this change, your activation feature is already effectively doing the same thing, just at a much less granular level. The activation feature as-is seems like a bit of a bandaid for the otherwise lack of ability to control dependent code's logging calls. I can imagine why straight up disabling/enabling whole top-level packages could be useful by itself, but you already provide the ability to do that by letting me specify
fwiw, I saw the primary advantages as being (in priority order):
EDIT: |
Hi @DanCardin. First of all, I would like to apologize for the time it took me to answer you. I was not sure what to do with this issue, and I spent my time on other problems. You took the time to write a constructive answer and explain in detail your point of view, thanks for that! It was rude of me not to answer you more quickly... So, I think we agree on these two points:
Which leads me to the next suggestion... Why not just extend the level_per_module = {
"foo": "DEBUG",
"foo.bar": "INFO"
}
logger.add(sys.stderr, filter=level_per_module) I'm much more willing to implement this solution. Actually, I think this approach would be more powerful: suppose you want to configure some chatty library so it only print warnings to the terminal, but logs everything to a file. At that point, using What are you thought on this solution? Do you think that would suits your use case? |
No problem! For the time being I've fully disabled those logs and that's alright. I dont expect a Rome to be built in a day for free. (While I still think your E.g. could i do?
If so, I'd maybe recommend having falsey values evaluate to filtering it out unconditionally. At that point you could effectively deprecate One other thing, I guess in order to maintain something like the existing If both of the above things, the total ruleset of filter would be something like:
|
He he. Although I think you got a point last time when you said that
Hum... I was planning to keep it very simple: a dictionary of sub-modules associated with their minimum level. I prefer not to add functions as valid values. If the handling of sub-modules is so complex that a function is needed, it should manage the whole filter-logic and be directly passed as the argument.
I hadn't thought to that, but it makes sense. We need a way to filter out, so we need
Hum, yeah, using
Indeed, actually,
About the mapping, I would like to point out that it will check for the presence of a "parent" in the dict, not necessarily the exact same module name. I see this as an extension of current
|
The main reason I suggested allowing callables as options to the dict, is that if someone using a filter for a preexisting reason wanted to make use of this feature, they'd need to drop their existing filter and switch to this new dict, or else write a function to perform the combination of the two. I guess my thought was that it composes somewhat nicely back into itself. Instead of any combination of two simple filters devolving into a more complex filter function which requires you to introspect attributes off a record that you wouldn't have needed to before, you could basically conjoin any two orthogonal filters on a given sink without having to switch the method you use. In any case, I'm not using filters at all right now, so I'd be happy with just the straight up dict with values accepting logging levels/
this feels weird to me. i'd probably expect one to always need to add a sink; and that a library would simply be expected to not add its own sinks. but that's besides the point.
yea i was mentally incorporating that but it's an important distinction. |
I understand your point, but I think that if someone is already using a
I think we need a way for libraries to explicitly disable logs, the standard |
I mean, I think you simply wouldn't register a logging handler in the normal But my trying to convince you of anything about that feature/adding an implicit sink is all besides the point (of this feature at least). I think even the simpler filter |
Yeah, don't worry, I was just genuinely interested to know why you thought it was better to display all logs by default. I guess it entirely depends on the user. I think it might surprise some people to see logs which are not their own, this is why there is the possibility to Anyway, I will implement the "dict-filtering" in the next few days and publish a new release shortly after that. 👍 |
Implemented! Thanks again for your patience and your feedback. It will be available in the |
(for people who come across this) from loguru import logger
def log_sink(message):
# Handle any loguru calls from the libraries we're using
print("loguru log message:", message)
if __name__ == "__main__":
logger.remove()
logger_format = "{message}"
logger.add(sink=log_sink, format=logger_format, level="INFO") |
In general, debug output is what I'm looking for, and I'd like to get it from all dependent libraries. Using the snippet for integrating with the logging library, all is mostly well.
However, if left unchecked,
boto3
andrequests
are good examples of libraries which are too chatty and log a lot of records that are generally not useful. But it's not obvious to me how to add loguru-side sinks in such a way that I can specify,x
,y
, andz
packages ought to be filtered to INFO logs, and otherwise unspecified packages ought to continue logging at DEBUG.Would the canonical method be adding a
filter
param to everyadd
call and doing a separate level comparison at the point where i'm comparing against the logger?The text was updated successfully, but these errors were encountered: