Skip to content

Handlers

A Handler is the low-level implementation on how to parse an event, typically each vendor will have its own handler and each transport method (Syslog, NetFlow, RADIUS Accounting) will also have its own handler implementation.

A handler will typically inherit either the Base handlers or a Generic handler:

from consumer.handlers.generic import BaseSyslogHandler, GenericSyslogHandler

class MySyslogHandler(BaseSyslogHandler):
    def parse_message(self, message: str) -> dict:
        # parse_message needs to be implemented on all Handlers that inherit the BaseSyslogHandler

class AnotherSyslogHandler(GenericSyslogHandler):
    pass

Typical Design of a Handler

Each handler should implement at a minimum the parse_message method. This should be responsible for determining which type of metric it is and passing into a relevant method to perform the preprocessing/data normalization. It's not a requirement to implement the 4 methods for parsing session, port, port_block and address because not all vendors will support these but at a minimum parse_session_mapping should be implemented.

These methods will normalize the data from the relevant collection method into a metric which can be processed by an output. Each metric must contain key named type of which the value type must be NATEventEnum, as shown below:

class NATEventEnum(str, Enum):
    ADDRESS_MAPPING = "address-mapping"
    PORT_MAPPING = "port-mapping"
    PORT_BLOCK_MAPPING = "port-block-mapping"
    SESSION_MAPPING = "session-mapping"

Outputs are then configured to use this event to determine further logic, for example, which database table it will be inserted into for the TimescaleDB output.

Handler Architecture