lpedro commited on
Commit
0eb29b9
·
1 Parent(s): 29f1059

main - Revert to card grid, remove logs section, fix colours

Browse files

Remove log section and row layout. Cards back with top colour border,
bright RSS colours (#4ade80 / #fbbf24 / #f87171), compact sizing (~85px
tall) to fit above HF logs panel. Header on one line to save vertical
space. JS polls /stats every 5s.

Files changed (1) hide show
  1. main.py +36 -58
main.py CHANGED
@@ -5,7 +5,7 @@ from fastapi.responses import HTMLResponse
5
 
6
  from models import RequestModel, ResponseModel
7
  from similarity import (
8
- check_similarity, get_all_memory_stats, get_log_lines,
9
  start_memory_stats_reporter, start_memory_trimmer,
10
  )
11
 
@@ -29,71 +29,49 @@ _PAGE = ("""<!DOCTYPE html><html><head>
29
  <link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@1,800&family=Inter:wght@400;500&display=swap" rel="stylesheet">
30
  <style>
31
  *{margin:0;padding:0;box-sizing:border-box}
32
- html,body{height:100%;overflow:hidden}
33
- body{background:#0d0d14;color:#e2e8f0;font-family:'Inter',system-ui,sans-serif;
34
- padding:1.1rem 1.5rem;display:flex;flex-direction:column;gap:.75rem}
35
  h1{font-family:'Barlow Condensed',sans-serif;font-weight:800;font-style:italic;
36
- font-size:1.85rem;color:#fff;letter-spacing:-.01em;line-height:1;display:inline}
37
- .meta{color:#6b7280;font-size:.7rem;font-family:'SF Mono','Fira Code',monospace;
38
- margin-left:.75rem}
39
- .meta b{color:#9ca3af}
40
- header{flex-shrink:0;padding-bottom:.6rem;border-bottom:1px solid #1a1a2e}
41
- .workers{flex-shrink:0;display:flex;flex-direction:column;gap:.2rem}
42
- .worker{display:grid;grid-template-columns:3.6rem 1fr 3rem 4.8rem;
43
- align-items:center;gap:.55rem;padding:.22rem .55rem;
44
- border-left:2px solid var(--c);background:#0f172a;border-radius:0 5px 5px 0}
45
- .pid{font-size:.65rem;color:#94a3b8;font-family:'SF Mono','Fira Code',monospace;
46
  text-transform:uppercase;letter-spacing:.06em}
47
- .track{background:#1a2235;border-radius:99px;height:3px;overflow:hidden}
48
- .fill{height:100%;border-radius:99px;background:#3b82f6;opacity:.7}
49
- .cn{font-size:.65rem;color:#94a3b8;text-align:right;white-space:nowrap}
50
- .rss{font-size:1rem;font-weight:700;font-family:'SF Mono','Fira Code',monospace;
51
- color:var(--c);text-align:right;white-space:nowrap}
52
- .log-wrap{flex:1;display:flex;flex-direction:column;min-height:0}
53
- .log-label{font-size:.56rem;color:#374151;text-transform:uppercase;
54
- letter-spacing:.1em;margin-bottom:.25rem;flex-shrink:0}
55
- .log-body{flex:1;overflow-y:auto;font-family:'SF Mono','Fira Code',monospace;
56
- font-size:.6rem;line-height:1.5;min-height:0}
57
- .log-body::-webkit-scrollbar{width:3px}
58
- .log-body::-webkit-scrollbar-thumb{background:#1f2937;border-radius:99px}
59
- .ln{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
60
- padding:.1rem 0;border-bottom:1px solid #0d1117}
61
- .ts{color:#64748b}.info{color:#60a5fa}.warning{color:#fbbf24}
62
- .error{color:#f87171}.msg{color:#cbd5e1}
63
- </style></head><body>
64
  <header>
65
- <h1>Prozis Similarity Service</h1><span id="meta" class="meta"></span>
 
66
  </header>
67
- <div id="workers" class="workers"></div>
68
- <div class="log-wrap">
69
- <div class="log-label">Logs</div>
70
- <div id="logs" class="log-body"></div>
71
- </div>
72
  <script>
73
  const MAX=__CACHE_MAX__;
74
- function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}
75
- function col(mb){return mb<800?'#22c55e':mb<1000?'#f59e0b':'#ef4444'}
76
- function render(d){
77
- const w=d.workers,gb=(w.reduce((s,x)=>s+x.rss_mb,0)/1024).toFixed(1);
78
  document.getElementById('meta').innerHTML=
79
- `<b>${w.length}</b> workers &nbsp;&middot;&nbsp; <b>${gb} GB</b> RSS &nbsp;&middot;&nbsp; ${new Date().toTimeString().slice(0,8)}`;
80
- document.getElementById('workers').innerHTML=w.map(x=>{
81
- const c=col(x.rss_mb),p=Math.min(100,x.cache_size/MAX*100).toFixed(0);
82
- return `<div class="worker" style="--c:${c}"><span class="pid">pid ${x.pid}</span>`+
83
- `<div class="track"><div class="fill" style="width:${p}%"></div></div>`+
84
- `<span class="cn">${x.cache_size}/${MAX}</span><span class="rss">${x.rss_mb} MB</span></div>`;
85
- }).join('');
86
- const lb=document.getElementById('logs');
87
- lb.innerHTML=d.logs.map(l=>{
88
- const m=l.match(/^(\S+) (\S+) ([\s\S]*)$/);
89
- if(!m) return `<div class="ln"><span class="msg">${esc(l)}</span></div>`;
90
- const [,ts,lvl,msg]=m;
91
- return `<div class="ln"><span class="ts">${esc(ts)}</span> `+
92
- `<span class="${lvl.toLowerCase()}">${esc(lvl)}</span> `+
93
- `<span class="msg">${esc(msg)}</span></div>`;
94
  }).join('');
95
  }
96
- async function refresh(){try{const r=await fetch('/stats');render(await r.json())}catch(e){}}
97
  refresh();setInterval(refresh,5000);
98
  </script>
99
  </body></html>""").replace("__CACHE_MAX__", str(_CACHE_MAX))
