The guardrail outcome counters added in the test-connection observability work (aisix_guardrail_blocks_total / aisix_guardrail_bypasses_total) are recorded in chat.rs's centralized emit_usage_event, which covers /v1/chat/completions only.
The anthropic /v1/messages handler (messages.rs) ALSO runs the guardrail chain (resolve + check_input/check_output, returns ContentFiltered on block) but has a pre-existing telemetry gap: its UsageEvent / AnthropicStreamCompletion does not carry guardrail_blocked / bypass_reason, so the metric can't be recorded at its emit point. As a result the counters undercount anthropic guardrail blocks/bypasses.
Fix: thread guardrail_blocked + bypass_reason through the messages.rs telemetry (closing the AnthropicStreamCompletion gap) and record_guardrail_outcome at its emit, OR record at the messages verdict sites. This naturally folds into the applied-guardrails telemetry-threading work (#379 observability "A" slice), which reworks guardrail telemetry uniformly across both paths.
The guardrail outcome counters added in the test-connection observability work (aisix_guardrail_blocks_total / aisix_guardrail_bypasses_total) are recorded in chat.rs's centralized emit_usage_event, which covers /v1/chat/completions only.
The anthropic /v1/messages handler (messages.rs) ALSO runs the guardrail chain (resolve + check_input/check_output, returns ContentFiltered on block) but has a pre-existing telemetry gap: its UsageEvent / AnthropicStreamCompletion does not carry guardrail_blocked / bypass_reason, so the metric can't be recorded at its emit point. As a result the counters undercount anthropic guardrail blocks/bypasses.
Fix: thread guardrail_blocked + bypass_reason through the messages.rs telemetry (closing the AnthropicStreamCompletion gap) and record_guardrail_outcome at its emit, OR record at the messages verdict sites. This naturally folds into the applied-guardrails telemetry-threading work (#379 observability "A" slice), which reworks guardrail telemetry uniformly across both paths.