11# -*- coding: utf-8 -*-
2- """Benchmark the request-logging masking Rust sidecar against the Python path."""
2+ """Benchmark the request-logging masking Rust native extension against the Python path."""
33
44# Standard
55from __future__ import annotations
66
7+ from contextlib import contextmanager
78import importlib
89import statistics
910import subprocess
1213from typing import Any , Callable
1314
1415# First-Party
16+ import mcpgateway .middleware .request_logging_middleware as request_logging_middleware
1517from mcpgateway .config import settings
1618from mcpgateway .middleware .request_logging_middleware import mask_sensitive_data , mask_sensitive_headers
1719
@@ -24,7 +26,36 @@ def _ensure_sidecar_installed() -> Any:
2426 return importlib .import_module ("request_logging_masking_sidecar" )
2527
2628
29+ def test_reset_rust_module_handle_keeps_flagged_masking_reloadable () -> None :
30+ _ensure_sidecar_installed ()
31+ request_logging_middleware ._RUST_REQUEST_LOGGING_MODULE = object ()
32+
33+ _reset_rust_module_handle ()
34+
35+ with _rust_masking_enabled (True ):
36+ masked = mask_sensitive_data ({"password" : "secret" }, 12 ) # pragma: allowlist secret
37+
38+ assert masked == {"password" : "******" } # pragma: allowlist secret
39+
40+
41+ @contextmanager
42+ def _rust_masking_enabled (enabled : bool ):
43+ original = settings .experimental_rust_request_logging_masking_enabled
44+ settings .experimental_rust_request_logging_masking_enabled = enabled
45+ try :
46+ yield
47+ finally :
48+ settings .experimental_rust_request_logging_masking_enabled = original
49+
50+
51+ def _reset_rust_module_handle () -> None :
52+ request_logging_middleware ._RUST_REQUEST_LOGGING_MODULE = None
53+
54+
2755def _measure (label : str , fn : Callable [[Any ], Any ], payload : Any , iterations : int ) -> tuple [float , float ]:
56+ for _ in range (5 ):
57+ fn (payload )
58+
2859 samples = []
2960 for _ in range (iterations ):
3061 started = time .perf_counter_ns ()
@@ -37,6 +68,24 @@ def _measure(label: str, fn: Callable[[Any], Any], payload: Any, iterations: int
3768 return median_ms , p95_ms
3869
3970
71+ def _measure_once (label : str , fn : Callable [[Any ], Any ], payload : Any ) -> float :
72+ started = time .perf_counter_ns ()
73+ fn (payload )
74+ elapsed_ms = (time .perf_counter_ns () - started ) / 1_000_000
75+ print (f"{ label } : elapsed={ elapsed_ms :.3f} ms" )
76+ return elapsed_ms
77+
78+
79+ def _run_with_rust_masking_enabled (enabled : bool , fn : Callable [[Any ], Any ], payload : Any ) -> Any :
80+ with _rust_masking_enabled (enabled ):
81+ return fn (payload )
82+
83+
84+ def _measure_with_rust_masking_enabled (enabled : bool , label : str , fn : Callable [[Any ], Any ], payload : Any , iterations : int ) -> tuple [float , float ]:
85+ with _rust_masking_enabled (enabled ):
86+ return _measure (label , fn , payload , iterations )
87+
88+
4089def _assert_parity (python_fn : Callable [[Any ], Any ], rust_fn : Callable [[Any ], Any ], payloads : list [Any ]) -> None :
4190 for payload in payloads :
4291 python_result = python_fn (payload )
@@ -47,29 +96,36 @@ def _assert_parity(python_fn: Callable[[Any], Any], rust_fn: Callable[[Any], Any
4796
4897def main () -> None :
4998 sidecar = _ensure_sidecar_installed ()
50- settings . experimental_rust_request_logging_masking_enabled = False
99+ request_logging_middleware . _RUST_REQUEST_LOGGING_MODULE = sidecar
51100
52101 def python_data (payload : Any ) -> Any :
53102 return mask_sensitive_data (payload , 12 )
54103
55104 def rust_data (payload : Any ) -> Any :
56- return sidecar .mask_sensitive_data (payload , 12 )
105+ return mask_sensitive_data (payload , 12 )
106+
107+ def python_headers (payload : Any ) -> Any :
108+ return mask_sensitive_headers (payload )
109+
110+ def rust_headers (payload : Any ) -> Any :
111+ return mask_sensitive_headers (payload )
57112
58- python_headers = mask_sensitive_headers
59- rust_headers = sidecar .mask_sensitive_headers
113+ # Warm the lazy import path once so the benchmark measures steady-state masking work.
114+ _run_with_rust_masking_enabled (True , rust_data , {"warmupToken" : "warmup" })
115+ _run_with_rust_masking_enabled (True , rust_headers , {"Authorization" : "Bearer warmup" })
60116
61117 _assert_parity (
62- python_data ,
63- rust_data ,
118+ lambda payload : _run_with_rust_masking_enabled ( False , python_data , payload ) ,
119+ lambda payload : _run_with_rust_masking_enabled ( True , rust_data , payload ) ,
64120 [
65121 {"password" : "secret" , "nested" : {"authToken" : "abc" , "ok" : "value" }},
66122 {"token_count" : 3 , "tokenizer" : "ok" , "privateKey" : "secret" },
67123 [{"jwt_token" : "abc" }, {"normal" : "value" }],
68124 ],
69125 )
70126 _assert_parity (
71- python_headers ,
72- rust_headers ,
127+ lambda payload : _run_with_rust_masking_enabled ( False , python_headers , payload ) ,
128+ lambda payload : _run_with_rust_masking_enabled ( True , rust_headers , payload ) ,
73129 [
74130 {"Authorization" : "Bearer abc" , "Cookie" : "jwt_token=abc; theme=dark" , "X-Trace-Id" : "123" },
75131 {"X-Auth-Count" : "5" , "X-Api-Key" : "secret" },
@@ -110,8 +166,12 @@ def rust_data(payload: Any) -> Any:
110166
111167 for name , python_fn , rust_fn , payload , iterations in scenarios :
112168 print (f"\n { name } ({ iterations } iterations)" )
113- python_median , _ = _measure ("python" , python_fn , payload , iterations )
114- rust_median , _ = _measure ("rust" , rust_fn , payload , iterations )
169+ _reset_rust_module_handle ()
170+ with _rust_masking_enabled (True ):
171+ _measure_once ("rust first_public_call" , rust_fn , payload )
172+ _measure_once ("rust warmup" , rust_fn , payload )
173+ python_median , _ = _measure_with_rust_masking_enabled (False , "python" , python_fn , payload , iterations )
174+ rust_median , _ = _measure_with_rust_masking_enabled (True , "rust-public-api" , rust_fn , payload , iterations )
115175 print (f"speedup={ python_median / rust_median :.2f} x" )
116176
117177
0 commit comments