Version
v0.9.11 (latest release), also present on master
Summary
extract_parameters() uses re.sub(delimiter, " ", log_message) (regex replacement) to preprocess delimiters, while get_content_as_tokens() uses content.replace(delimiter, " ") (literal replacement).
When a delimiter is a regex metacharacter (e.g. "."), template mining succeeds but parameter extraction silently returns None.
Root Cause
Two methods handle the same extra_delimiters config inconsistently:
┌─────────────────────────┬───────────────────┬──────┬─────────────────────────────────────┬─────────────────────┐
│ Method │ File │ Line │Code │ Treats delimiter as │
├─────────────────────────┼───────────────────┼──────┼─────────────────────────────────────┼─────────────────────┤
│ get_content_as_tokens() │ drain.py │ 306 │ content.replace(delimiter, " ") │ Literal string │
├─────────────────────────┼───────────────────┼──────┼─────────────────────────────────────┼─────────────────────┤
│ extract_parameters() │ template_miner.py │ 214 │ re.sub(delimiter, " ", log_message) │ Regex pattern │
└─────────────────────────┴───────────────────┴──────┴─────────────────────────────────────┴─────────────────────┘
Introduced in commit 2a363a2 (PR #52, Jan 12 2022) by Ovi T, co-authored by David Ohana.
Reproduction
from drain3 import TemplateMiner
from drain3.template_miner_config import TemplateMinerConfig
config = TemplateMinerConfig()
config.drain_extra_delimiters = ["."] # dot as delimiter
tm = TemplateMiner(None, config)
# Step 1: Mine templates — works fine
tm.add_log_message("app.server status.ok code.200")
tm.add_log_message("app.server status.ok code.404")
result = tm.add_log_message("app.server status.err code.500")
template = result["template_mined"]
print(f"Template: {template}") # contains <*> — mining succeeded
# Step 2: Extract parameters — silently fails
params = tm.extract_parameters(template, "app.server status.err code.503")
print(f"Params: {params}") # None — extraction failed on a line it just clustered
Why it fails: re.sub(".", " ", "app.server status.err code.503") treats . as the regex wildcard (matches any character), turning the entire message into spaces. The template regex then can't match.
Why mining works: get_content_as_tokens uses str.replace(".", " ") which only replaces literal dots — correctly producing tokens ["app", "server", "status", "err", "code", "503"].
Affected delimiters
Any regex metacharacter used as a delimiter: ., +, *, ?, ^, $, |, (, ), [, {, \
Suggested Fix
template_miner.py line 214 — use literal replacement to match get_content_as_tokens:
Before (regex — breaks on metacharacters):
log_message = re.sub(delimiter, " ", log_message
After (literal — consistent with get_content_as_tokens):
log_message = log_message.replace(delimiter, " ")
Version
v0.9.11 (latest release), also present on master
Summary
extract_parameters()usesre.sub(delimiter, " ", log_message)(regex replacement) to preprocess delimiters, whileget_content_as_tokens()usescontent.replace(delimiter, " ")(literal replacement).When a delimiter is a regex metacharacter (e.g. "."), template mining succeeds but parameter extraction silently returns None.
Root Cause
Two methods handle the same extra_delimiters config inconsistently:
Introduced in commit 2a363a2 (PR #52, Jan 12 2022) by Ovi T, co-authored by David Ohana.
Reproduction
Why it fails:
re.sub(".", " ", "app.server status.err code.503")treats . as the regex wildcard (matches any character), turning the entire message into spaces. The template regex then can't match.Why mining works:
get_content_as_tokensusesstr.replace(".", " ")which only replaces literal dots — correctly producingtokens ["app", "server", "status", "err", "code", "503"].Affected delimiters
Any regex metacharacter used as a delimiter:
., +, *, ?, ^, $, |, (, ), [, {, \Suggested Fix
template_miner.py line 214 — use literal replacement to match
get_content_as_tokens:Before (regex — breaks on metacharacters):
log_message = re.sub(delimiter, " ", log_messageAfter (literal — consistent with get_content_as_tokens):
log_message = log_message.replace(delimiter, " ")