I'm trying to set up a particular logging scheme for an application I'm building. For it, I want to be able to rotate logs arbitrarily on a custom condition. As such, the built-in options of rotating based on time (using TimedRotatingFileHandler) or log size (using RotatingFileHandler) are not sufficient. Both TimedRotatingFileHandler and RotatingFileHandler do however have the method doRollover which I could use to implement what I want. The problem comes from that I'm using logging.config.dictConfig to set up my log configuration, like so:
config = {
"version": 1,
"formatters": {
"default_formatter": {
"format": logging.BASIC_FORMAT,
},
},
"handlers": {
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "NOTSET",
"formatter": "default_formatter",
"backupCount": 5,
"filename": "log.txt",
"encoding": "utf8",
},
},
"loggers": {
"": {
"level": "NOTSET",
"handlers": ["file"],
},
},
}
logging.config.dictConfig(config)
This way, logging.config.dictConfig is responsible for instantiating RotatingFileHandler, and so I never get the chance to retain a reference to the class instance (i.e., the object). As such, it is not clear how I could go about calling methods upon the object.
How could I go about calling a method (in my case, doRollover) on an object instantiated as a handler by logging.config.dictConfig? Alternatively, if that is not possible, how can I manually provide a handler object that I have instantiated by calling the constructor directly given this configuration?
This can be done by assessing the
handlersproperty of the logger the handler is installed onto. In the code snippet above, the root logger is assigned the handler, and so we can get it like so:This works because in the question's example, the handler is named "file", and in here we essentially iterate through
root_logger.handlersuntil we find one where thenameproperty is equal to "file". The handler returned by this iteration is then the object that was instantiated bylogging.config.dictConfig.If using
nextisn't to your liking, the equivalent with a for-loop would be this: