Implementation method of filtering log output in python using Filter

  • 2021-07-22 09:57:41
  • OfStack

Here's the thing, I wrote an tornado service, In the process, I used logging to record some contents. Since 1 didn't carefully observe tornado's own log management at first, Therefore, I use debug to record ordinary logs and error to record problematic logs. However, when the service runs, it is discovered that the access log level of tornado is info, that is, 20, and debug is 10. Therefore, if I define the log level as debug, it will definitely be output to the log file by default.

But I don't care about accessing logs right now, and since my service may have access all the time, it has a big impact when I search for log information.

What shall I do?

There are several ways

Modify the level when initializing the log

One is to modify the log level defined when I initialize, and set it to be higher than info, so that the log of info will not be recorded again

But this method requires me to modify the previous debug method to a higher level than info, that is, greater than 20. There are a lot of modifications, and I am used to using debug to record, so the cost of modifying is a bit high.

Modify tornado itself

You can modify web. py under tornado in site-packages


def log_request(self, handler):
  """Writes a completed HTTP request to the logs.

  By default writes to the python root logger. To change
  this behavior either subclass Application and override this method,
  or pass a function in the application settings dictionary as
  ``log_function``.
  """
  if "log_function" in self.settings:
    self.settings["log_function"](handler)
    return
  if handler.get_status() < 400:
    log_method = access_log.info
  elif handler.get_status() < 500:
    log_method = access_log.warning
  else:
    log_method = access_log.error
  request_time = 1000.0 * handler.request.request_time()
  log_method("%d %s %.2fms", handler.get_status(),
        handler._request_summary(), request_time)

Among them log_method = access_log.info You can modify it, access_log Defined in log. py,


access_log = logging.getLogger( " tornado.access " )

Here you can define the level of access_log, and then modify the implementation of log_request. It is complicated to think about it, and it is a stupid method to directly modify the library files in site-packes, and many inexplicable problems will occur in future migration.

Using logging. Filter to set filtering rules

In fact, logging has already had a corresponding solution. There is one Filterer class in logging library, and Handler and Logger classes in logging library are inherited from Filter class

There are three methods in the Filter class, addFilter(filter) , removeFilter(filter) 和 filter(record) Method, mainly using addFilter and filter methods.

The addFilter method requires an filter object, where I define a new class and override the filter method,

Filter out logs named tornado. access and log level 20.


class NoParsingFilter(logging.Filter):
  def filter(self, record):
    if record.name == 'tornado.access' and record.levelno == 20:
      return False
    return True

So I add this filter after initializing the logging object


logobj = logging.getLogger('server')
logobj.addFilter(NoParsingFilter())

In this way, after adding a filter log, it will be recorded in its own way at will. record is also a class LogRecord of logging, and the commonly used attributes are as follows name, level, pathname, lineno,msg, args, exc_info

name is the name passed in when the logger object is initialized

level is the level

Which file is pathname outputting this line of logs

lineno is the line number

msg is the log itself

ps: Let's look at the use of filter filter in python


# No. 1 1 The parameters are 1 Return bool Value of 1 General function or lambda Function, first 2 The parameters are 1 Iterable objects 
# Final return 1 Iterable objects, which can be passed through list Obtain 
def is_positive(item):
  return item>0
values = [1,-2,3,-4]
print(filter(is_poditive,values))
a = list(filter(is_positive,values))
print(a)
print(values)
#output
<filter object at 0x000002398A1AB4A8>
[1, 3]
[1, -2, 3, -4]
b = list(filter(lambda item:item>0,values))
print(b)
 #output 
[1,3]

Summarize


Related articles: