0

I'm using the logging library and I want to call a function whenever any event is logged. Something like this:

import logging

#logging config here

async def on_log(message, level): #call this whenever something is logged
    print(level, ":", message)

logging.debug("Hello world")

Edit: on_log is a coroutine

Edit2: I tried implementing one of your suggestions but I'm not 100% sure about how to add it to my current logging configuration.

from logging import *
import datetime
import sys

class MyLogger(Handler):
    def emit(*args):
        for item in args:
            print(item)

time = datetime.datetime.today()
logtime = f"{time.year}-{time.month}-{time.day}__{time.hour}h-{time.minute}m-{time.second}s"

file_handler = FileHandler(filename=f'./logs/{logtime}.log')  # File output
stdout_handler = StreamHandler(sys.stdout)  # Console output

basicConfig(
    format=f'[%(asctime)s][%(levelname)s] %(message)s',
    datefmt='%H:%M:%S',
    level=DEBUG,
    handlers=[file_handler, stdout_handler, MyLogger]
)

I get this error: AttributeError: type object 'MyLogger' has no attribute 'formatter'

  • Does this answer your question? [How to write custom python logging handler?](https://stackoverflow.com/questions/3118059/how-to-write-custom-python-logging-handler) – Joe Jun 27 '20 at 08:41
  • This similar question - https://stackoverflow.com/questions/46354908/python-logger-with-a-callback-function - doesn't currently have an answer but looks like it has a potentially useful comment. – alani Jun 27 '20 at 08:41
  • Add a logging handler to the logging configuration. – Klaus D. Jun 27 '20 at 08:41
  • I've taken a look at the other questions, but I still don't really get how to add a custom log handler. –  Jun 27 '20 at 08:58
  • Where did you get stuck? – Klaus D. Jun 27 '20 at 09:12
  • you have to use `MyLogger` the same way you use `FileHandler` and `StreamHandler` - first you have to create instance `my_handler = MyLogger()` and later use this instance `handlers=[file_handler, stdout_handler, my_handler]` – furas Jun 27 '20 at 15:57

2 Answers2

5

The comments recommend using a custom handler but I would advise against it since there is a way to do this that is also proposed in the official documentation by using filters. In the specific case here it would work like this:

import logging

def on_log(record):
    print(record.levelname, ":", record.getMessage())
    return True

logging.root.addFilter(on_log)

logging.warning('some log')

blues
  • 4,547
  • 3
  • 23
  • 39
0

It is minimal working code

import logging

# --- classes ---

class MyLogger():

    #level = logging.NOTSET
    level = logging.DEBUG

    def handle(*args):
        print('--- args ---')
        for item in args:
            print(item)
        print('---')

# --- main ---

logger = logging.getLogger('test')
logger.setLevel(logging.DEBUG) 
#logger.setLevel(logging.INFO) 

my_logger = MyLogger()
#my_logger.level = logging.DEBUG

logger.addHandler(my_logger)

# --- test ---

logger.debug("DEBUG: Hello world")
logger.info("INFO: Hello world")

It can't be function but class with method handle and in variable level because every handler has own level. This way some handlers can be executed always, other only for debug message.


EDIT:

The same using class Handler which already has variable level and you have to only rewrite method handle. But is better to rewrite method emit which is executed by handle after filtering.

You can set level when you create instance.

import logging

# --- classes ---

class MyLogger(logging.Handler):
    
    #def handle(*args):
    def emit(*args):
        print('--- args ---')
        for item in args:
            print(item)
        print('---')
        
# --- main ---

logger = logging.getLogger('test')
logger.setLevel(logging.DEBUG) 
#logger.setLevel(logging.INFO) 

my_logger = MyLogger(logging.DEBUG)

logger.addHandler(my_logger)

# --- test ---

logger.debug("DEBUG: Hello world")
logger.info("INFO: Hello world")
furas
  • 134,197
  • 12
  • 106
  • 148
  • I'm not really sure how to add add this to my current logging configuration (I edited the post) –  Jun 27 '20 at 15:17