Skip to content

Instantly share code, notes, and snippets.

@dirkakrid
Forked from ColinDuquesnoy/html_logger.py
Created September 4, 2017 23:54
Show Gist options
  • Save dirkakrid/9c2ffa304b7ab48faec6b17639a08ab0 to your computer and use it in GitHub Desktop.
Save dirkakrid/9c2ffa304b7ab48faec6b17639a08ab0 to your computer and use it in GitHub Desktop.

Revisions

  1. @ColinDuquesnoy ColinDuquesnoy revised this gist Jan 20, 2014. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion html_logger.py
    Original file line number Diff line number Diff line change
    @@ -114,9 +114,14 @@ def format(self, record):
    class_name = "info"

    t = time.time() - self._start_time

    # handle '<' and '>' (typically when logging %r)
    msg = record.msg
    msg = msg.replace("<", "&#60")
    msg = msg.replace(">", "&#62")

    return _MSG_FMT % {"class": class_name, "time": "%.4f" % t,
    "msg": record.msg}
    "msg": msg}


    class HTMLLogger(logging.Logger):
  2. @ColinDuquesnoy ColinDuquesnoy revised this gist Jan 7, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion html_logger.py
    Original file line number Diff line number Diff line change
    @@ -136,7 +136,7 @@ def __init__(self,
    self.addHandler(h)


    #: Gloval logger instance
    #: Global logger instance
    _logger = None


  3. @ColinDuquesnoy ColinDuquesnoy renamed this gist Jan 7, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. @ColinDuquesnoy ColinDuquesnoy created this gist Jan 7, 2014.
    198 changes: 198 additions & 0 deletions html_logger
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,198 @@
    """
    HTML logger inspired by the Horde3D logger.

    Usage:

    - call setup and specify the filename, title, version and level
    - call dbg, info, warn or err to log messages.
    """
    import logging
    import time

    #: HTML header (starts the document
    _START_OF_DOC_FMT = """<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>%(title)s</title>
    <style type="text/css">
    body, html {
    background: #000000;
    width: 1000px;
    font-family: Arial;
    font-size: 16px;
    color: #C0C0C0;
    }
    h1 {
    color : #FFFFFF;
    border-bottom : 1px dotted #888888;
    }
    pre {
    font-family : arial;
    margin : 0;
    }
    .box {
    border : 1px dotted #818286;
    padding : 5px;
    margin: 5px;
    width: 950px;
    background-color : #292929;
    }
    .err {
    color: #EE1100;
    font-weight: bold
    }
    .warn {
    color: #FFCC00;
    font-weight: bold
    }
    .info {
    color: #C0C0C0;
    }
    .debug {
    color: #CCA0A0;
    }
    </style>
    </head>

    <body>
    <h1>%(title)s</h1>
    <h3>%(version)s</h3>
    <div class="box">
    <table>
    """

    _END_OF_DOC_FMT = """</table>
    </div>
    </body>
    </html>
    """

    _MSG_FMT = """
    <tr>
    <td width="100">%(time)s</td>
    <td class="%(class)s"><pre>%(msg)s</pre></td>
    <tr>
    """


    class HTMLFileHandler(logging.FileHandler):
    """
    File handler specialised to write the start of doc as html and to close it
    properly.
    """
    def __init__(self, title, version, *args):
    super().__init__(*args)
    assert self.stream is not None
    # Write header
    self.stream.write(_START_OF_DOC_FMT % {"title": title,
    "version": version})

    def close(self):
    # finish document
    self.stream.write(_END_OF_DOC_FMT)
    super().close()


    class HTMLFormatter(logging.Formatter):
    """
    Formats each record in html
    """
    CSS_CLASSES = {'WARNING': 'warn',
    'INFO': 'info',
    'DEBUG': 'debug',
    'CRITICAL': 'err',
    'ERROR': 'err'}

    def __init__(self):
    super().__init__()
    self._start_time = time.time()

    def format(self, record):
    try:
    class_name = self.CSS_CLASSES[record.levelname]
    except KeyError:
    class_name = "info"

    t = time.time() - self._start_time

    return _MSG_FMT % {"class": class_name, "time": "%.4f" % t,
    "msg": record.msg}


    class HTMLLogger(logging.Logger):
    """
    Log records to html using a custom HTML formatter and a specialised
    file stream handler.
    """
    def __init__(self,
    name="html_logger",
    level=logging.DEBUG,
    filename="log.html", mode='w',
    title="HTML Logger", version="1.0.0"):
    super().__init__(name, level)
    f = HTMLFormatter()
    h = HTMLFileHandler(title, version, filename, mode)
    h.setFormatter(f)
    self.addHandler(h)


    #: Gloval logger instance
    _logger = None


    def setup(title, version, filename="log.html", mode='w', level=logging.DEBUG):
    """
    Setup the logger

    :param title: Title of the html document
    :param version: Framework/lib/app version
    :param filename: output filename. Default is "log.html"
    :param mode: File open mode. Default is 'w'
    :param level: handler output level. Default is DEBUG
    """
    global _logger
    if _logger is None:
    _logger = HTMLLogger(filename=filename, mode=mode, title=title,
    version=version, level=level)


    def dbg(msg):
    """
    Logs a debug message
    """
    global _logger
    _logger.debug(msg)


    def info(msg):
    """
    Logs an info message
    """
    global _logger
    _logger.info(msg)


    def warn(msg):
    """
    Logs a warning message
    """
    global _logger
    _logger.warning(msg)


    def err(msg):
    """
    Logs an error message
    """
    global _logger
    _logger.error(msg)


    # Example of usage
    if __name__ == "__main__":
    setup("Example", "1.0")
    dbg("A debug message")
    info("An information message")
    warn("A warning message")
    time.sleep(1)
    err("An error message")