@@ -101,7 +79,7 @@ refresh();setInterval(refresh,5000);
101
 
102
  @app.get("/stats", include_in_schema=False)
103
  async def stats_endpoint():
104
- return {"workers": get_all_memory_stats(), "logs": get_log_lines()}
105
 
106
 
107
  @app.get("/", include_in_schema=False)
 
5
 
6
  from models import RequestModel, ResponseModel
7
  from similarity import (
8
+ check_similarity, get_all_memory_stats,
9
  start_memory_stats_reporter, start_memory_trimmer,
10
  )
11
 
 
29
  <link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@1,800&family=Inter:wght@400;500&display=swap" rel="stylesheet">
30
  <style>
31
  *{margin:0;padding:0;box-sizing:border-box}
32
+ body{background:#0d0d14;color:#e2e8f0;font-family:'Inter',system-ui,sans-serif;padding:.875rem 1.5rem}
33
+ header{display:flex;align-items:baseline;gap:1rem;margin-bottom:.75rem;
34
+ padding-bottom:.625rem;border-bottom:1px solid #1a1a2e}
35
  h1{font-family:'Barlow Condensed',sans-serif;font-weight:800;font-style:italic;
36
+ font-size:1.85rem;color:#fff;letter-spacing:-.01em;line-height:1}
37
+ .meta{color:#64748b;font-size:.72rem;font-family:'SF Mono','Fira Code',monospace}
38
+ .meta b{color:#94a3b8}
39
+ .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:.5rem}
40
+ .card{background:#111827;border:1px solid #1e2942;border-top:2px solid var(--c);
41
+ border-radius:8px;padding:.65rem .875rem}
42
+ .card-top{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:.45rem}
43
+ .pid{font-size:.62rem;color:#94a3b8;font-family:'SF Mono','Fira Code',monospace;
 
 
44
  text-transform:uppercase;letter-spacing:.06em}
45
+ .cn{font-size:.6rem;color:#64748b;font-family:'SF Mono','Fira Code',monospace}
46
+ .rss{font-size:1.5rem;font-weight:700;font-family:'SF Mono','Fira Code',monospace;
47
+ color:var(--c);line-height:1}
48
+ .unit{font-size:.6rem;color:#64748b;font-weight:400;margin-left:.15rem}
49
+ .track{height:3px;background:#1e2942;border-radius:99px;margin-top:.5rem;overflow:hidden}
50
+ .fill{height:100%;border-radius:99px;background:#3b82f6;opacity:.8}
51
+ </style>
52
+ </head><body>
 
 
 
 
 
 
 
 
 
53
  <header>
54
+ <h1>Prozis Similarity Service</h1>
55
+ <span id="meta" class="meta"></span>
56
  </header>
57
+ <div id="grid" class="grid"></div>
 
 
 
 
58
  <script>
59
  const MAX=__CACHE_MAX__;
60
+ function col(mb){return mb<800?'#4ade80':mb<1000?'#fbbf24':'#f87171'}
61
+ function render(workers){
62
+ const gb=(workers.reduce((s,w)=>s+w.rss_mb,0)/1024).toFixed(1);
 
63
  document.getElementById('meta').innerHTML=
64
+ `<b>${workers.length}</b> workers &nbsp;&middot;&nbsp; <b>${gb} GB</b> RSS &nbsp;&middot;&nbsp; ${new Date().toTimeString().slice(0,8)}`;
65
+ document.getElementById('grid').innerHTML=workers.map(w=>{
66
+ const c=col(w.rss_mb),p=Math.min(100,w.cache_size/MAX*100).toFixed(0);
67
+ return `<div class="card" style="--c:${c}">` +
68
+ `<div class="card-top"><span class="pid">pid ${w.pid}</span><span class="cn">${w.cache_size}/${MAX}</span></div>` +
69
+ `<div class="rss">${w.rss_mb}<span class="unit">MB</span></div>` +
70
+ `<div class="track"><div class="fill" style="width:${p}%"></div></div>` +
71
+ `</div>`;
 
 
 
 
 
 
 
72
  }).join('');
73
  }
74
+ async function refresh(){try{const r=await fetch('/stats');render((await r.json()).workers)}catch(e){}}
75
  refresh();setInterval(refresh,5000);
76
  </script>
77
  </body></html>""").replace("__CACHE_MAX__", str(_CACHE_MAX))
 
79
 
80
  @app.get("/stats", include_in_schema=False)
81
  async def stats_endpoint():
82
+ return {"workers": get_all_memory_stats()}
83
 
84
 
85
  @app.get("/", include_in_schema=False)