Summary
recost/_init.py registers no os.register_at_fork hooks. After a fork:
- The patched method-object references are inherited (fine — class attrs).
- The module-level
_handle global points at the parent's RecostHandle, but no timer thread is running in the child. Flushes never fire. Transport._local._loop references the parent's asyncio loop, which doesn't exist in the child. run_coroutine_threadsafe raises and is swallowed (_transport.py:195-197). All events queue silently and never send.
Symptom: every gunicorn pre-fork or Celery worker started after init() collects metrics into the void. Most production Python deployments use prefork servers — this is the single largest production gap.
Fix
Register os.register_at_fork(after_in_child=_reinit_after_fork) that re-creates the timer thread and transport thread in the child. Alternatively, document a "call init() in the worker's post_fork hook" pattern and refuse to instrument until init() has been called in the current PID.
Files
recost/_init.pyrecost/_transport.pyREADME.mdtests/test_init.py
Priority
P0 — silent total failure on the most common Python production deployment shape.
Summary
recost/_init.pyregisters noos.register_at_forkhooks. After a fork:_handleglobal points at the parent'sRecostHandle, but no timer thread is running in the child. Flushes never fire.Transport._local._loopreferences the parent's asyncio loop, which doesn't exist in the child.run_coroutine_threadsaferaises and is swallowed (_transport.py:195-197). All events queue silently and never send.Symptom: every gunicorn pre-fork or Celery worker started after
init()collects metrics into the void. Most production Python deployments use prefork servers — this is the single largest production gap.Fix
Register
os.register_at_fork(after_in_child=_reinit_after_fork)that re-creates the timer thread and transport thread in the child. Alternatively, document a "callinit()in the worker'spost_forkhook" pattern and refuse to instrument untilinit()has been called in the current PID.Files
recost/_init.pyrecost/_transport.pyREADME.mdtests/test_init.pyPriority
P0 — silent total failure on the most common Python production deployment shape.