feat(egress): replace log bool with integer log levels (0/1/2)
Level 0 (off, default): no stderr output beyond boot line. Level 1 (blocks): each block/warn emitted as JSON with reason and request context (host, method, path, response_status for inbound). Level 2 (full): level-1 events + egress_request and egress_response JSON lines for every forwarded connection. Block logging at level 1+ replaces the previous plain-text stderr write. DLP warn logging is also gated on level 1+. All block call sites now pass _req_ctx(flow) so the blocked request is visible in the log entry. Boot message shows log level label (off/blocks/full). Adds PRD 0053 documenting wire format, manifest format, and all log event shapes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,9 @@ from pathlib import Path
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
from bot_bottle.egress_addon_core import (
|
||||
LOG_BLOCKS,
|
||||
LOG_FULL,
|
||||
LOG_OFF,
|
||||
Config,
|
||||
Decision,
|
||||
HeaderMatch,
|
||||
@@ -278,23 +281,34 @@ class TestLoadRoutes(unittest.TestCase):
|
||||
|
||||
|
||||
class TestLoadConfig(unittest.TestCase):
|
||||
def test_log_defaults_to_false(self):
|
||||
def test_log_defaults_to_off(self):
|
||||
cfg = load_config('routes:\n - host: "api.example"\n')
|
||||
self.assertFalse(cfg.log)
|
||||
self.assertEqual(LOG_OFF, cfg.log)
|
||||
self.assertEqual(1, len(cfg.routes))
|
||||
|
||||
def test_log_true_parsed(self):
|
||||
cfg = load_config('log: true\nroutes:\n - host: "api.example"\n')
|
||||
self.assertTrue(cfg.log)
|
||||
self.assertEqual(1, len(cfg.routes))
|
||||
def test_log_level_1_parsed(self):
|
||||
cfg = load_config('log: 1\nroutes:\n - host: "api.example"\n')
|
||||
self.assertEqual(LOG_BLOCKS, cfg.log)
|
||||
|
||||
def test_log_false_explicit(self):
|
||||
cfg = load_config('log: false\nroutes:\n - host: "api.example"\n')
|
||||
self.assertFalse(cfg.log)
|
||||
def test_log_level_2_parsed(self):
|
||||
cfg = load_config('log: 2\nroutes:\n - host: "api.example"\n')
|
||||
self.assertEqual(LOG_FULL, cfg.log)
|
||||
|
||||
def test_log_non_bool_rejected(self):
|
||||
def test_log_level_0_explicit(self):
|
||||
cfg = load_config('log: 0\nroutes:\n - host: "api.example"\n')
|
||||
self.assertEqual(LOG_OFF, cfg.log)
|
||||
|
||||
def test_log_invalid_level_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
load_config('log: "yes"\nroutes: []\n')
|
||||
load_config('log: 3\nroutes: []\n')
|
||||
|
||||
def test_log_bool_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
load_config('log: true\nroutes: []\n')
|
||||
|
||||
def test_log_string_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
load_config('log: "full"\nroutes: []\n')
|
||||
|
||||
def test_routes_accessible_via_config(self):
|
||||
cfg = load_config('routes:\n - host: "x.example"\n')
|
||||
|
||||
Reference in New Issue
Block a user