Syslog-ng send raw json

Posted on Saturday, March 25, 2017


I recently had to get up to speed on setting up and using syslog-ng. which I wrote up on how to install it and get it logging a simple python app.  See http://www.whiteboardcoder.com/2017/03/syslog-ng-install-and-configure.html [1] I also did a write up on how to get it to listen on a port http://www.whiteboardcoder.com/2017/03/syslog-ng-listen-on-port.html [2]


In this post I am going to go over overcoming a few issues in getting raw json log outputs to a file.




The first problem (extra info)


First my set up in my /etc/syslog-ng/syslog-ng.conf  here is my set up to listen and create a log for my app at /var/log/myapp.log


source s_myapp {
      system();
};

destination d_myapp { file("/var/log/myapp.log"); };
filter f_myapp { facility(local0) and not level(debug); };
log { source (s_myapp); filter(f_myapp); destination(d_myapp); };


These are the relevant parts of my syslog-ng.conf file for this.

Now If I use the logger tool to send a simple json message…


  > logger -p local0.info '{"num":2, "notes":"My message"}'




And as I tail the log


  > tail -f /var/log/myapp.log




I do get out my json, but I also get out some extra information that includes a timestamp, hostname, and username.  (my hostname happens to be syslog)

But I just want the raw json!  How do I get this done?


Edit syslog-ng.conf


  > sudo vi /etc/syslog-ng/syslog-ng.conf




Update this piece with an inline template.


destination d_myapp { file("/var/log/myapp.log" template("${MSG}\n"));  };


Now reload  the syslog-ng services


  > sudo systemctl reload syslog-ng


Send another message


  > logger -p local0.info '{"num":2, "notes":"My message"}'



Tailing the log again


  > tail -f /var/log/myapp.log




Wahoo that worked.



The second problem … Python


The way python sends the log I get a little issue.

With this code….


#!/usr/bin/python3
import sys
import syslog
import logging
import logging.handlers

#Set up Logger
logger = logging.getLogger("10x13")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log',facility=16)
log_format = logging.Formatter('{"time": "%(asctime)s", "note":"%(message)s"}')
handler.setFormatter(log_format)
logger.addHandler(handler)

logger.info("Info Log Message")
logger.debug("Debug Log Message")
logger.error("Error log Message")


If I run this bit of code…


  > ./log_test.py





I am getting the first part of my json lopped off. 

Turns out the way python is sending the message if we choose to use a template it will split the raw json into two variable MSGHDR and MSG.  One simple tweak to account for that is to edit the template.




Edit syslog-ng.conf


  > sudo vi /etc/syslog-ng/syslog-ng.conf


And create the most simple network source just network()



destination d_myapp {
    file("/var/log/myapp.log" template("${MSGHDR}${MSG}\n"));
};




Now reload  the syslog-ng services


  > sudo systemctl reload syslog-ng




Now run the program


  > ./log_test.py




There we go!

Hmmm… I should probably add level of log to the output.



Here is my updated code.



#!/usr/bin/python3
import sys
import syslog
import logging
import logging.handlers

#Set up Logger
logger = logging.getLogger("10x13")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log',facility=16)
log_format = logging.Formatter('{"level": "%(levelname)s", "time": "%(asctime)s", "note":"%(message)s"}')
handler.setFormatter(log_format)
logger.addHandler(handler)

logger.info("Info Log Message")
logger.debug("Debug Log Message")
logger.error("Error log Message")




Much better J 



References


[1]        syslog-ng install and configure.
[2]        syslon-ng listen on a port
[3]        syslog-ng templates

No comments:

Post a Comment