I'm trying to add contextual information to the logging output of my python script. Essentially, I'm using the SocketServer class to handle incoming network connections, and when a client sends a message to the server I want to make a log entry to STDOUT and a file with the time, log level, ip of the client and the message received.
I've tried implementing this using filters (which I couldn't get working, but I'm open to suggestions) and a LoggerAdapter: http://pastebin.com/peT0rjA7
class ConnInfo:
def __getitem__(self, name):
if name == "ip":
result = tlocal.ip
if name == "cmd":
result = tlocal.msg
return result
def __iter__(self):
keys = ['ip', 'cmd']
keys.extend(self.__dict__.keys())
return keys.__iter__()
logging.basicConfig(level=logging.DEBUG,
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
datefmt="%d-%m %H:%M:%S",
filename="distpovadmin.log",
filemode="w")
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
nodeCommsConFormatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(ip)-4s %(cmd)-8s %(message)s')
console.setFormatter(formatter)
#nodeCommsConLogging = logging.LoggerAdapter(logging.getLogger('NodeCommsConnection').addHandler(console.setFormatter(nodeCommsConFormatter())), ConnInfo())
CommsConConsole = logging.StreamHandler()
CommsConConsole.setLevel(logging.INFO)
CommsConConsole.setFormatter(nodeCommsConFormatter)
nodeCommsConLogging = logging.LoggerAdapter(logging.getLogger('NodeCommsConnection'), ConnInfo())
logging.getLogger('NodeCommsConnection').removeHandler(console)
logging.getLogger('NodeCommsConnection').addHandler(CommsConConsole)
logging.getLogger('').addHandler(console)
When I make a call to nodeCommsConLogging like this:
nodeCommsConLogging.info("Message Received")
I get duplicate entries in the STDOUT log
NodeCommsConnection: INFO 192.168.1.8 REQ; Message Received
NodeCommsConnection: INFO Message Received
Thanks in advance for any help and suggestions!
EDIT: Added code example
Loggers are hierarchical. So you have a root logger (named ''
, i.e. blank). Every other logger is a child of the root logger - eventually.
In your case, you have this hierarchy:
root
+-- NodeCommsConnection
If you log something on the child, it will try to handle it and then pass the log message to the parent logger unless you set propagate
to False
.
Since you add an appender to NodeCommsConnection
, it will log its messages using this appender and then call root which will log using its appender -> two outputs on the console.
So either add your appender to the root logger (and remove the default console logger) or set propagate
to False
:
logging.getLogger('NodeCommsConnection').propagate = False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With