feat(egress): add global log option for full request/response logging
Adds a top-level `log: true` option to the egress config that logs the full request (method, path, headers, body) and response (status, headers, body) for every forwarded connection as JSON lines on stderr. Wire format: `log: true` at the root of routes.yaml, parsed into the new `Config` dataclass alongside `routes`. The sidecar addon switches from `self.routes` to `self.config` and writes `_log_request` / `_log_response` JSON lines when `self.config.log` is set. Manifest: `egress.log: true` in bottle YAML flows through `EgressConfig.Log` → `Egress.prepare()` → `egress_render_routes(..., log=)` → routes.yaml. `EgressPlan` also carries the flag for introspection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ from pathlib import Path
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
from bot_bottle.egress_addon_core import (
|
||||
Config,
|
||||
Decision,
|
||||
HeaderMatch,
|
||||
MatchEntry,
|
||||
@@ -21,8 +22,10 @@ from bot_bottle.egress_addon_core import (
|
||||
decide,
|
||||
evaluate_matches,
|
||||
is_git_push_request,
|
||||
load_config,
|
||||
load_routes,
|
||||
match_route,
|
||||
parse_config,
|
||||
parse_routes,
|
||||
)
|
||||
|
||||
@@ -271,6 +274,34 @@ class TestLoadRoutes(unittest.TestCase):
|
||||
load_routes("routes:\n\t- host: x\n")
|
||||
|
||||
|
||||
# --- load_config / parse_config ------------------------------------------
|
||||
|
||||
|
||||
class TestLoadConfig(unittest.TestCase):
|
||||
def test_log_defaults_to_false(self):
|
||||
cfg = load_config('routes:\n - host: "api.example"\n')
|
||||
self.assertFalse(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_false_explicit(self):
|
||||
cfg = load_config('log: false\nroutes:\n - host: "api.example"\n')
|
||||
self.assertFalse(cfg.log)
|
||||
|
||||
def test_log_non_bool_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
load_config('log: "yes"\nroutes: []\n')
|
||||
|
||||
def test_routes_accessible_via_config(self):
|
||||
cfg = load_config('routes:\n - host: "x.example"\n')
|
||||
self.assertIsInstance(cfg, Config)
|
||||
self.assertEqual("x.example", cfg.routes[0].host)
|
||||
|
||||
|
||||
# --- evaluate_matches ---------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user