When building or troubleshooting detection logic in Wazuh, wazuh-logtest is one of the most valuable diagnostic tools available.
It allows administrators to simulate how Wazuh processes incoming log events without waiting for live data to arrive from monitored endpoints.
By feeding sample logs into the analysis engine, you can verify whether decoders correctly parse fields and whether rules generate the expected security alerts before deploying changes to production.
One of the more confusing issues administrators encounter is when the alerts field is missing from the JSON output.
At first glance, the log may appear to have been processed successfully, yet the expected alert information never appears.
This often leads users to believe that wazuh-logtest is malfunctioning when the real cause is typically related to rule evaluation, decoder matching, configuration settings, or the specific command-line options being used.
Without the alerts field, validating detection logic becomes significantly more difficult.
Security teams cannot easily confirm whether a custom rule fired, whether an event reached the configured alert level, or whether changes to decoders produced the intended results.
This uncertainty can delay deployments and increase the risk of production rules silently failing to detect malicious activity.
In this guide, you’ll learn how wazuh-logtest generates alerts internally, why the alerts field may disappear from JSON output, how to systematically troubleshoot each stage of the processing pipeline, and the best practices for ensuring your custom decoders and rules generate consistent, testable results.
Resources:
Wazuh documentation on log testing: https://documentation.wazuh.com/current/user-manual/ruleset/testing.html
Related Guide:
What Is wazuh-logtest?
wazuh-logtest is a command-line utility included with the Wazuh manager that allows administrators to manually submit log events to the Wazuh analysis engine.
Instead of waiting for agents to forward real-world events, the tool processes sample logs immediately, making it invaluable for developing custom decoders, testing detection rules, and troubleshooting parsing issues.
Unlike simply inspecting log files, wazuh-logtest executes the same analysis pipeline used by the Wazuh manager.
This means it evaluates:
- Decoders
- Rule inheritance
- Rule chaining
- Field extraction
- Alert generation logic
Because the tool follows the actual detection workflow, it provides an accurate preview of how Wazuh will treat a log once it reaches production.
Purpose of the Tool
The primary goal of wazuh-logtest is to validate detection logic before deployment.
Security teams commonly use it to:
- Test custom decoders
- Verify regex patterns
- Confirm extracted fields
- Debug rule inheritance
- Validate rule IDs
- Test alert levels
- Confirm MITRE ATT&CK mappings
- Verify JSON output before deploying configuration changes
Using wazuh-logtest dramatically reduces troubleshooting time because you can repeatedly test the same log entry without generating actual events on monitored systems.
Related Guide: Custom Decoder Isn’t Matching: Wazuh Logtest Deep Dive
How It Processes Logs
When a log is submitted, wazuh-logtest sends it through the same internal processing stages used by the Wazuh analysis daemon (analysisd).
The tool attempts to:
- Normalize the raw log
- Match a decoder
- Extract fields
- Evaluate every applicable rule
- Generate alerts if rule conditions are satisfied
- Produce structured output (including JSON when requested)
Because every stage depends on the previous one succeeding, an error early in the pipeline, such as a decoder failing to match, can prevent alert generation entirely.
Relationship Between Decoders, Rules, and Alerts
Understanding the relationship between these three components is essential when troubleshooting missing alerts.
Decoders identify the log format and extract meaningful fields from the raw message.
For example, a decoder might extract:
- source IP
- username
- process name
- event ID
- file path
These extracted fields are then evaluated against rules.
Rules determine whether:
- suspicious activity occurred
- thresholds were exceeded
- compliance requirements were met
- an alert should be created
Only after a rule successfully matches does Wazuh create an alert object.
If no rule fires, or if every matching rule has an alert level below the configured threshold, the JSON output may not contain an alerts section.
Typical JSON Output Structure
When everything works correctly, JSON output typically contains several sections describing how the event was processed.
Common objects include:
- Input log
- Decoder information
- Extracted fields
- Matching rules
- Alert metadata
- Rule level
- Description
- Groups
- MITRE ATT&CK mappings (when applicable)
If the alerts object is missing, it usually indicates that the processing pipeline completed without producing an alert rather than indicating a failure of wazuh-logtest itself.
The official Wazuh documentation recommends using log testing to verify both decoder extraction and rule matching before deploying configuration changes.
How Wazuh Generates Alerts During Log Testing
Understanding how Wazuh internally creates alerts makes troubleshooting much easier.
The detection engine follows a sequential pipeline where each phase depends on the previous one.
If any stage fails, the final JSON output may omit the alerts field entirely.
Phase 1: Log Collection
Everything begins when wazuh-logtest receives a raw log entry.
Unlike events received from an agent, the log is manually submitted through the testing interface.
The analysis engine then treats this input as though it had arrived from a monitored endpoint.
Before any detection occurs, Wazuh performs basic preprocessing, such as:
- Normalizing the log
- Determining the log format
- Preparing the event for decoder matching
If the input log is malformed or incomplete, later stages may never execute correctly.
Phase 2: Decoder Matching
The next step is identifying which decoder can interpret the log.
Decoders act as parsers that recognize known log formats and extract structured fields.
During this phase Wazuh attempts to identify:
- Program name
- Timestamp
- Username
- Source IP
- Destination IP
- Process name
- Event identifiers
- File paths
- Custom fields
If no decoder matches, rule evaluation becomes extremely limited because most rules rely on extracted fields rather than raw log text.
This is one of the most common reasons administrators later discover that no alerts appear in the JSON output.
Related Guide: How to Fix “Field Already Defined” Syntax Errors in Wazuh Decoders
Phase 3: Rule Evaluation
After decoding, Wazuh begins evaluating its ruleset.
Each rule checks specific conditions, including:
- Decoder name
- Parent rule inheritance
- Extracted field values
- Regular expression matches
- Frequency thresholds
- Time windows
- Event correlation
- Previous rule matches
Rules are evaluated in order, with child rules inheriting conditions from parent rules where applicable.
Only rules whose conditions evaluate to true are considered successful matches.
One important design principle emphasized by the Wazuh engineering team is that decoders extract information, while rules make detection decisions.
Keeping these responsibilities separate improves maintainability and reduces false positives.
Wazuh Rules Syntax Reference: https://documentation.wazuh.com/current/user-manual/ruleset/rules/index.html
Phase 4: Alert Creation
If one or more rules match successfully, Wazuh determines whether an alert should actually be generated.
Several factors influence alert creation, including:
- Rule level
noalertsettings- Rule suppression
- Correlation logic
- Frequency requirements
- Ignore intervals
- Child rule behavior
A rule can technically match without producing an alert.
For example:
- Rules configured with
<noalert>1</noalert> - Informational parent rules
- Correlation rules awaiting additional events
- Rules below configured alert thresholds
These situations commonly explain why users see successful decoder matches but no alerts object in JSON output.
Phase 5: JSON Output Generation
Finally, wazuh-logtest serializes the processing results into JSON.
Depending on what occurred during evaluation, the output may contain:
- Input event information
- Decoder metadata
- Extracted fields
- Matching rules
- Alert information
- Rule descriptions
- Groups
- Compliance mappings
- MITRE ATT&CK techniques
If no alert object was created during Phase 4, the resulting JSON simply omits the alerts field.
This behavior is expected and generally indicates that Wazuh completed processing successfully but determined that the event did not produce an alert under the current ruleset, rather than indicating a software defect.
Independent security practitioners and experienced Wazuh users frequently recommend tracing the event through each processing phase, decoder, rule match, and alert generation, to isolate where the pipeline stops, rather than assuming the JSON serializer is at fault.
Example: Decoder Matches but No Alert Is Generated
One of the most common wazuh-logtest scenarios is where the decoder successfully parses a log entry, but no alert appears in the JSON output.
This typically indicates that the decoding stage completed successfully while rule evaluation failed.
Let’s walk through a practical example.
Sample Log
Suppose you’re testing the following authentication log:
Jul 15 09:42:17 web01 sshd[2153]: Failed password for invalid user admin from 192.168.1.100 port 53324 ssh2Running the log through wazuh-logtest shows that it is decoded correctly.
Decoder Example
A simplified decoder might look like this:
<decoder name="custom-sshd">
<prematch>sshd</prematch>
<regex>Failed password for invalid user (\S+) from (\S+)</regex>
<order>username,srcip</order>
</decoder>The decoder successfully extracts:
username = adminsrcip = 192.168.1.100
At this point, decoding has completed successfully.
Rule Example
Now consider the following custom rule:
<rule id="100500" level="10">
<decoded_as>custom-sshd</decoded_as>
<field name="action">failed</field>
<description>Failed SSH login</description>
</rule>Although the decoder worked, the rule never matches.
Why?
The decoder never extracted an action field.
The rule depends on:
<field name="action">failed</field>Since that field does not exist, the condition evaluates to false.
Why the Alert Is Missing
The processing pipeline looks like this:
Raw Log
│
▼
Decoder ✓
│
Extract username ✓
Extract srcip ✓
│
▼
Rule Evaluation
│
Missing action field ✗
│
▼
No Rule Match
│
▼
No alerts objectNotice that nothing is technically broken.
The decoder works exactly as designed.
The rule simply requires information that is never extracted.
Corrected Configuration
There are two possible fixes.
Option 1: Modify the decoder
Extract the missing field.
<decoder name="custom-sshd">
<prematch>sshd</prematch>
<regex>Failed password for invalid user (\S+) from (\S+)</regex>
<order>action,username,srcip</order>
</decoder>Or adjust the regex so the first capture group extracts the action value.
Option 2: Modify the rule
If the action field isn’t necessary, simplify the rule.
<rule id="100500" level="10">
<decoded_as>custom-sshd</decoded_as>
<description>Failed SSH login</description>
</rule>The corrected rule now evaluates successfully and generates an alert.
Example: Rule Level Prevents Alert Creation
Another common source of confusion is when a rule matches successfully but still produces no alert because of its configured severity level.
Demonstrate a Level 0 Rule
Consider the following rule:
<rule id="100510" level="0">
<decoded_as>custom-sshd</decoded_as>
<description>SSH authentication event</description>
</rule>During testing:
- Decoder matches ✓
- Rule matches ✓
- Alert generated ✗
The missing alert is expected because the rule is configured with level="0".
Level 0 rules are intended for classification, preprocessing, or as parent rules for inheritance, not for creating alerts.
Show Corrected Rule Level
Updating the rule to an alerting severity resolves the issue.
<rule id="100510" level="8">
<decoded_as>custom-sshd</decoded_as>
<description>SSH authentication failure</description>
</rule>Now the same log produces an alert object in the JSON output.
Compare JSON Outputs
Level 0 Rule
{
"decoder": {
"name": "custom-sshd"
},
"data": {
"username": "admin",
"srcip": "192.168.1.100"
}
}Notice there is no alerts object.
Level 8 Rule
{
"decoder": {
"name": "custom-sshd"
},
"data": {
"username": "admin",
"srcip": "192.168.1.100"
},
"alerts": [
{
"rule": {
"id": 100510,
"level": 8,
"description": "SSH authentication failure"
}
}
]
}The only configuration change was the rule level, yet the JSON output now includes the expected alert information.
Example: Missing Required Decoder Fields
Another frequent cause of missing alerts is when the decoder only extracts part of the information required by downstream rules.
Even though the decoder matches successfully, incomplete field extraction prevents rule conditions from evaluating to true.
Broken Decoder Example
Suppose the incoming log contains:
User admin logged in from 192.168.1.100The decoder is written as:
<decoder name="custom-login">
<regex>User (\S+) logged in from (\S+)</regex>
<order>username</order>
</decoder>Although the regex captures two values, only one is assigned.
Missing Extracted Field
The decoder extracts:
username = adminHowever, the second captured value is discarded because the <order> element only contains one field.
As a result:
srcip = missingA downstream rule such as:
<field name="srcip">192\.168\..*</field>can never match because srcip does not exist.
Correct Decoder Configuration
The decoder should assign every captured group.
<decoder name="custom-login">
<regex>User (\S+) logged in from (\S+)</regex>
<order>username,srcip</order>
</decoder>Now Wazuh extracts:
username = adminsrcip = 192.168.1.100
The dependent rule has access to all required fields and can evaluate successfully.
Successful JSON Output
After correcting the decoder, wazuh-logtest produces output similar to:
{
"decoder": {
"name": "custom-login"
},
"data": {
"username": "admin",
"srcip": "192.168.1.100"
},
"alerts": [
{
"rule": {
"id": 100520,
"level": 7,
"description": "User login detected"
}
}
]
}This illustrates the complete processing pipeline:
- The decoder matches the log.
- All required fields are extracted.
- The rule conditions evaluate successfully.
- Wazuh generates an alert.
- The
alertsobject appears in the JSON output.
Wazuh Decoder Syntax Documentation: https://documentation.wazuh.com/current/user-manual/ruleset/ruleset-xml-syntax/decoders.html
Useful Commands for Troubleshooting
When the alerts field is missing from wazuh-logtest output, a handful of commands can quickly help you determine whether the issue lies with your decoder, rules, configuration files, or the Wazuh manager itself.
Running these commands in a logical order can significantly reduce troubleshooting time.
Running wazuh-logtest Interactively
The easiest way to test detection logic is to launch wazuh-logtest in interactive mode.
/var/ossec/bin/wazuh-logtestAfter starting the tool, paste a raw log entry when prompted.
For every test, review:
- Selected decoder
- Extracted fields
- Matching rule IDs
- Rule levels
- Final alert output
Testing interactively allows you to make incremental changes to decoders or rules and immediately verify the results.
Wazuh Log Testing Documentation: https://documentation.wazuh.com/current/user-manual/ruleset/testing.html
Testing Individual Rules
If a specific rule is expected to generate an alert, isolate it during testing.
Verify:
- The correct decoder is selected.
- Every required field is present.
- Regex conditions evaluate successfully.
if_sidandif_groupdependencies are satisfied.- The rule’s
levelis greater than zero.
Testing one rule at a time makes it much easier to identify which condition is preventing a match.
Validating XML Files
Before assuming there is a logic problem, verify that your XML files are valid.
Check for:
- Missing closing tags
- Invalid nesting
- Duplicate rule IDs
- Duplicate decoder fields
- Incorrect
<order>entries - Improperly escaped characters
Many “missing alert” issues are ultimately caused by XML syntax errors that prevent custom rules or decoders from loading.
Checking Wazuh Manager Logs
If custom rules appear to be ignored, inspect the Wazuh manager logs during startup.
Typical log locations include:
/var/ossec/logs/ossec.logLook for messages indicating:
- XML parsing errors
- Failed rule loading
- Duplicate IDs
- Invalid decoder definitions
- Configuration warnings
These logs often reveal configuration problems that are not immediately visible in wazuh-logtest.
Restarting the Manager After Changes
Whenever you modify:
- decoders
- rules
ossec.conf- included XML files
restart the Wazuh manager so the changes are reloaded.
For systems using systemd:
sudo systemctl restart wazuh-managerAfter the restart:
- Confirm there are no startup errors.
- Verify your custom rules loaded successfully.
- Run
wazuh-logtestagain with the same sample log.
Skipping this step is a common reason administrators believe their configuration changes are being ignored.
Best Practices for Reliable wazuh-logtest Results
Following a few proven practices when developing decoders and rules can help you avoid many of the issues that cause the alerts field to be missing from JSON output.
Design Decoders Before Rules
Always create and validate your decoder before writing rules that depend on it.
First confirm that the decoder:
- Matches the correct log format.
- Extracts all required fields.
- Produces consistent output for different log samples.
Only then should you build rules around those extracted fields.
Keep Rule IDs Unique
Every custom rule should have a unique rule ID.
Duplicate IDs can lead to:
- Rules being overridden
- Unexpected matches
- Inconsistent testing results
- Difficult-to-diagnose behavior
Reserve a dedicated ID range for custom rules to minimize conflicts with the built-in ruleset.
Use Meaningful Rule Levels
Choose alert levels that reflect the severity of the event.
For example:
- Level 0: Classification or parent rules only
- Levels 1–5: Informational or low-priority events
- Levels 6–10: Medium- to high-priority security events
- Levels 11+: Critical detections requiring immediate attention
Using appropriate rule levels makes testing more predictable and helps downstream integrations prioritize alerts correctly.
Test with Real Production Logs
Whenever possible, test using raw logs captured from production systems.
Avoid manually rewriting or simplifying log entries, as even small differences in:
- spacing
- timestamps
- delimiters
- metadata
- field order
can affect decoder matching and rule evaluation.
Testing with authentic data provides the most accurate representation of production behavior.
Validate XML Before Deployment
Treat XML validation as a required step before deploying any configuration changes.
Verify that:
- XML is well-formed.
- Rule IDs are unique.
- Decoder definitions are complete.
<order>entries match regex capture groups.- Include statements reference the correct files.
Catching syntax issues early prevents unnecessary troubleshooting later.
Organize Custom Rules Separately
Store custom decoders and rules in dedicated files rather than modifying the default Wazuh ruleset.
This approach offers several benefits:
- Easier upgrades
- Simpler backups
- Cleaner troubleshooting
- Reduced risk of overwriting customizations during updates
Document Rule Dependencies
Many custom rules depend on parent rules, decoder fields, or group membership.
Document:
- Parent rule IDs
if_sidrelationshipsif_groupdependencies- Required extracted fields
- Expected decoder names
Maintaining clear documentation makes future troubleshooting much easier, especially in larger deployments.
Test Incrementally After Every Change
Avoid making multiple configuration changes before testing.
Instead:
- Modify one decoder or rule.
- Restart the Wazuh manager.
- Run
wazuh-logtest. - Review the results.
- Repeat for the next change.
Incremental testing makes it much easier to pinpoint the exact change that introduced an issue.
Frequently Asked Questions (FAQ)
Question: Why is the alerts field missing in wazuh-logtest JSON output?
The alerts field is usually missing because no rule generated an alert.
Common causes include missing rule matches, rule levels set to 0, unsatisfied rule conditions, missing decoder fields, or custom rules that failed to load.
Question: Can a decoder work without generating an alert?
Yes. A decoder’s responsibility is to parse logs and extract structured fields.
Alert generation only occurs if one or more rules successfully evaluate those fields and produce an alert.
Question: Does a level 0 rule create alerts?
No. Rules configured with level="0" are intended for classification, preprocessing, or serving as parent rules.
They typically do not generate alert objects in wazuh-logtest output.
Question: How do I know whether my decoder matched successfully?
Review the wazuh-logtest output for:
- Decoder name
- Extracted fields
- Captured values
If the expected decoder appears and the required fields are populated, the decoder matched successfully.
Question: Why are my custom rules not triggering?
Common reasons include:
- Required fields were not extracted.
- Rule conditions are incorrect.
if_sidorif_groupdependencies are not satisfied.- The rule level is set to
0. - The custom rule file failed to load because of XML errors or configuration issues.
Question: Do parent rules affect child rule execution?
Yes. Child rules that use directives such as if_sid depend on their parent rules matching first.
If the parent rule does not execute, the child rule will not be evaluated.
Question: Can malformed XML prevent rules from loading?
Absolutely. Invalid XML can prevent an entire decoder or rule file from loading.
Always validate your XML and review the Wazuh manager logs after making configuration changes.
Question: Should I restart the Wazuh manager after editing rules?
Yes. Changes to rules, decoders, or related configuration files are not applied until the Wazuh manager reloads them.
Restart the manager and verify there are no startup errors before testing again.
Question: Does wazuh-logtest behave exactly like production event processing?
For decoder and rule evaluation, wazuh-logtest uses the same analysis engine as the Wazuh manager, making it highly representative of production behavior.
However, certain features that rely on live event streams, such as long-term event correlation, frequency thresholds over time, or distributed cluster behavior, may not be fully replicated in isolated tests.
Question: How can I verify that my custom rules have been loaded?
After restarting the Wazuh manager:
- Review
/var/ossec/logs/ossec.logfor startup messages. - Check for XML parsing errors or duplicate rule IDs.
- Run
wazuh-logtestand confirm that your custom rule ID appears when the expected conditions are met.
Conclusion
When the alerts field is missing from wazuh-logtest JSON output, the root cause is almost always found within the event processing pipeline rather than the tool itself.
The most common reasons include missing rule matches, rules configured with level="0", unsatisfied rule conditions, incomplete decoder field extraction, parent rule dependency failures, malformed XML, or custom rules that were never loaded.
A successful decoder match is only the first step.
Before troubleshooting rule logic, verify that your decoder extracted every field required by downstream rules.
Missing or incorrectly parsed fields are one of the most frequent reasons alerts fail to appear.
From there, systematically examine rule conditions, alert levels, inheritance chains, XML configuration, and manager startup logs.
Working through each stage of the pipeline methodically is far more effective than making multiple configuration changes at once.
By following Wazuh best practices, such as validating decoders before writing rules, keeping custom rules organized, using unique rule IDs, testing with real production logs, and validating XML before deployment, you can ensure that wazuh-logtest produces reliable, predictable results and accurately reflects how your detection logic will behave in production.
Related Guides:

Be First to Comment