import json,os,time,subprocess,urllib.request
from pathlib import Path
import yaml
os.umask(0o077)
root=Path(__file__).parent
def api(path):
    with urllib.request.urlopen('http://127.0.0.1:35000'+path,timeout=3) as r:return json.load(r)
def cmd(args,timeout=5):return subprocess.run(args,capture_output=True,text=True,timeout=timeout,check=True).stdout
def triton():
    code='''import json,urllib.request
models=['RFDETRMedium','RFDETRKeypointPreview','RFDETRFireSmoke','Awiros_person_and_head_detection']
out={}
for m in models:
 try:out[m]=json.load(urllib.request.urlopen('http://localhost:8000/v2/models/'+m+'/stats',timeout=2))['model_stats'][0]
 except Exception as e:out[m]={'error':type(e).__name__}
print(json.dumps(out))'''
    return json.loads(cmd(['docker','exec','contextra-analytics-1','python3','-B','-c',code],10))
specs=yaml.safe_load(Path('/data/contextra/runtime-state/streams_runtime.yaml').read_text())['added']
mapping={s['stream_id']:s.get('camera_id',s.get('source_id')) for s in specs}
begin=time.monotonic();samples=[]
tri0=triton()
docker0=json.loads(cmd(['docker','stats','--no-stream','--format','{{json .}}','contextra-analytics-1']))
start=time.monotonic()
for i in range(11):
    target=start+3*i
    if target>time.monotonic():time.sleep(target-time.monotonic())
    rows=api('/api/v1/streams')['streams']
    filtered=[]
    for r in rows:
        if r['state']=='stopped':continue
        filtered.append(dict(camera=mapping.get(r['stream_id']),
            **{k:r.get(k) for k in ('state','run_id','run_generation','child_pid','last_error','metadata_path')}))
    pub=api('/api/v1/metadata/status')
    samples.append(dict(t=time.monotonic(),channels=filtered,publisher=pub['metrics'],
        artifacts={k:pub['artifacts'].get(k) for k in ('active','rendering','counts','error','storage_warning')},
        gpu=cmd(['nvidia-smi','--query-gpu=utilization.gpu,utilization.memory,memory.used,memory.total,power.draw','--format=csv,noheader,nounits']).strip(),
        cpu=Path('/proc/stat').read_text().splitlines()[0],
        cpu_pressure=Path('/proc/pressure/cpu').read_text(),memory_pressure=Path('/proc/pressure/memory').read_text(),
        meminfo=[x for x in Path('/proc/meminfo').read_text().splitlines() if x.startswith(('MemAvailable:','SwapFree:','SwapTotal:'))]))
tri1=triton()
docker1=json.loads(cmd(['docker','stats','--no-stream','--format','{{json .}}','contextra-analytics-1']))
report=dict(samples=samples,triton_before=tri0,triton_after=tri1,docker_before=docker0,docker_after=docker1,
 cpu_cores=os.cpu_count(),elapsed_s=samples[-1]['t']-samples[0]['t'])
with (root/'observation.json').open('x') as f:json.dump(report,f,indent=2)
print(json.dumps(dict(elapsed_s=report['elapsed_s'],samples=len(samples),active_start=len(samples[0]['channels']),active_end=len(samples[-1]['channels']))),flush=True)
