July 13, 2014

How to Reformat Logback Output

Spring defaults to using logback for logging. It spits the logs out on standard output, which cannot be persisted. So, we must first send the log output to a file. This is done by leveraging the FileAppender class, as follows:

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>/home/hdiwan/around.log</file>
    <encoder>
      <pattern>"%date" "%level" "[%thread]" "%logger" "%file : %line" "%msg"%n</pattern>
    </encoder>
  </appender>

Now, you'll be getting logs to the file indicated, make sure the LOG_FILE at the top of the script matches the configuration:

import argparse
import cgi
import csv
import cStringIO as StringIO
import json
import logging

from lxml import etree

if __name__ == '__main__':
    LOGFILE_PATH = '/home/hdiwan/around.log'

    logger = logging.basicConfig(level=logging.FATAL)

    web = cgi.FieldStorage()
    format_ = web.getfirst('format', default='csv')
    csv.register_dialect('arounddialect')
    logging.debug(csv.list_dialects())
    if format_ == 'csv':
        print('Content-Type: application/csv\n')
    elif format_ == 'xml':
        print('Content-Type: text/xml\n')
    elif format_ == 'json':
        print('Content-Type: application/json\n')

    with open(LOGFILE_PATH,'rb') as fin:
        reader = csv.reader(fin, dialect='arounddialect')
        out = StringIO.StringIO()
        if format_ == 'csv':
            writer = csv.writer(out)
            writer.writerows(list(reader))

        elif format_ == 'xml':
            document = etree.Element('log')
            for r in list(reader):
                logging.debug(len(r))
                node = etree.SubElement(document, 'entry')

                timestamp = etree.SubElement(node, 'timestamp')
                timestamp.text = etree.CDATA(r[0])

                level = etree.SubElement(node, 'level')
                level.text = etree.CDATA(r[1])

                thread = etree.SubElement(node, 'thread')
                try:
                    thread.text = etree.CDATA(r[2])
                except IndexError,e:
                    thread.text = etree.CDATA('')

                class_ = etree.SubElement(node, 'class')
                try:
                    class_.text = etree.CDATA(r[3])
                except IndexError, e:
                    class_.text = etree.CDATA('')

                msg = etree.SubElement(node, 'message')
                try:
                    msg.text = etree.CDATA(r[4])
                except IndexError, e:
                    msg.text = etree.CDATA('')

            out.write(etree.tostring(document, encoding='utf-8', xml_declaration=True, pretty_print=True))

        elif format_ == 'json':
            out.write(json.dumps(list(reader)))
        
        print out.getvalue()
The other novel part here is the use of lxml to generate the XML, which alleviates the need to use cgi.escape and friends to get the xml properly formatted and pretty prints it automatically.

No comments:

Post a Comment