-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[Enhancement] Regularize logging messages #3176
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
Conversation
This commit adds invokeai.backend.util.logging, which provides support
for formatted console and logfile messages that follow the status
reporting conventions of earlier InvokeAI versions.
Examples:
### A critical error (logging.CRITICAL)
*** A non-fatal error (logging.ERROR)
** A warning (logging.WARNING)
>> Informational message (logging.INFO)
| Debugging message (logging.DEBUG)
This commit adds invokeai.backend.util.logging, which provides support
for formatted console and logfile messages that follow the status
reporting conventions of earlier InvokeAI versions.
Examples:
### A critical error (logging.CRITICAL)
*** A non-fatal error (logging.ERROR)
** A warning (logging.WARNING)
>> Informational message (logging.INFO)
| Debugging message (logging.DEBUG)
This style logs everything through a single logging object and is
identical to using Python's `logging` module. The commonly-used
module-level logging functions are implemented as simple pass-thrus
to logging:
import invokeai.backend.util.logging as ialog
ialog.debug('this is a debugging message')
ialog.info('this is a informational message')
ialog.log(level=logging.CRITICAL, 'get out of dodge')
ialog.disable(level=logging.INFO)
ialog.basicConfig(filename='/var/log/invokeai.log')
Internally, the invokeai logging module creates a new default logger
named "invokeai" so that its logging does not interfere with other
module's use of the vanilla logging module. So `logging.error("foo")`
will go through the regular logging path and not add the additional
message decorations.
For more control, the logging module's object-oriented logging style
is also supported. The API is identical to the vanilla logging
usage. In fact, the only thing that has changed is that the
getLogger() method adds a custom formatter to the log messages.
import logging
from invokeai.backend.util.logging import InvokeAILogger
logger = InvokeAILogger.getLogger(__name__)
fh = logging.FileHandler('/var/invokeai.log')
logger.addHandler(fh)
logger.critical('this will be logged to both the console and the log file')
|
Is there a way for the user to override the formats, or even just use standard Python formats? I can imagine there are tools out there that work really well with standard Python log formatting, and changing that might create extra work. In particular, I've seen log aggregators do well when the logging level is part of the message (e.g. they can automatically pick out |
|
I'd maybe just import as |
Absolutely. You can change the format using the same methods as you would Really all the ialogger does is to change the default formatter. You can also still import the standard logging library and use that. They Here's what appears on the console: And here's what appears in the |
You didn't get the joke? It's "dialog" without the "d", meaning a one-way conversation. Oh well. New commit changes |
About the "user" changing the log format - I meant more the "end user" than the programmer. Can we set up configuration so the user can configure logging via command line flags / environment variables / config files? |
|
Yes, that's coming with the configuration system. There will be "logging", "loglevel" and "log-format" options. "logging" will provide options for console, syslog, file and http log destinations. BTW, if I use omegaconf for the configuration system, which I'm strongly considering doing, the command-line option format will change by default to |
|
hrm... I don't know? I'm used to |
omegaconf doesn't seem to offer the option, but I could process I'm going to finish off replacing print() calls with log() calls and then do the system-wide configuration work, and will figure out a way to preserve argparse-style command-line arguments while supporting an omegaconf-style .yaml configuration file for user preferences. |
|
The configuration system is coming along OK, and I'll be adding options to log to files, syslog and arbitrary http endpoints at that time. |
- resolve conflicts - remove unused code identified by pyflakes
psychedelicious
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. I'm approving with two nice-to-haves:
-
There are a number of other useful subclasses of
Handler(and it is possible to create a custom handler). It'd be nice to be able to dynamically add and remove handlers. -
May also be nice to slot in a totally different logging module at some point.
|
|
@Kyle0654 @psychedelicious I've made the logging module into one of the customizable services provided by |
I'm very used to object-oriented approaches, and I know Python utilizes static approaches for a lot of things, so I'm not sure what the correct approach is here. I suspect it's to configure a logging module at startup and then just use that logging module everywhere else (as long as you can ensure it's been configured before use). |
ebr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - does what it says on the tin. I was able to:
- easily add standardized logging everywhere in the web API by accessing
invoker.services.logger - customize the log format by getting a new logger
- use a different logger by importing it
api_app.py
Regarding it being a service (addressing @psychedelicious' point) - we could add a wrapper under api/services so the logger class could be used as a fully fledged InvocationService. Right now it appears the logger is initialized differently. I believe that would be the correct pattern, but on the other hand, if we configure the logging module at startup, we could use it for FastAPI as well to uniformly format messages across the board. Anyway, this can all be improved later.
|
@lstein - Think this is ready to merge after it gets updated w/ main. I'm hesitant to join in the fun and do that, as I'm not sure if it would result in needing new approvals. |
That sounds good, but I'm really unfamiliar with FastAPI. Can you give me a hint on how to do this? |
I am pretty sure that last part might be as simple as setting |
Intro
This commit adds invokeai.backend.util.logging, which provides support for formatted console and logfile messages that follow the status reporting conventions of earlier InvokeAI versions:
Internally, the invokeai logging module creates a new default logger named "invokeai" so that its logging does not interfere with other module's use of the vanilla logging module. So
logging.error("foo")will go through the regular logging path and not add InvokeAI's informational message decorations, whileialog.error("foo")will add the decorations.Usage:
This is a thin wrapper around the standard Python logging module. It can be used in several ways:
Module-level logging style
This style logs everything through a single default logging object and is identical to using Python's
loggingmodule. The commonly-used module-level logging functions are implemented as simple pass-thrus to logging:Internally these functions all go through a custom logging object named "invokeai". You can access it to perform additional customization in either of these ways:
Object-oriented style
For more control, the logging module's object-oriented logging style is also supported. The API is identical to the vanilla logging usage. In fact, the only thing that has changed is that the getLogger() method adds a custom formatter to the log messages.
Within the nodes API
From within the nodes API, the logger module is stored in the
loggerslot of InvocationServices during dependency initialization. For example, in a router, the idiom is:Currently, to change the logger used by the API, one must change the logging module passed to
ApiDependencies.initialize()inapi_app.py. However, this will eventually be replaced with a method to select the preferred logging module using the configuration file (dependent on merging of PR #3221)