runtime zmeny
This commit is contained in:
@@ -14,10 +14,16 @@ import json
|
||||
import sqlite3
|
||||
import sys
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
WORKSPACE = Path(__file__).resolve().parents[3]
|
||||
DB_PATH = WORKSPACE / "db" / "ollama_usage.sqlite"
|
||||
from ollama_usage import (
|
||||
DB_PATH,
|
||||
SESSION_BLOCK,
|
||||
Sample,
|
||||
fmt_countdown,
|
||||
is_window_reset,
|
||||
load_samples,
|
||||
window_rollovers,
|
||||
)
|
||||
|
||||
DEFAULT_WINDOW = timedelta(hours=24)
|
||||
GAP_MINUTES = 15
|
||||
@@ -37,14 +43,6 @@ def resolve_window(args: argparse.Namespace) -> tuple[str, str]:
|
||||
return since, until
|
||||
|
||||
|
||||
def load_samples(conn: sqlite3.Connection, since: str, until: str) -> list[tuple]:
|
||||
return conn.execute(
|
||||
"SELECT ts, session_usage, weekly_usage, session_models, weekly_models "
|
||||
"FROM samples WHERE ts >= ? AND ts <= ? ORDER BY ts",
|
||||
(since, until),
|
||||
).fetchall()
|
||||
|
||||
|
||||
def count_deltas(previous: dict[str, int], current: dict[str, int]) -> dict[str, int]:
|
||||
names = set(previous) | set(current)
|
||||
deltas = {n: current.get(n, 0) - previous.get(n, 0) for n in names}
|
||||
@@ -60,37 +58,56 @@ def minutes_between(earlier: str, later: str) -> float:
|
||||
return delta.total_seconds() / 60
|
||||
|
||||
|
||||
def is_window_reset(previous: tuple, current: tuple) -> bool:
|
||||
"""Session window rolled over: its usage or its request total went down."""
|
||||
previous_total = sum(json.loads(previous[3]).values())
|
||||
current_total = sum(json.loads(current[3]).values())
|
||||
return current[1] < previous[1] or current_total < previous_total
|
||||
|
||||
|
||||
def print_rows(samples: list[tuple]) -> dict[str, int]:
|
||||
def print_rows(samples: list[Sample]) -> dict[str, int]:
|
||||
total: dict[str, int] = {}
|
||||
for previous, current in itertools.pairwise(samples):
|
||||
gap = minutes_between(previous[0], current[0])
|
||||
gap = minutes_between(previous.ts, current.ts)
|
||||
if gap > GAP_MINUTES:
|
||||
print(f" … {gap:.0f} min with no recorded change (idle or poller down)")
|
||||
if is_window_reset(previous, current):
|
||||
print(" ── session window reset ──")
|
||||
|
||||
deltas = count_deltas(json.loads(previous[4]), json.loads(current[4]))
|
||||
deltas = count_deltas(json.loads(previous.weekly_models), json.loads(current.weekly_models))
|
||||
for name, count in deltas.items():
|
||||
total[name] = total.get(name, 0) + count
|
||||
print(
|
||||
f"{current[0]} session {current[1] * 100:5.1f} % "
|
||||
f"weekly {current[2] * 100:5.1f} % {format_deltas(deltas)}"
|
||||
f"{current.ts} session {current.session_usage * 100:5.1f} % "
|
||||
f"weekly {current.weekly_usage * 100:5.1f} % {format_deltas(deltas)}"
|
||||
)
|
||||
return total
|
||||
|
||||
|
||||
def print_summary(samples: list[tuple], total: dict[str, int]) -> None:
|
||||
def print_window(conn: sqlite3.Connection) -> None:
|
||||
"""The session window in progress, plus the gaps that test how it is anchored.
|
||||
|
||||
Consecutive rollovers exactly SESSION_BLOCK apart would mean a fixed grid;
|
||||
longer gaps mean the window is anchored by the first request after the
|
||||
previous one ran out, which is what the data so far shows.
|
||||
"""
|
||||
rollovers = window_rollovers(load_samples(conn))
|
||||
if not rollovers:
|
||||
print("Session window: no rollover recorded yet")
|
||||
return
|
||||
|
||||
for previous, current in itertools.pairwise(rollovers):
|
||||
gap = current - previous
|
||||
verdict = "= block" if gap == SESSION_BLOCK else "> block (window is request-anchored)"
|
||||
print(f"Rollover gap: {previous:%m-%d %H:%M} → {current:%m-%d %H:%M} = {fmt_countdown(gap)} {verdict}")
|
||||
|
||||
started = rollovers[-1].astimezone()
|
||||
ends = (rollovers[-1] + SESSION_BLOCK).astimezone()
|
||||
now = datetime.now(UTC)
|
||||
remaining = (
|
||||
f"in {fmt_countdown(ends - now)}" if ends > now else "expired; next window starts with the next request"
|
||||
)
|
||||
print(f"Session window: started {started:%m-%d %H:%M %Z}, ends {ends:%m-%d %H:%M %Z} ({remaining})")
|
||||
|
||||
|
||||
def print_summary(samples: list[Sample], total: dict[str, int]) -> None:
|
||||
first, last = samples[0], samples[-1]
|
||||
print()
|
||||
print(f"Window: {first[0]} → {last[0]} ({len(samples)} samples)")
|
||||
print(f"Weekly usage: {first[2] * 100:.1f} % → {last[2] * 100:.1f} %")
|
||||
print(f"Window: {first.ts} → {last.ts} ({len(samples)} samples)")
|
||||
print(f"Weekly usage: {first.weekly_usage * 100:.1f} % → {last.weekly_usage * 100:.1f} %")
|
||||
print(f"Requests: {format_deltas(total)}")
|
||||
|
||||
|
||||
@@ -116,6 +133,7 @@ def main() -> None:
|
||||
|
||||
total = print_rows(samples)
|
||||
print_summary(samples, total)
|
||||
print_window(conn)
|
||||
print_poll_status(conn)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user