| | |
| | | import com.vincent.rsf.server.ai.entity.AiMcpCallLog; |
| | | import com.vincent.rsf.server.ai.mapper.AiCallLogMapper; |
| | | import com.vincent.rsf.server.ai.mapper.AiMcpCallLogMapper; |
| | | import com.vincent.rsf.server.ai.store.AiObserveStatsStore; |
| | | import com.vincent.rsf.server.ai.service.AiCallLogService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private static final Pattern BEARER_PATTERN = Pattern.compile("(?i)(bearer\\s+)([a-z0-9._-]+)"); |
| | | |
| | | private final AiMcpCallLogMapper aiMcpCallLogMapper; |
| | | private final AiObserveStatsStore aiObserveStatsStore; |
| | | |
| | | @Override |
| | | public AiCallLog startCallLog(String requestId, Long sessionId, Long userId, Long tenantId, String promptCode, |
| | |
| | | .setCreateTime(now) |
| | | .setUpdateTime(now); |
| | | this.save(callLog); |
| | | aiObserveStatsStore.recordObserveCallStarted(tenantId); |
| | | return callLog; |
| | | } |
| | | |
| | |
| | | .set(AiCallLog::getToolFailureCount, (int) toolFailureCount) |
| | | .set(AiCallLog::getToolCallCount, (int) (toolSuccessCount + toolFailureCount)) |
| | | .set(AiCallLog::getUpdateTime, new Date())); |
| | | AiCallLog latest = this.getById(callLogId); |
| | | if (latest != null) { |
| | | aiObserveStatsStore.recordObserveCallFinished(latest.getTenantId(), status, elapsedMs, firstTokenLatencyMs, totalTokens); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | .set(AiCallLog::getToolFailureCount, (int) toolFailureCount) |
| | | .set(AiCallLog::getToolCallCount, (int) (toolSuccessCount + toolFailureCount)) |
| | | .set(AiCallLog::getUpdateTime, new Date())); |
| | | AiCallLog latest = this.getById(callLogId); |
| | | if (latest != null) { |
| | | aiObserveStatsStore.recordObserveCallFinished(latest.getTenantId(), status, elapsedMs, firstTokenLatencyMs, null); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | .setUserId(userId) |
| | | .setTenantId(tenantId) |
| | | .setCreateTime(new Date())); |
| | | aiObserveStatsStore.recordObserveToolCall(tenantId, toolName, status); |
| | | } |
| | | |
| | | @Override |
| | | public AiObserveStatsDto getObserveStats(Long tenantId) { |
| | | return aiObserveStatsStore.getObserveStats(tenantId, () -> loadObserveStatsFromDatabase(tenantId)); |
| | | } |
| | | |
| | | private AiObserveStatsDto loadObserveStatsFromDatabase(Long tenantId) { |
| | | // 数据库聚合只作为 Redis 冷启动兜底,正常情况下看板应直接消费实时计数。 |
| | | List<AiCallLog> callLogs = this.list(new LambdaQueryWrapper<AiCallLog>() |
| | | .eq(AiCallLog::getTenantId, tenantId) |
| | | .eq(AiCallLog::getDeleted, 0) |