mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 22:17:00 +00:00
fix(admin): second review pass
Correctness - /api/remote never recorded source.created, so URL, GitHub and connector sources had a source.deleted with no matching creation. All three creation paths now go through one _audit_source_created helper. - The prompt-cache rate divided cached tokens by a whole bucket's prompt tokens. A bucket is a day and mixes calls whose provider reports a cache breakdown with calls whose provider does not, so filtering buckets in the client could not separate them and the rate was understated by however much traffic ran on a non-reporting provider. The denominator is now computed in SQL over the reporting rows. - The outcome pill matched values nothing writes. Guardrails emit triggered / not_evaluated and the device feed emits dispatched; the map had blocked / denied / allowed, so a guardrail that fired rendered neutral grey -- the one signal the merged feed exists to surface. Fixtures were seeding the fictional values, so the tests passed on it too. - Stream duration_ms timed the consumer. stream_token_usage is a generator, so start-to-exhaustion includes the agent loop's tool handling and the SSE client's pace; a slow browser recorded ~30s for a sub-second call. It now accumulates only the time spent inside next(). Safety - Activity filters failed open: an unknown facet or unparseable timestamp was dropped, and no filter means every row, so a typo widened an audit view and on the export streamed the full history. Both are now a 400. - The search term was interpolated into an ILIKE pattern, so "100%" matched everything and "q1_report" matched more than it should. Escaped. - 0034 set actor_id NOT NULL with no default. A previous-release process inserting mid-rollout would raise, and in admin/routes.py that insert shares the request transaction, so a role grant beside it would roll back too. Noise and dead code - The per-user panel is a security panel: data-plane events file under the actor, so an active account's routine deletes pushed a denied login out of the 20-row window. It now excludes them; the Activity tab shows everything. - device_audit_log had no created_at-leading index, so the merged feed sequentially scanned that branch every page (migration 0036). - conversation.deleted_all no longer records when nothing was deleted, and agent.updated no longer records an empty field list. - Dropped by_model from /admin/usage (no consumer; an extra aggregate per page load), the duplicate filter surface on AuthEventsRepository that nothing called, and the unreachable FLOW_LABELS.schedule entry. - Type hints on record_event's conn and the remaining unannotated helpers.
This commit is contained in:
1 parent
2ea9d66789
commit
25c82003d7
33 files changed
+635
-206
No files matched your search
+23
-4
@@ -305,12 +305,28 @@ def stream_token_usage(func):
|
||||
batch = []
|
||||
started_at = time.monotonic()
|
||||
first_chunk_at: float | None = None
|
||||
# Time spent waiting on the provider, accumulated across ``next()``
|
||||
# calls. The wall clock cannot be used here: this is a generator, so
|
||||
# every ``yield`` suspends until the consumer comes back, and the span
|
||||
# from start to exhaustion includes the agent loop's tool handling and
|
||||
# the SSE client's backpressure. A slow browser would otherwise record
|
||||
# 30s for a 900ms call, and latency_summary would mix that with true
|
||||
# non-streaming durations under one p50.
|
||||
provider_seconds = 0.0
|
||||
error: BaseException | None = None
|
||||
try:
|
||||
result = func(self, model, messages, stream, tools, **kwargs)
|
||||
for r in result:
|
||||
stream_iter = iter(result)
|
||||
while True:
|
||||
pull_started = time.monotonic()
|
||||
try:
|
||||
r = next(stream_iter)
|
||||
except StopIteration:
|
||||
provider_seconds += time.monotonic() - pull_started
|
||||
break
|
||||
provider_seconds += time.monotonic() - pull_started
|
||||
if first_chunk_at is None:
|
||||
first_chunk_at = time.monotonic()
|
||||
first_chunk_at = pull_started + provider_seconds
|
||||
batch.append(r)
|
||||
yield r
|
||||
except Exception as exc:
|
||||
@@ -320,7 +336,7 @@ def stream_token_usage(func):
|
||||
error = exc
|
||||
raise
|
||||
finally:
|
||||
duration_ms = int((time.monotonic() - started_at) * 1000)
|
||||
duration_ms = int(provider_seconds * 1000)
|
||||
# NULL, not 0, when the stream failed before yielding: "no first
|
||||
# token" must not read as an instant one in a p50.
|
||||
ttft_ms = (
|
||||
@@ -343,7 +359,10 @@ def stream_token_usage(func):
|
||||
model,
|
||||
prompt_tokens=call_usage["prompt_tokens"],
|
||||
completion_tokens=call_usage["generated_tokens"],
|
||||
latency_ms=duration_ms,
|
||||
# The log line has always meant end-to-end wall clock
|
||||
# for the streamed response; only the persisted column
|
||||
# isolates provider time.
|
||||
latency_ms=int((time.monotonic() - started_at) * 1000),
|
||||
cached_tokens=call_usage.get("cached_tokens"),
|
||||
cache_write_tokens=call_usage.get("cache_write_tokens"),
|
||||
error=error,
|
||||
|
||||
Reference in new issue
Block a user