WAF Auto-Block uses standard .NET structured logging. Log entries cover the full polling and blocking lifecycle — startup, every poll cycle, each block and unblock decision, cleanup passes, and API failures — and are designed to let you operate the service safely without reading source code. Every significant state transition emits a log entry that includes enough context to understand what happened and why.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/proteo5/waf-autoblock/llms.txt
Use this file to discover all available pages before exploring further.
Log Levels
The default configuration emitsInformation-level logs for most components. This includes cycle start and end summaries, block and unblock events, cleanup summaries, and any error conditions.
Changing the log level
Set the WafAutoblock-scoped log level to Debug to see fine-grained matching decisions: per-candidate evaluation, threshold comparisons, and skip reasons for IPs that were considered but not blocked.
Override via environment variable (recommended for Docker deployments):
Key Log Messages
The entries below reflect the actual log calls inWorker.cs. Template placeholders like {Ip} and {RuleId} are replaced with real values at runtime.
WAF auto-block worker started
WAF auto-block worker started
Polling skipped because Cloudflare credentials or detectors are not configured yet.
Polling skipped because Cloudflare credentials or detectors are not configured yet.
ApiToken, ZoneTag, AccountId, or BlocklistId), or when no detector (WAF rule or HTTP status code rule) is enabled. The service continues running and will retry on the next cycle — no restart is needed after completing configuration.Polling Cloudflare for the last {WindowSeconds} seconds
Polling Cloudflare for the last {WindowSeconds} seconds
{WindowSeconds} reflects the configured Polling.WindowSeconds value (minimum 1). Seeing this message confirms credentials are present and at least one detector is enabled.BLOCKED {Ip} via {RuleName} ({RuleId}) count {Count} threshold {Threshold} ttl {TtlMinutes}m item {ItemId}
BLOCKED {Ip} via {RuleName} ({RuleId}) count {Count} threshold {Threshold} ttl {TtlMinutes}m item {ItemId}
{Ip}— the offending IP address{RuleName}/{RuleId}— the matched rule’s display name and Cloudflare rule ID{Count}— number of WAF events observed within the polling window{Threshold}— the configured minimum count required to block{TtlMinutes}— how long (in minutes) this block will be maintained{ItemId}— the Cloudflare account-level IP list item ID, used for TTL-based removal
BLOCKED {Ip} via {DetectorName} (HTTP {StatusCode}) totalErrors ...
BLOCKED {Ip} via {DetectorName} (HTTP {StatusCode}) totalErrors ...
{Ip}— the offending IP address{DetectorName}— the configured detector name, defaulting tohttp_status_{StatusCode}{StatusCode}— the HTTP status code that triggered the ruletotalErrors {TotalErrors}— total error requests from this IP across all monitored codesdistinctPaths {DistinctPaths}— number of distinct request paths hitcodeCount {CodeCount}— requests matching this specific status coderatio {CodeRatio}— fraction of total errors attributable to this status codettl {TtlMinutes}m— block duration in minutesitem {ItemId}— Cloudflare IP list item ID
Unblocked {Ip} after TTL expiry (rule {RuleId}, item {ItemId})
Unblocked {Ip} after TTL expiry (rule {RuleId}, item {ItemId})
{RuleId} identifies the original rule that triggered the block.Poll cycle completed ... with {EventCount} WAF candidate events, {HttpStatusSignalCount} HTTP status signals and {BlockedCount} new blocks
Poll cycle completed ... with {EventCount} WAF candidate events, {HttpStatusSignalCount} HTTP status signals and {BlockedCount} new blocks
{EventCount}— total WAF event records returned by Cloudflare analytics for the window{HttpStatusSignalCount}— total HTTP status signal records evaluated{BlockedCount}— net new IPs added to the blocklist in this cycle (0 is normal when no new offenders appear)
Cleanup completed ... with {RemovedCount} expired entries removed and {DeferredCount} deferred
Cleanup completed ... with {RemovedCount} expired entries removed and {DeferredCount} deferred
{RemovedCount} is the number of IPs successfully removed from both Cloudflare and SQLite. {DeferredCount} is the number of entries whose Cloudflare item ID could not be resolved and will be retried on the next cycle.Skipping {Ip} in HTTP status detector because it is a loopback address
Skipping {Ip} in HTTP status detector because it is a loopback address
127.0.0.1, ::1, localhost, or IPv4-mapped IPv6 loopback). Loopback addresses are monitored but never auto-blocked by design.Rate-limited while blocking {Ip}
Rate-limited while blocking {Ip}
Failed to block {Ip}
Failed to block {Ip}
HTTP Status Detection Logs
WhenHttpStatusDetection.Enabled = true, additional log entries appear at Debug level during per-IP threshold evaluation.
| Message | Level | Meaning |
|---|---|---|
Evaluating HTTP status detector for codes {Codes} over {WindowSeconds} seconds | Debug | Status detection sub-cycle is starting; lists all active status codes |
HTTP status signal {Ip} status {StatusCode} path {Path} count {Count} | Debug | Raw signal from Cloudflare analytics before aggregation |
Skipping {Ip} for HTTP {StatusCode} because thresholds were not met (total …, paths …, ratio …) | Debug | IP evaluated but did not meet MinTotalErrors, MinDistinctPaths, or MinCodeRatio |
Skipping {Ip} for HTTP {StatusCode} because it is already in the local block store | Debug | IP already blocked; evaluation short-circuits |
BLOCKED {Ip} via {DetectorName} (HTTP {StatusCode}) … | Warning | Block decision — see full field list in Key Log Messages above |
Skipping {Ip} in HTTP status detector because it is a loopback address | Information | Loopback exclusion |
HTTP status detector excluded {Count} loopback IP aggregate(s) in this cycle | Information | Cycle-level summary of loopback exclusions |
Distributed Path Detector Logs
WhenHttpStatusDetection.DistributedPathDetection.Enabled = true, additional entries appear for the path-level analysis layer.
| Message | Level | Meaning |
|---|---|---|
Distributed HTTP path detector found no suspicious paths for HTTP {StatusCode} | Debug | No paths met MinPathTotalErrors and MinDistinctIpsPerPath thresholds |
Skipping {Ip} in distributed HTTP path detector because thresholds were not met | Debug | IP hit suspicious paths but below MinIpHitsOnSuspiciousPaths or MinDistinctSuspiciousPathsPerIp |
BLOCKED {Ip} via {DetectorName} (HTTP {StatusCode}) suspiciousPathHits … suspiciousPathCount … | Warning | Distributed path detector triggered a block |
Skipping {Ip} in distributed HTTP path detector because it is a loopback address | Information | Loopback exclusion in the path detector |
Distributed HTTP path detector evaluated codes {StatusCodes} and blocked {BlockedCount} | Information | End-of-detector summary |
Log Level Recommendations
| Scenario | Recommended Level | Reason |
|---|---|---|
| Production steady-state | Information | Cycle summaries and block/unblock events without per-candidate noise |
| Troubleshooting missing blocks | Debug for WafAutoblock | Exposes skip reasons, rule ID mismatches, and threshold comparisons |
| Alerting integrations | Warning or above | Block events, rate-limit warnings, and poll skip warnings — no routine chatter |
| Initial setup validation | Debug | See every candidate event and matching decision to confirm rule IDs are correct |