Home > Software design >  How to dynamically pass variable to class __init__ method in a custom python logging class
How to dynamically pass variable to class __init__ method in a custom python logging class

Time:04-02

It is difficult to put what I need in a sentence but the code below pretty much explains it:

I have my logging class in a separate file (log_file) as below, and a logger object defined there:

from io import StringIO
import logging

class NetddLog():
   def __init__(self, name, format="%(asctime)s %(levelname)s %(message)s", level=logging.INFO):
      self.name = name
      self.level = level
      self.format = format

      #Logger configuration.
      self.formatter = logging.Formatter(self.format)
      self.logger = logging.getLogger(name)#name
      self.logger.setLevel(self.level)
      #Logging to memory
      self.log_capture_string = StringIO()
      self.ch_logger = logging.StreamHandler(self.log_capture_string)
      self.ch_logger.setFormatter(self.formatter)
      self.logger.addHandler(self.ch_logger)

   def debug(self, msg, extra=None):
      self.logger.debug(msg, extra=extra)

ip_logger = NetddLog("IP_LOG")

In another file (ip_file), I have my ping function as below:

from log_file import ip_logger
from icmplib import ping

def ping_ip(ip_num, ip):
    try: 
        ip_logger.info(f"{ip_num}: Pinging {ip} started")

        host = ping(ip, count=4, interval=1, timeout=2, payload_size=64, privileged=True)
        if host.is_alive:
            ip_logger.info(f"{ip_num}: Pinging {ip} succeded")
        else:
            raise Exception 

    except Exception as err:
        ip_logger.error(f"{ip_num}: Pinging {ip} failed {err}")

The ip_num is the number of the IP address(ip) in a IP addr list, in another file (main_file), from which I call ping_ip(ip_num, ip)

The log messages prints just fine, but I'm putting ip_num inside the actual log message, each time. What I want to do is, having included in the format of the logger when the logger is created in the class, and probably just call the function with ping_ip(ip)

So the format in the init class method will look something like this: format=f"%(asctime)s %(levelname)s {ip_num}: %(message)s" , this way I don't have to include ip_num inside every log message I create. Is there a way to achieve this within the current class configuration or an alternative way? (I want to keep things separated as much as possible and not put everything in the main_file)

Update: Based on a previous answer I just redefined the logging methods inside the class to add an extra parameter in the format. For instance info function would change like below, and %(ip_num)s can be added to the format.

   def info(self, ip_num, msg):
      self.d = {'ip_num': f"{ip_num}"}
      self.logger.info(msg, extra=self.d)

CodePudding user response:

Yes, you can achieve what you want, actually is well documented under: https://docs.python.org/3/howto/logging.html

There is a parameter where you can provide a dictionary with additional values to your log format.

Below you can find the snippet which does the job:

import logging


def config_log(FORMAT = '%(asctime)s %(levelname)s IP:%(ip_num)s %(message)s'):
    logging.basicConfig(filename='example.log', encoding='utf-8',format=FORMAT, level=logging.INFO)
    
def log_something(ipnum, mymessage):
    d = {'ip_num': f"{ipnum}"}
    logging.info(mymessage, extra=d)

if __name__ == "__main__":       
    config_log() 
    log_something("127.0.0.1",'Here is your message log')
  • Related