Create a TQL parsing pipeline package from sample log data
Builds a Tenzir package that parses raw log data into structured events.
/plugin marketplace add tenzir/claude-plugins/plugin install meta@tenzirGuide the user through creating a Tenzir package that parses raw log data into structured events.
Begin by invoking these skills:
tql:managing-packagestql:writing-programsYou MUST follow the following phases in EXACT order.
Objective: Learn about the input data and understand its structure.
Steps:
You MUST state "Phase 1 complete" before proceeding.
Objective: Create the package structure for iterative development.
Prerequisites: (read with the docs:reader subagent once per session)
Steps:
Use AskUserQuestion to confirm the package ID (typically vendor name, e.g.,
fortinet, cisco, microsoft). In the instructions below, replace pkg
with the chosen package ID.
Create the package directory structure:
<pkg>/
├── package.yaml
├── README.md
├── operators/
│ └── parse.tql
├── tests/
│ ├── parse.tql
│ └── inputs/
│ └── parse.txt
└── changelog/
Create package.yaml with the package metadata.
Create the initial parse operator in operators/parse.tql with just
read_lines as a starting point.
Create a test file tests/parse.tql that reads from the input:
from_file f"{env("TENZIR_INPUTS")}/parse.txt" {
pkg::parse
}
Note: Use an appropriate file extension for the input (.json, .csv,
.log) based on the detected format.
Save the sample log data to tests/inputs/parse.txt (or appropriate
extension).
Run uvx tenzir-test --root <pkg> -u --summary to create an initial
baseline.
You MUST state "Phase 2 complete" before proceeding.
Objective: Refine the parser until all fields are parsed and properly typed.
Prerequisites: (read with the docs:reader subagent once per session)
Steps:
Loop until all fields are properly parsed:
Make ONE modification to the parse operator. Typical actions include:
Date & time parsing: Parse timestamps as type time or duration
rather than keeping them as strings.
IP addresses: TQL has first-class IP address types; an ip literal
has the form 1.2.3.4 (not "1.2.3.4"). Ensure all IP addresses are
parsed as type ip.
Subnets: TQL has first-class subnet types; a subnet literal has
the form 10.0.0.0/8. Ensure all CIDR subnets are parsed as subnet.
Strings: Clean string artifacts with the trim function.
Lists: Parse comma-separated values surrounded by brackets as lists.
Nested structures: Parse nested structures using parse_* functions
according to the value format.
Sentinel values: Use replace to normalize sentinel values:
replace what="None", with=null
replace what="N/A", with=null
replace fieldname, what="NO", with=false
Run uvx tenzir-test --root <pkg> --summary and observe the output diff
If the diff looks good, run uvx tenzir-test --root <pkg> -u --summary to
update the baseline
Go back to Step 1 and continue with the next modification
You MUST state "Phase 3 complete" before proceeding.
Objective: Create additional input samples to expand test coverage.
Steps:
tests/inputs/parse-synthetic.txttests/parse-synthetic.tqlYou MUST state "Phase 4 complete" before proceeding.
Provide a final summary of the parser's functionality: