chore: opt-in tracemalloc to attribute unclosed aiohttp sessions (#1657)

Prod logs show bursts of 'Unclosed client session' (aiohttp), leaking
fds + memory, but the warning omits the allocation site. When
DEBUG_TRACEMALLOC is set, start tracemalloc at webapp import so aiohttp
appends an 'Object allocated at' traceback naming the exact source.
Inert when the env var is unset.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit 320bb39ab1f5cd7a2acdac52c7b375854334176c)
This commit is contained in:
Johannes du Plessis 2026-06-30 17:59:56 -07:00 • committed by seahaven-openswe[bot]
parent 52798e8873
commit 5964a9f0d4

View file

@ -125,6 +125,26 @@ from .utils.slack_feedback import (
logger = logging.getLogger(__name__)
# Opt-in leak diagnostics. Bursts of aiohttp "Unclosed client session" warnings
# (from a third-party SDK) leak fds + memory in prod, but the warning omits the
# allocation site. With tracemalloc running, aiohttp appends an "Object allocated
# at" traceback to each warning, naming the exact source. Inert unless the env
# var is set, so this is safe to ship and flip on for one diagnostic run.
if os.environ.get("DEBUG_TRACEMALLOC"):
import tracemalloc
try:
_tracemalloc_frames = int(os.environ.get("DEBUG_TRACEMALLOC_FRAMES") or "25")
except ValueError:
_tracemalloc_frames = 25
tracemalloc.start(_tracemalloc_frames)
logger.warning(
"DEBUG_TRACEMALLOC enabled: tracemalloc started (%d frames) to attribute "
"unclosed-session warnings",
_tracemalloc_frames,
)
@asynccontextmanager
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
from .utils.model import validate_local_dev_llm_config