feat: 集成阿里云日志服务(SLS)并增强日志记录详情
- 添加 SLS 日志上报模块(sls-logger.js) - 支持批量上报(每10条或5秒间隔) - 环境变量缺失时静默降级 - 自动重试失败的日志 - 新增日志信息提取器(log-extractor.js) - 提取 Token 使用统计(input_tokens, output_tokens) - 提取用户标识信息(user_id, session_id, ip) - 提取请求参数(temperature, max_tokens, stream) - 提取消息摘要(message_count, role_distribution, tool_names) - 增强所有 API 端点的日志记录 - /v1/chat/completions - /v1/responses - /v1/messages - /v1/messages/count_tokens - 修复日志字段序列化问题 - 扁平化嵌套对象字段,避免 [object Object] - 数组字段转换为逗号分隔字符串 - 添加阿里云环境变量配置到 docker-compose.yml - ALIYUN_ACCESS_KEY_ID - ALIYUN_ACCESS_KEY_SECRET - ALIYUN_SLS_ENDPOINT - ALIYUN_SLS_PROJECT - ALIYUN_SLS_LOGSTORE - 修改认证配置为自动刷新 Token 机制 - 使用 DROID_REFRESH_KEY 替代固定的 FACTORY_API_KEY - 实现每6小时自动刷新(Token有效期8小时) - Token 持久化到 auth.json
This commit is contained in:
117
routes.js
117
routes.js
@@ -10,6 +10,7 @@ import { OpenAIResponseTransformer } from './transformers/response-openai.js';
|
||||
import { getApiKey } from './auth.js';
|
||||
import { getNextProxyAgent } from './proxy-manager.js';
|
||||
import { logRequest as slsLogRequest } from './sls-logger.js';
|
||||
import { buildDetailedLog } from './log-extractor.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -189,7 +190,14 @@ async function handleChatCompletions(req, res) {
|
||||
}
|
||||
res.end();
|
||||
logInfo('Stream forwarded (common type)');
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/chat/completions', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/chat/completions',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req
|
||||
}));
|
||||
} catch (streamError) {
|
||||
logError('Stream error', streamError);
|
||||
res.end();
|
||||
@@ -209,7 +217,14 @@ async function handleChatCompletions(req, res) {
|
||||
}
|
||||
res.end();
|
||||
logInfo('Stream completed');
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/chat/completions', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/chat/completions',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req
|
||||
}));
|
||||
} catch (streamError) {
|
||||
logError('Stream error', streamError);
|
||||
res.end();
|
||||
@@ -232,12 +247,28 @@ async function handleChatCompletions(req, res) {
|
||||
logResponse(200, null, data);
|
||||
res.json(data);
|
||||
}
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/chat/completions', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/chat/completions',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
responseData: data
|
||||
}));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logError('Error in /v1/chat/completions', error);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/chat/completions', model: req.body?.model, status: 500, duration_ms: Date.now() - startTime, error: error.message });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/chat/completions',
|
||||
model: req.body?.model,
|
||||
status: 500,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
error: error.message
|
||||
}));
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: error.message
|
||||
@@ -394,7 +425,14 @@ async function handleDirectResponses(req, res) {
|
||||
}
|
||||
res.end();
|
||||
logInfo('Stream forwarded successfully');
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/responses', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/responses',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req
|
||||
}));
|
||||
} catch (streamError) {
|
||||
logError('Stream error', streamError);
|
||||
res.end();
|
||||
@@ -404,12 +442,28 @@ async function handleDirectResponses(req, res) {
|
||||
const data = await response.json();
|
||||
logResponse(200, null, data);
|
||||
res.json(data);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/responses', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/responses',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
responseData: data
|
||||
}));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logError('Error in /v1/responses', error);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/responses', model: req.body?.model, status: 500, duration_ms: Date.now() - startTime, error: error.message });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/responses',
|
||||
model: req.body?.model,
|
||||
status: 500,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
error: error.message
|
||||
}));
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: error.message
|
||||
@@ -631,7 +685,14 @@ async function handleDirectMessages(req, res) {
|
||||
}
|
||||
res.end();
|
||||
logInfo('Stream forwarded successfully');
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/messages', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/messages',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req
|
||||
}));
|
||||
} catch (streamError) {
|
||||
logError('Stream error', streamError);
|
||||
res.end();
|
||||
@@ -641,12 +702,28 @@ async function handleDirectMessages(req, res) {
|
||||
const data = await response.json();
|
||||
logResponse(200, null, data);
|
||||
res.json(data);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/messages', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/messages',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
responseData: data
|
||||
}));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logError('Error in /v1/messages', error);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/messages', model: req.body?.model, status: 500, duration_ms: Date.now() - startTime, error: error.message });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/messages',
|
||||
model: req.body?.model,
|
||||
status: 500,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
error: error.message
|
||||
}));
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: error.message
|
||||
@@ -743,11 +820,27 @@ async function handleCountTokens(req, res) {
|
||||
const data = await response.json();
|
||||
logResponse(200, null, data);
|
||||
res.json(data);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/messages/count_tokens', model: modelId, status: 200, duration_ms: Date.now() - startTime });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/messages/count_tokens',
|
||||
model: modelId,
|
||||
status: 200,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
responseData: data
|
||||
}));
|
||||
|
||||
} catch (error) {
|
||||
logError('Error in /v1/messages/count_tokens', error);
|
||||
slsLogRequest({ method: 'POST', endpoint: '/v1/messages/count_tokens', model: req.body?.model, status: 500, duration_ms: Date.now() - startTime, error: error.message });
|
||||
slsLogRequest(buildDetailedLog({
|
||||
method: 'POST',
|
||||
endpoint: '/v1/messages/count_tokens',
|
||||
model: req.body?.model,
|
||||
status: 500,
|
||||
duration_ms: Date.now() - startTime,
|
||||
req,
|
||||
error: error.message
|
||||
}));
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: error.message
|
||||
|
||||
Reference in New Issue
Block a user