mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
feat(trace): 在请求链路追踪中记录并展示首字时间(TTFB)
将 first_byte_time_ms 添加到候选记录的 extra_data 中, 并在前端时间线组件中展示该指标。
This commit is contained in:
@@ -175,6 +175,13 @@
|
|||||||
{{ currentAttempt.finished_at ? formatTime(currentAttempt.finished_at) : '进行中' }}
|
{{ currentAttempt.finished_at ? formatTime(currentAttempt.finished_at) : '进行中' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="currentAttempt.extra_data?.first_byte_time_ms != null"
|
||||||
|
class="info-item"
|
||||||
|
>
|
||||||
|
<span class="info-label">首字 (TTFB)</span>
|
||||||
|
<span class="info-value mono">{{ formatLatency(currentAttempt.extra_data.first_byte_time_ms) }}</span>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="currentAttempt.key_name || currentAttempt.key_id"
|
v-if="currentAttempt.key_name || currentAttempt.key_id"
|
||||||
class="info-item"
|
class="info-item"
|
||||||
|
|||||||
@@ -1438,6 +1438,13 @@ class CliMessageHandlerBase(BaseMessageHandler):
|
|||||||
if ctx.status_code and ctx.status_code >= 400:
|
if ctx.status_code and ctx.status_code >= 400:
|
||||||
# 请求链路追踪使用 upstream_response(原始响应),回退到 error_message(友好消息)
|
# 请求链路追踪使用 upstream_response(原始响应),回退到 error_message(友好消息)
|
||||||
trace_error_message = ctx.upstream_response or ctx.error_message or f"HTTP {ctx.status_code}"
|
trace_error_message = ctx.upstream_response or ctx.error_message or f"HTTP {ctx.status_code}"
|
||||||
|
extra_data = {
|
||||||
|
"stream_completed": False,
|
||||||
|
"chunk_count": ctx.chunk_count,
|
||||||
|
"data_count": ctx.data_count,
|
||||||
|
}
|
||||||
|
if ctx.first_byte_time_ms is not None:
|
||||||
|
extra_data["first_byte_time_ms"] = ctx.first_byte_time_ms
|
||||||
RequestCandidateService.mark_candidate_failed(
|
RequestCandidateService.mark_candidate_failed(
|
||||||
db=bg_db,
|
db=bg_db,
|
||||||
candidate_id=ctx.attempt_id,
|
candidate_id=ctx.attempt_id,
|
||||||
@@ -1447,23 +1454,22 @@ class CliMessageHandlerBase(BaseMessageHandler):
|
|||||||
error_message=trace_error_message,
|
error_message=trace_error_message,
|
||||||
status_code=ctx.status_code,
|
status_code=ctx.status_code,
|
||||||
latency_ms=response_time_ms,
|
latency_ms=response_time_ms,
|
||||||
extra_data={
|
extra_data=extra_data,
|
||||||
"stream_completed": False,
|
|
||||||
"chunk_count": ctx.chunk_count,
|
|
||||||
"data_count": ctx.data_count,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
extra_data = {
|
||||||
|
"stream_completed": True,
|
||||||
|
"chunk_count": ctx.chunk_count,
|
||||||
|
"data_count": ctx.data_count,
|
||||||
|
}
|
||||||
|
if ctx.first_byte_time_ms is not None:
|
||||||
|
extra_data["first_byte_time_ms"] = ctx.first_byte_time_ms
|
||||||
RequestCandidateService.mark_candidate_success(
|
RequestCandidateService.mark_candidate_success(
|
||||||
db=bg_db,
|
db=bg_db,
|
||||||
candidate_id=ctx.attempt_id,
|
candidate_id=ctx.attempt_id,
|
||||||
status_code=ctx.status_code,
|
status_code=ctx.status_code,
|
||||||
latency_ms=response_time_ms,
|
latency_ms=response_time_ms,
|
||||||
extra_data={
|
extra_data=extra_data,
|
||||||
"stream_completed": True,
|
|
||||||
"chunk_count": ctx.chunk_count,
|
|
||||||
"data_count": ctx.data_count,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -241,16 +241,20 @@ class StreamTelemetryRecorder:
|
|||||||
|
|
||||||
from src.services.request.candidate import RequestCandidateService
|
from src.services.request.candidate import RequestCandidateService
|
||||||
|
|
||||||
|
extra_data: Dict[str, Any] = {
|
||||||
|
"stream_completed": ctx.is_success(),
|
||||||
|
"data_count": ctx.data_count,
|
||||||
|
}
|
||||||
|
if ctx.first_byte_time_ms is not None:
|
||||||
|
extra_data["first_byte_time_ms"] = ctx.first_byte_time_ms
|
||||||
|
|
||||||
if ctx.is_success():
|
if ctx.is_success():
|
||||||
RequestCandidateService.mark_candidate_success(
|
RequestCandidateService.mark_candidate_success(
|
||||||
db=db,
|
db=db,
|
||||||
candidate_id=ctx.attempt_id,
|
candidate_id=ctx.attempt_id,
|
||||||
status_code=ctx.status_code,
|
status_code=ctx.status_code,
|
||||||
latency_ms=response_time_ms,
|
latency_ms=response_time_ms,
|
||||||
extra_data={
|
extra_data=extra_data,
|
||||||
"stream_completed": True,
|
|
||||||
"data_count": ctx.data_count,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
error_type = "client_disconnected" if ctx.status_code == 499 else "stream_error"
|
error_type = "client_disconnected" if ctx.status_code == 499 else "stream_error"
|
||||||
@@ -263,10 +267,7 @@ class StreamTelemetryRecorder:
|
|||||||
error_message=trace_error_message,
|
error_message=trace_error_message,
|
||||||
status_code=ctx.status_code,
|
status_code=ctx.status_code,
|
||||||
latency_ms=response_time_ms,
|
latency_ms=response_time_ms,
|
||||||
extra_data={
|
extra_data=extra_data,
|
||||||
"stream_completed": False,
|
|
||||||
"data_count": ctx.data_count,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _update_usage_status_on_error(
|
async def _update_usage_status_on_error(
|
||||||
|
|||||||
Reference in New Issue
Block a user