13

I'm using standard Python logging module with Flask framework. I want to write logs to file with the all records of users actions with custom parameter - %(username)s to logging.Formatter:

admin - 2013-10-11 15:11:47,033 action0
user1 - 2013-10-11 15:11:48,033 action1
user2 - 2013-10-11 15:11:49,033 action2
admin - 2013-10-11 15:11:50,033 action3

I'm using RotatingFileHandler:

def get_user_name():
    return session.get("username", "")

file_handler = RotatingFileHandler(fname, maxBytes=1 * 1024 * 1024, backupCount=5)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(logging.Formatter(
    '%(username)s - %(asctime)s %(levelname)-10s %(message)s  [in %(pathname)s:%(lineno)d]'
)) # how to insert get_user_name() instead %(username)s?

app.logger.addHandler(file_handler)

What is the right way to do such logger? Thanks.

3
  • Is 2013-10-11 15:11:47,033 [DEBUG] admin - action0 ok? Commented Oct 11, 2013 at 12:36
  • @xiaowl The problem is that I don't know how to insert admin into this log message. %(username)s can be in any place, if it's important. Commented Oct 11, 2013 at 12:52
  • 1
    This is discussed at docs.python.org/3/howto/… Commented Dec 15, 2018 at 22:31

2 Answers 2

22

u can do it with logging.LoggerAdapter

myLogger = logging.LoggerAdapter(logging.getLogger("my-logger"), {"username" : get_user_name()})

Here is the complete solution for your program. I use a dict to build my configuration. It is better, if you have more logger

    def get_user_name():
        return session.get("username", "")

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': True,
        'formatters': {
            'my_format': {
                'format': '%(username)s - %(asctime)s %(levelname)-10s %(message)s  [in %(pathname)s:%(lineno)d]'
            },
        },
        'handlers': {
            'my_handler': {
                'level': 'DEBUG',
                'class': 'logging.handlersRotatingFileHandler',
                'filename': fname,
                'maxBytes': 1 * 1024 * 1024,
                'backupCount': 5,
            },
        },
        'loggers': {
            'my_logger': {
                'handlers': ['my_handler'],
                'propagate': True,
                'level': 'DEBUG',
            },
        } }

logging.config.dictConfig(LOGGING) 
logging.LoggerAdapter(logging.getLogger('my_logger'),
                                           {"username" : get_user_name()})
Sign up to request clarification or add additional context in comments.

Comments

9

Isn't the easier way to just subclass a Formatter and add your custom attribute to the LogRecord just before formatting?

For instance I use this code:

# A custom formatter to add the timestamp from the simulated clock.
class _Formatter(logging.Formatter):
  def format(self, record):
    record.simulated_clock = clock.get_time()
    return super(_Formatter, self).format(record)

# Creates a logger object.
def _create_logger():
  logger = logging.getLogger("simulation")
  logger.setLevel(kLevel)
  ch = logging.StreamHandler()
  ch.setLevel(kLevel)
  formatter = _Formatter("%(simulated_clock)s - %(levelname)s - %(message)s")
  ch.setFormatter(formatter)
  logger.addHandler(ch)

  return logger

I don't consider myself a Python expert, but it works for me....

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.