drain3

repository·master·Indexed 21 days ago

https://github.com/logpai/drain3

A persistent and streaming log template miner that extracts structured templates from unstructured log streams in real-time using a fixed-depth parse tree. It supports real-time learning, masking of variable parts (like IPs and emails), and state persistence via Kafka, Redis, File, or Memory. The library provides both Training mode for continuous learning and Inference mode for matching logs against fixed templates.

Tokens
10.7K
Snippets
29
Records
42
Agent score
73%

What's inside drain3

  1. What is Drain3?

    master
    Drain3 is an online log template miner designed to extract templates (clusters) from a stream of log messages in real-time. It uses a fixed-depth parse tree to guide the search process, preventing the construction of deep, unbalanced trees. It continuously learns on-the-fly and supports features like masking, persistence, and memory-efficient cluster management.
  2. Choose between Training and Inference modes

    master

    Drain3 provides two distinct modes depending on whether you want to learn new templates or just match against existing ones.

    Training Mode

    Use this when you want the model to continuously learn from a stream. It will match logs to existing clusters or create/update clusters as needed.

    • Method: template_miner.add_log_message(log_line)

    Inference Mode

    Use this when you want to match logs against a fixed set of already-learned templates without modifying the model. No new clusters are created, and existing templates are not changed. A match must be perfect; otherwise, it returns None.

    • Method: template_miner.match(log_line)
    • Tip: Use the persistence feature to load previously trained clusters before starting inference.
  3. Use Masking to improve template mining accuracy

    master

    Masking allows you to replace specific variable parts of a log message (like IPs, numbers, or emails) with keywords before they reach the Drain core. This prevents the miner from creating too many unique templates for similar messages.

    Custom masking is defined using a list of regular expressions in the format {'regex_pattern', 'mask_with'}. Any parameter that does not match a custom mask is replaced by the default <*> by the Drain core.

    [MASKING]
    masking = [
              {"regex_pattern":"((?<=[^A-Za-z0-9])|^)(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})((?=[^A-Za-z0-9])|$)", "mask_with": "IP"},
              {"regex_pattern":"((?<=[^A-Za-z0-9])|^)([\\-\+]?\\d+)((?=[^A-Za-z0-9])|$)", "mask_with": "NUM"},
              ]
  4. Persist Drain3 state for restart resiliency

    master

    Drain3 can save and load snapshots of its state (the search tree and all identified clusters) in JSON format. This allows the miner to continue learning from where it left off after a restart.

    Snapshots are triggered by:

    • cluster_created: When a new template is identified.
    • cluster_template_changed: When an existing template is updated.
    • periodic: After the interval specified by snapshot_interval_minutes.

    Supported Persistence Modes

    • Kafka: Saves snapshots to a dedicated topic. Requires topic_name and supports standard Kafka kwargs (e.g., bootstrap_servers).
    • Redis: Saves snapshots to a key in a Redis database.
    • File: Saves snapshots to a local file.
    • Memory: Saves snapshots to an in-memory object.
    • None: No persistence.

    Developers can extend persistence to other databases by inheriting from the PersistenceHandler class.

  5. Install Drain3 via pip

    master

    You can install the core Drain3 package using pip3.

    Note on Persistence: If you intend to use Kafka or Redis for persistence, you must install their respective client libraries explicitly as they are optional dependencies.

    pip3 install drain3
    
    # If using Kafka persistence:
    pip3 install kafka-python
    
    # If using Redis persistence:
    pip3 install redis
  6. Run Drain3 examples

    master

    To run the provided examples from the repository, you must first install the dependencies using pipenv:

    python3 -m pipenv sync

    Example 1: Stdin Demo

    Run examples/drain_stdin_demo.py to test Drain3 using input from stdin. This demo supports various persistence modes (Kafka, file, or none). You can switch modes by changing the persistence_type variable in the script.

    • Enter log lines via command line.
    • Press q to exit 'online learn-and-match' mode.
    • The demo then enters 'match (inference) only' mode (no new clusters are trained).
    • Press q again to finish.

    Example 2: Big File Demo

    Run examples/drain_bigfile_demo.py to process a real-world SSH server log file. This demo prints the resulting clusters, the prefix tree, and performance statistics.

    # Install dependencies
    python3 -m pipenv sync
    
    # Run stdin demo
    python3 -m pipenv run python -m examples.drain_stdin_demo
    
    # Run big file demo
    python3 -m pipenv run python -m examples.drain_bigfile_demo
  7. How Jaccard similarity is calculated in JaccardDrain

    master

    The similarity between a log sequence (seq2) and a template sequence (seq1) is calculated using the Jaccard index: len(set(seq1) & set(seq2)) / len(set(seq1) | set(seq2)).

    Key implementation details:

    • Parameter Handling: If include_params is True, the param_str (wildcard tokens) are excluded from the set intersection and union calculation.
    • Length Matching: If the sequences have the same length and the template contains parameters, the positions of those parameters are handled to ensure accurate comparison.
    • Similarity Boost: To account for the nature of the Jaccard coefficient in this implementation, a gain of 1.3 is applied to the result (capped at 1.0) to adjust the similarity score.
    • Empty Sequences: An empty sequence results in a similarity of 1.0.
    # Internal logic representation of the similarity calculation
    ret_val = len(set(seq1) & set(seq2)) / len(set(seq1) | set(seq2))
    ret_val = ret_val * 1.3 if ret_val * 1.3 < 1 else 1
  8. Configure Drain3 using .ini files or objects

    master

    Drain3 uses configparser for configuration. By default, it looks for a drain3.ini file in the working directory. Alternatively, you can pass a TemplateMinerConfig object directly to the TemplateMiner constructor.

    Primary Configuration Parameters

    [DRAIN] Section

    • sim_th: Similarity threshold. If the percentage of similar tokens is below this value, a new cluster is created. (Default: 0.4)
    • depth: Maximum depth levels of log clusters. Minimum is 3. (Default: 4)
    • max_children: Maximum number of children for an internal node. (Default: 100)
    • max_clusters: Maximum number of tracked clusters. When reached, the model uses an LRU (Least Recently Used) eviction policy to replace old clusters. (Default: unlimited)
    • extra_delimiters: Additional delimiters used when splitting log messages into words (e.g., ['_', ':']).

    [MASKING] Section

    • masking: Parameters for masking, provided in JSON format.
    • mask_prefix: The prefix used for identified parameters in templates. (Default: <)
    • mask_suffix: The suffix used for identified parameters in templates. (Default: >)

    [SNAPSHOT] Section

    • snapshot_interval_minutes: Time interval for creating new snapshots. (Default: 1)
    • compress_state: Whether to compress the state before saving (useful for Kafka persistence).
  9. Configure token parameterization

    master

    Drain3 can automatically treat tokens containing digits as parameters (wildcards). This is controlled by the parametrize_numeric_tokens flag in the Drain constructor.

    When enabled, if a token contains a digit, the parser may use the param_str (default <*>) to represent it in the template, allowing for more generalized matching of logs containing IDs, IP addresses, or timestamps.

  10. Understand the output format of SimpleProfiler

    master

    When SimpleProfiler.report() is called, it prints a summary of all tracked sections. The output for each section follows this pattern:

    {section_name}: took {total_time} s ({% of total}), {sample_count} samples, {ms_per_1k} ms / 1000 samples, {hz} hz

    Field Definitions

    • took: Total time spent in the section (e.g., 12.34 s). If an enclosing_section_name is provided, it also shows the percentage of that section's time.
    • samples: Total number of times the section was executed.
    • ms / 1000 samples: The average time taken for 1,000 samples (useful for high-frequency operations).
    • hz: The frequency of execution (samples per second).

    If reset_after_sample_count is used, batch statistics are also shown in parentheses next to the total statistics.

  11. Extract parameters from log messages

    master

    Drain3 allows you to retrieve an ordered list of variables from a log message after its template has been mined. Each extracted parameter is an ExtractedParameter object containing the value and the mask_name (the name of the mask that matched, or * for the catch-all mask).

    By default, exact_matching=True uses the regular expressions defined in your masking instructions to find variables. If you disable exact matching, every variable is matched against a non-whitespace character sequence, which can improve performance at the cost of accuracy.

    To optimize performance, regexes generated per template are cached. You can adjust the cache size using the MASKING/parameter_extraction_cache_capacity configuration parameter.

    result = template_miner.add_log_message(log_line)
    params = template_miner.extract_parameters(
        result["template_mined"], 
        log_line, 
        exact_matching=True
    )
  12. Reference: TemplateMinerConfig attributes

    master

    The following attributes define the behavior of the template mining engine. When loading from a file, these correspond to specific sections and keys in a .ini formatted configuration file.

    [DRAIN] Section

    • engine: The mining engine to use (e.g., Drain).
    • extra_delimiters: A collection of strings used as additional delimiters.
    • sim_th: Similarity threshold for matching log messages to existing templates.
    • depth: The maximum depth of the parsing tree.
    • max_children: The maximum number of children allowed per node in the tree.
    • max_clusters: The maximum number of clusters (templates) to maintain. If None, there is no limit.
    • parametrize_numeric_tokens: Boolean indicating whether numeric tokens should be automatically parameterized.

    [PROFILING] Section

    • enabled: Boolean to enable or disable profiling.
    • report_sec: Interval in seconds for generating profiling reports.

    [SNAPSHOT] Section

    • snapshot_interval_minutes: Interval in minutes for taking state snapshots.
    • compress_state: Boolean indicating whether to compress the state during snapshots.

    [MASKING] Section

    • masking: A JSON-formatted list of masking instructions. Each instruction is a dictionary containing regex_pattern and mask_with.
    • mask_prefix: The prefix string used for masked parameters.
    • mask_suffix: The suffix string used for masked parameters.
    • parameter_extraction_cache_capacity: The capacity of the cache used for parameter extraction.
    [DRAIN]
    engine = Drain
    sim_th = 0.4
    depth = 4
    max_children = 100
    max_clusters = 1000
    parametrize_numeric_tokens = True
    extra_delimiters = [' ', '	', ':']
    
    [PROFILING]
    enabled = True
    report_sec = 60
    
    [SNAPSHOT]
    snapshot_interval_minutes = 5
    compress_state = True
    
    [MASKING]
    mask_prefix = <
    mask_suffix = >
    parameter_extraction_cache_capacity = 3000
    masking = [{"regex_pattern": "\\d+", "mask_with": "<NUM>"}]