logger.info('Telling listener to stop ... ') stop_event .set() lp.join() logger.info('All done. ') if __name__ =='__main__ ': main() 

(continued from previous page) 

## 18 Inserting a BOM into messages sent to a SysLogHandler 

RFC 5424 requires that a Unicode message be sent to a syslog daemon as a set of bytes which have the following structure: an optional pure-ASCII component, followed by a UTF-8 Byte Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the relevant section of the specification .) 

In Python 3.1, code was added to$_{SysLogHandler}$ to insert a BOM into the message, but unfortunately, it was implemented incorrectly, with the BOM appearing at the beginning of the message and hence not allowing any pure- ASCII component to appear before it. 

As this behaviour is broken, the incorrect BOM insertion code is being removed from Python 3.2.4 and later. How- ever, it is not being replaced, and if you want to produce RFC 5424 -compliant messages which include a BOM, an optional pure-ASCII sequence before it and arbitrary Unicode after it, encoded using UTF-8, then you need to do the following: 

1. Attach a$_{Formatter}$ instance to your$_{SysLogHandler}$ instance, with a format string such as: 

'ASCII section \ufeff Unicode section' 

The Unicode code point U+FEFF, when encoded using UTF-8, will be encoded as a UTF-8 BOM – the byte- string$_{b'\xef\xbb\xbf'}$ . 

2. Replace the ASCII section with whatever placeholders you like, but make sure that the data that appears in there after substitution is always ASCII (that way, it will remain unchanged after UTF-8 encoding). 

3. Replace the Unicode section with whatever placeholders you like; if the data which appears there after substi- tution contains characters outside the ASCII range, that’s fine – it will be encoded using UTF-8. 

The formatted message will be encoded using UTF-8 encoding by$_{SysLogHandler}$ . If you follow the above rules, you should be able to produce RFC 5424 -compliant messages. If you don’t, logging may not complain, but your messages will not be RFC 5424-compliant, and your syslog daemon may complain. 

## 19 Implementing structured logging 

Although most logging messages are intended for reading by humans, and thus not readily machine-parseable, there might be circumstances where you want to output messages in a structured format which is capable of being parsed by a program (without needing complex regular expressions to parse the log message). This is straightforward to achieve using the logging package. There are a number of ways in which this could be achieved, but the following is a simple approach which uses JSON to serialise the event in a machine-parseable manner: 

import json import logging classStructuredMessage : def __init__ (self, message,/,**kwargs): self.message =message self.kwargs =kwargs def __str__ (self): 

(continues on next page) 

