@faapi/faapi 6.7.0 → 6.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +196 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +43 -3
- package/dist/index.js +186 -4
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-CsL7xtqu.d.ts → routeTypes-J5pPbjwR.d.ts} +104 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +97 -1
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AppRegistries, R as RouteManifest, F as FaapiContext, C as CorsOptions, T as TaskClient, H as HelmetOptions, L as LoggerOptions, a as FaapiMiddleware, I as InjectorMap,
|
|
2
|
-
export {
|
|
1
|
+
import { A as AppRegistries, R as RouteManifest, F as FaapiContext, C as CorsOptions, T as TaskClient, H as HelmetOptions, L as LoggerOptions, a as LogConfig, b as FaapiMiddleware, I as InjectorMap, c as TaskFailedHandler, d as TaskQueueDeps, e as TaskQueue, f as TaskDriver, g as TaskRegistry, h as TaskManifest, i as ToolMetadata, j as AgentCore, k as AgentMetadata, l as CreateLoggerOptions, m as Logger, W as WsRouteManifest } from './routeTypes-J5pPbjwR.js';
|
|
2
|
+
export { n as AgentHandleFactory, o as AgentHandleStore, p as AgentPathMeta, q as AgentRegistry, r as AgentToolDescriptor, s as FaapiContextConfig, t as FaapiTaskMeta, u as FailOptions, v as Injector, w as LogEntry, x as LogLevel, y as LogSink, z as RouteInfo, B as RouteInputSchema, D as RouteOutputSchema, E as RouteParamSchema, S as SkillRegistry, G as SseEvent, J as SseWriter, K as TaskContext, M as TaskDriverJob, N as TaskDriverProcess, O as TaskDriverRecord, P as TaskFailedInfo, Q as TaskJob, U as TaskJobStatus, V as TaskMetadata, X as TaskModule, Y as TaskRegistriesSnapshot, Z as TaskRegistriesView, _ as ToolCore, $ as ToolPathMeta, a0 as ToolRegistry, a1 as cors, a2 as createAppRegistries, a3 as createTaskRegistriesView, a4 as createTaskRegistry, a5 as helmet, a6 as logger } from './routeTypes-J5pPbjwR.js';
|
|
3
3
|
import * as node_http from 'node:http';
|
|
4
4
|
import { Server, IncomingMessage, ServerResponse } from 'node:http';
|
|
5
5
|
import { Socket } from 'node:net';
|
|
@@ -552,6 +552,26 @@ interface FaapiConfig {
|
|
|
552
552
|
bodyLimit?: number;
|
|
553
553
|
/** 日志中间件配置 */
|
|
554
554
|
logger?: LoggerOptions | boolean;
|
|
555
|
+
/**
|
|
556
|
+
* 业务日志器全局配置(与 `logger` 请求日志中间件是两条独立管道,详见 logger/logger.md)
|
|
557
|
+
*
|
|
558
|
+
* - `false`:完全静默(含 error,测试降噪)
|
|
559
|
+
* - `true` / 缺省:默认级别(显式 level > LOG_LEVEL env > 'info')+ console 文本输出
|
|
560
|
+
* - `LogConfig`:精细配置 level 与 sink(sink 可整体接管接 pino/winston/文件)
|
|
561
|
+
*
|
|
562
|
+
* 生效范围:`ctx.log` / 参数注入 `log` / `createLogger` / `taskCtx.log`。
|
|
563
|
+
* 日志全局配置是进程级资源,多 app 同进程时后启动覆盖先启动。
|
|
564
|
+
*
|
|
565
|
+
* ```ts
|
|
566
|
+
* export default {
|
|
567
|
+
* log: {
|
|
568
|
+
* level: 'debug',
|
|
569
|
+
* sink: (entry) => pinoLogger[entry.level]({ scope: entry.scope, ...entry.fields }, entry.message),
|
|
570
|
+
* },
|
|
571
|
+
* } satisfies FaapiConfig;
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
574
|
+
log?: LogConfig | boolean;
|
|
555
575
|
/** HTTP/2 配置,false 禁用(默认 http/1.1) */
|
|
556
576
|
http2?: Http2Options | boolean;
|
|
557
577
|
/**
|
|
@@ -1466,6 +1486,26 @@ declare function loadConfig(rootDir: string, dist: string): Promise<Partial<Faap
|
|
|
1466
1486
|
*/
|
|
1467
1487
|
declare function loadEnv(rootDir: string): void;
|
|
1468
1488
|
|
|
1489
|
+
/**
|
|
1490
|
+
* 设置全局日志配置(进程级,`createAppBase` 启动时以 `config.log` 调用)
|
|
1491
|
+
*
|
|
1492
|
+
* - `false`:完全静默(含 error,测试降噪场景)
|
|
1493
|
+
* - `true` / `{}`:默认级别(显式 level > LOG_LEVEL env > 'info')+ 默认 console sink
|
|
1494
|
+
* - `{ level, sink }`:精细配置;非法 level 抛错(启动期 fail fast)
|
|
1495
|
+
* - `undefined`:重置为默认(编程式多 app 切换全局配置用)
|
|
1496
|
+
*
|
|
1497
|
+
* LOG_LEVEL env 仅在本函数读取——app 启动路径必经此处(env 非法在启动期报错);
|
|
1498
|
+
* 纯编程式不调本函数时 env 不生效(默认 info)。
|
|
1499
|
+
*/
|
|
1500
|
+
declare function configureLogging(config?: LogConfig | boolean | undefined): void;
|
|
1501
|
+
/**
|
|
1502
|
+
* 创建日志器
|
|
1503
|
+
*
|
|
1504
|
+
* @param scope 分类标签(如 'db'、'http'),默认无分类
|
|
1505
|
+
* @param options 实例级覆盖(level/sink/构造 fields)
|
|
1506
|
+
*/
|
|
1507
|
+
declare function createLogger(scope?: string, options?: CreateLoggerOptions): Logger;
|
|
1508
|
+
|
|
1469
1509
|
declare const VALIDATION_ERROR = "VALIDATION_ERROR";
|
|
1470
1510
|
declare const ROUTE_NOT_FOUND = "ROUTE_NOT_FOUND";
|
|
1471
1511
|
declare const METHOD_NOT_ALLOWED = "METHOD_NOT_ALLOWED";
|
|
@@ -1666,4 +1706,4 @@ type ProdApp = AppBase;
|
|
|
1666
1706
|
*/
|
|
1667
1707
|
declare function createProdApp(options?: CreateAppOptions): Promise<ProdApp>;
|
|
1668
1708
|
|
|
1669
|
-
export { type AgentConfig, AgentCore, AgentMetadata, type AgentModule, type ProdApp as App, AppRegistries, CorsOptions, type CreateAppOptions, type CronScheduler, type DevApp, type FaapiConfig, FaapiContext, FaapiError, FaapiMiddleware, type FaapiPlugin, type HandlerTypeInfo, HelmetOptions, type InjectOptions, type InjectResponse, InjectorMap, InternalError, type LifecycleContext, type LifecycleHooks, type LlmConfig, type LlmModelConfig, LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type ResponseConfig, RouteManifest, RouteNotFoundError, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, TASK_PATTERNS, type TaskBullMqOptions, TaskClient, type TaskConfig, TaskDriver, TaskFailedHandler, TaskManifest, type TaskPgBossOptions, TaskQueue, TaskRegistry, ToolMetadata, type ToolModule, type ToolSchemaModule, type TypeConstraint, type UpgradeHandler, ValidationError, type ValidationErrorCode, type ValidationIssue, type WsContext, type WsEventHandlers, type WsHandler, type WsSocket, clearAgentHandleFactory, collectRouteSchemaSources, createProdApp as createApp, createCronScheduler, createDevApp, createProdApp, createProgram, createPrograms, createTaskQueue, extractTypeInfo, getAgent, getAgentEntry, getApp, getInputTypeForMethod, getSkill, getTool, getToolSchemaPath, hydrateSkillRegistry, invalidateProgramCache, listSkills, loadAgentModule, loadConfig, loadEnv, loadTaskDriver, loadToolModule, loadToolSchema, registerAgentHandleFactory, removeSkill, resolveAgentTools, resolveSubAgents, resolveTypeNode, scanTasks, upsertSkill };
|
|
1709
|
+
export { type AgentConfig, AgentCore, AgentMetadata, type AgentModule, type ProdApp as App, AppRegistries, CorsOptions, type CreateAppOptions, CreateLoggerOptions, type CronScheduler, type DevApp, type FaapiConfig, FaapiContext, FaapiError, FaapiMiddleware, type FaapiPlugin, type HandlerTypeInfo, HelmetOptions, type InjectOptions, type InjectResponse, InjectorMap, InternalError, type LifecycleContext, type LifecycleHooks, type LlmConfig, type LlmModelConfig, LogConfig, Logger, LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type ResponseConfig, RouteManifest, RouteNotFoundError, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, TASK_PATTERNS, type TaskBullMqOptions, TaskClient, type TaskConfig, TaskDriver, TaskFailedHandler, TaskManifest, type TaskPgBossOptions, TaskQueue, TaskRegistry, ToolMetadata, type ToolModule, type ToolSchemaModule, type TypeConstraint, type UpgradeHandler, ValidationError, type ValidationErrorCode, type ValidationIssue, type WsContext, type WsEventHandlers, type WsHandler, type WsSocket, clearAgentHandleFactory, collectRouteSchemaSources, configureLogging, createProdApp as createApp, createCronScheduler, createDevApp, createLogger, createProdApp, createProgram, createPrograms, createTaskQueue, extractTypeInfo, getAgent, getAgentEntry, getApp, getInputTypeForMethod, getSkill, getTool, getToolSchemaPath, hydrateSkillRegistry, invalidateProgramCache, listSkills, loadAgentModule, loadConfig, loadEnv, loadTaskDriver, loadToolModule, loadToolSchema, registerAgentHandleFactory, removeSkill, resolveAgentTools, resolveSubAgents, resolveTypeNode, scanTasks, upsertSkill };
|
package/dist/index.js
CHANGED
|
@@ -1122,8 +1122,10 @@ var init_resolveInjection = __esm({
|
|
|
1122
1122
|
// Phase 2.3
|
|
1123
1123
|
agents: "agents",
|
|
1124
1124
|
// Phase 2.3
|
|
1125
|
-
tasks: "tasks"
|
|
1125
|
+
tasks: "tasks",
|
|
1126
1126
|
// 任务子系统:TaskClient(入队/查询)
|
|
1127
|
+
log: "log"
|
|
1128
|
+
// 请求级日志器(ctx.log 同一实例:scope http,自动带 requestId 等字段)
|
|
1127
1129
|
};
|
|
1128
1130
|
injectionCache = /* @__PURE__ */ new WeakMap();
|
|
1129
1131
|
}
|
|
@@ -2066,6 +2068,36 @@ function serializeError(err) {
|
|
|
2066
2068
|
return { name: 'Error', message: String(err), stack: undefined, props: {} };
|
|
2067
2069
|
}
|
|
2068
2070
|
`;
|
|
2071
|
+
var BUILD_LOGGER_SOURCE = `
|
|
2072
|
+
var LOG_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2073
|
+
function createTaskLogger(level, scope, fields) {
|
|
2074
|
+
function make(suffix) {
|
|
2075
|
+
function write(lvl, message, callFields) {
|
|
2076
|
+
if (LOG_RANK[lvl] < LOG_RANK[level]) return;
|
|
2077
|
+
var entry = { level: lvl, message: message, time: new Date().toISOString() };
|
|
2078
|
+
var fullScope = suffix === undefined ? scope : scope === undefined ? suffix : scope + ':' + suffix;
|
|
2079
|
+
if (fullScope !== undefined) entry.scope = fullScope;
|
|
2080
|
+
if (fields !== undefined || callFields !== undefined) {
|
|
2081
|
+
entry.fields = Object.assign({}, fields, callFields);
|
|
2082
|
+
}
|
|
2083
|
+
try {
|
|
2084
|
+
parentPort.postMessage({ type: 'log', entry: entry });
|
|
2085
|
+
} catch (_) {
|
|
2086
|
+
entry.fields = { warning: 'log fields not cloneable across worker boundary, dropped' };
|
|
2087
|
+
parentPort.postMessage({ type: 'log', entry: entry });
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
return {
|
|
2091
|
+
debug: function (m, f) { write('debug', m, f); },
|
|
2092
|
+
info: function (m, f) { write('info', m, f); },
|
|
2093
|
+
warn: function (m, f) { write('warn', m, f); },
|
|
2094
|
+
error: function (m, f) { write('error', m, f); },
|
|
2095
|
+
child: function (cs) { return make(suffix === undefined ? cs : suffix + ':' + cs); },
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
return make(undefined);
|
|
2099
|
+
}
|
|
2100
|
+
`;
|
|
2069
2101
|
function buildWrapperSource(moduleUrl) {
|
|
2070
2102
|
return `
|
|
2071
2103
|
import { parentPort } from 'node:worker_threads';
|
|
@@ -2075,6 +2107,8 @@ ${BUILD_VIEW_SOURCE}
|
|
|
2075
2107
|
|
|
2076
2108
|
${SERIALIZE_ERROR_SOURCE}
|
|
2077
2109
|
|
|
2110
|
+
${BUILD_LOGGER_SOURCE}
|
|
2111
|
+
|
|
2078
2112
|
const run = mod.run;
|
|
2079
2113
|
if (typeof run !== 'function') {
|
|
2080
2114
|
parentPort.postMessage({
|
|
@@ -2094,7 +2128,8 @@ if (typeof run !== 'function') {
|
|
|
2094
2128
|
try {
|
|
2095
2129
|
const registries = buildRegistriesView(msg.registries);
|
|
2096
2130
|
const progress = (value) => parentPort.postMessage({ type: 'progress', value });
|
|
2097
|
-
const
|
|
2131
|
+
const taskLog = msg.log ? createTaskLogger(msg.log.level, msg.log.scope, msg.log.fields) : undefined;
|
|
2132
|
+
const result = await run(payload, { ...taskCtx, signal: controller.signal, registries, progress, log: taskLog });
|
|
2098
2133
|
parentPort.postMessage({ type: 'done', result });
|
|
2099
2134
|
} catch (err) {
|
|
2100
2135
|
const serialized = serializeError(err);
|
|
@@ -2202,6 +2237,8 @@ async function runTaskInWorker(options) {
|
|
|
2202
2237
|
finish(() => reject(reviveError(msg.error)));
|
|
2203
2238
|
} else if (msg?.type === "progress") {
|
|
2204
2239
|
options.onProgress?.(msg.value);
|
|
2240
|
+
} else if (msg?.type === "log") {
|
|
2241
|
+
options.onLog?.(msg.entry);
|
|
2205
2242
|
}
|
|
2206
2243
|
}
|
|
2207
2244
|
);
|
|
@@ -2225,7 +2262,8 @@ async function runTaskInWorker(options) {
|
|
|
2225
2262
|
type: "run",
|
|
2226
2263
|
payload,
|
|
2227
2264
|
taskCtx: { config: safeConfig(taskCtx.config), job: taskCtx.job },
|
|
2228
|
-
registries: options.registries
|
|
2265
|
+
registries: options.registries,
|
|
2266
|
+
log: options.log
|
|
2229
2267
|
});
|
|
2230
2268
|
} catch (err) {
|
|
2231
2269
|
finish(
|
|
@@ -2237,6 +2275,118 @@ async function runTaskInWorker(options) {
|
|
|
2237
2275
|
});
|
|
2238
2276
|
}
|
|
2239
2277
|
|
|
2278
|
+
// src/logger/logger.ts
|
|
2279
|
+
var LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2280
|
+
var VALID_LEVELS = ["debug", "info", "warn", "error"];
|
|
2281
|
+
function assertLogLevel(value, source) {
|
|
2282
|
+
if (typeof value !== "string" || !VALID_LEVELS.includes(value)) {
|
|
2283
|
+
throw new Error(
|
|
2284
|
+
`[faapi] Invalid log level from ${source}: ${String(value)}. Expected one of: ${VALID_LEVELS.join(", ")}.`
|
|
2285
|
+
);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
var globalState = {
|
|
2289
|
+
level: null,
|
|
2290
|
+
sink: null,
|
|
2291
|
+
disabled: false
|
|
2292
|
+
};
|
|
2293
|
+
function configureLogging(config) {
|
|
2294
|
+
if (config === void 0) {
|
|
2295
|
+
globalState.level = null;
|
|
2296
|
+
globalState.sink = null;
|
|
2297
|
+
globalState.disabled = false;
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2300
|
+
const objectConfig = typeof config === "object" ? config : {};
|
|
2301
|
+
globalState.disabled = config === false;
|
|
2302
|
+
globalState.sink = objectConfig.sink ?? null;
|
|
2303
|
+
if (objectConfig.level !== void 0) {
|
|
2304
|
+
assertLogLevel(objectConfig.level, "config.log.level");
|
|
2305
|
+
globalState.level = objectConfig.level;
|
|
2306
|
+
} else if (process.env.LOG_LEVEL !== void 0) {
|
|
2307
|
+
assertLogLevel(process.env.LOG_LEVEL, "LOG_LEVEL env");
|
|
2308
|
+
globalState.level = process.env.LOG_LEVEL;
|
|
2309
|
+
} else {
|
|
2310
|
+
globalState.level = null;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
function globalThreshold() {
|
|
2314
|
+
return globalState.level ?? "info";
|
|
2315
|
+
}
|
|
2316
|
+
function getEffectiveLogLevel() {
|
|
2317
|
+
return globalThreshold();
|
|
2318
|
+
}
|
|
2319
|
+
function serializeFieldValue(value) {
|
|
2320
|
+
if (value instanceof Error) {
|
|
2321
|
+
return { name: value.name, message: value.message, stack: value.stack };
|
|
2322
|
+
}
|
|
2323
|
+
return value;
|
|
2324
|
+
}
|
|
2325
|
+
function formatEntry(entry) {
|
|
2326
|
+
let line = `[${entry.time}] ${entry.level.toUpperCase()} `;
|
|
2327
|
+
if (entry.scope) line += `[${entry.scope}] `;
|
|
2328
|
+
line += entry.message;
|
|
2329
|
+
if (entry.fields !== void 0) {
|
|
2330
|
+
const plain = Object.fromEntries(
|
|
2331
|
+
Object.entries(entry.fields).map(([k, v]) => [k, serializeFieldValue(v)])
|
|
2332
|
+
);
|
|
2333
|
+
try {
|
|
2334
|
+
line += ` ${JSON.stringify(plain)}`;
|
|
2335
|
+
} catch (err) {
|
|
2336
|
+
line += ` [unserializable fields: ${err instanceof Error ? err.message : String(err)}]`;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
return line;
|
|
2340
|
+
}
|
|
2341
|
+
var CONSOLE_METHOD = {
|
|
2342
|
+
debug: "debug",
|
|
2343
|
+
info: "info",
|
|
2344
|
+
warn: "warn",
|
|
2345
|
+
error: "error"
|
|
2346
|
+
};
|
|
2347
|
+
var consoleSink = (entry) => {
|
|
2348
|
+
console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
|
|
2349
|
+
};
|
|
2350
|
+
function globalDispatch(entry) {
|
|
2351
|
+
if (globalState.disabled) return;
|
|
2352
|
+
(globalState.sink ?? consoleSink)(entry);
|
|
2353
|
+
}
|
|
2354
|
+
function writeLogEntry(entry) {
|
|
2355
|
+
if (LEVEL_RANK[entry.level] < LEVEL_RANK[globalThreshold()]) return;
|
|
2356
|
+
globalDispatch(entry);
|
|
2357
|
+
}
|
|
2358
|
+
function createLogger(scope, options) {
|
|
2359
|
+
const baseScope = scope;
|
|
2360
|
+
const baseFields = options?.fields;
|
|
2361
|
+
const write = (level, message, callFields, scopeSuffix) => {
|
|
2362
|
+
const threshold = options?.level ?? globalThreshold();
|
|
2363
|
+
if (LEVEL_RANK[level] < LEVEL_RANK[threshold]) return;
|
|
2364
|
+
const entry = {
|
|
2365
|
+
level,
|
|
2366
|
+
message,
|
|
2367
|
+
time: (/* @__PURE__ */ new Date()).toISOString()
|
|
2368
|
+
};
|
|
2369
|
+
const fullScope = scopeSuffix === void 0 ? baseScope : baseScope === void 0 ? scopeSuffix : `${baseScope}:${scopeSuffix}`;
|
|
2370
|
+
if (fullScope !== void 0) entry.scope = fullScope;
|
|
2371
|
+
if (baseFields !== void 0 || callFields !== void 0) {
|
|
2372
|
+
entry.fields = { ...baseFields, ...callFields };
|
|
2373
|
+
}
|
|
2374
|
+
if (options?.sink) {
|
|
2375
|
+
options.sink(entry);
|
|
2376
|
+
} else {
|
|
2377
|
+
globalDispatch(entry);
|
|
2378
|
+
}
|
|
2379
|
+
};
|
|
2380
|
+
const makeLogger = (scopeSuffix) => ({
|
|
2381
|
+
debug: (message, fields) => write("debug", message, fields, scopeSuffix),
|
|
2382
|
+
info: (message, fields) => write("info", message, fields, scopeSuffix),
|
|
2383
|
+
warn: (message, fields) => write("warn", message, fields, scopeSuffix),
|
|
2384
|
+
error: (message, fields) => write("error", message, fields, scopeSuffix),
|
|
2385
|
+
child: (childScope) => makeLogger(scopeSuffix === void 0 ? childScope : `${scopeSuffix}:${childScope}`)
|
|
2386
|
+
});
|
|
2387
|
+
return makeLogger(void 0);
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2240
2390
|
// src/task/taskQueue.ts
|
|
2241
2391
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["done", "failed", "cancelled"]);
|
|
2242
2392
|
var MAX_FINISHED_RECORDS = 1e3;
|
|
@@ -2340,12 +2490,20 @@ function createTaskQueue(deps) {
|
|
|
2340
2490
|
job: { id: job.id, name: job.name, attempt: job.attempt }
|
|
2341
2491
|
},
|
|
2342
2492
|
registries: snapshotRegistries(),
|
|
2493
|
+
// 日志配置随 workerData 下发(纯数据),worker 内联重建 taskCtx.log,
|
|
2494
|
+
// 条目回传宿主走统一管道(scope/fields 与进程内路径一致)
|
|
2495
|
+
log: {
|
|
2496
|
+
level: getEffectiveLogLevel(),
|
|
2497
|
+
scope: `task:${job.name}`,
|
|
2498
|
+
fields: { jobId: job.id, task: job.name, attempt: job.attempt }
|
|
2499
|
+
},
|
|
2343
2500
|
timeoutMs: meta.timeoutMs,
|
|
2344
2501
|
graceMs: meta.graceMs,
|
|
2345
2502
|
externalSignal: job.signal,
|
|
2346
2503
|
onProgress: (value) => {
|
|
2347
2504
|
if (record.status === "running") record.progress = value;
|
|
2348
|
-
}
|
|
2505
|
+
},
|
|
2506
|
+
onLog: writeLogEntry
|
|
2349
2507
|
});
|
|
2350
2508
|
} else {
|
|
2351
2509
|
let mod = moduleCache2.get(job.name);
|
|
@@ -2361,6 +2519,9 @@ function createTaskQueue(deps) {
|
|
|
2361
2519
|
config: deps.config,
|
|
2362
2520
|
job: { id: job.id, name: job.name, attempt: job.attempt },
|
|
2363
2521
|
registries: registriesView,
|
|
2522
|
+
log: createLogger(`task:${job.name}`, {
|
|
2523
|
+
fields: { jobId: job.id, task: job.name, attempt: job.attempt }
|
|
2524
|
+
}),
|
|
2364
2525
|
progress: (value) => {
|
|
2365
2526
|
if (record.status === "running") record.progress = value;
|
|
2366
2527
|
}
|
|
@@ -3772,6 +3933,7 @@ function logger(options = {}) {
|
|
|
3772
3933
|
const response = await next();
|
|
3773
3934
|
const duration = Date.now() - start;
|
|
3774
3935
|
const entry = {
|
|
3936
|
+
requestId: ctx.requestId,
|
|
3775
3937
|
method: ctx.method,
|
|
3776
3938
|
path: ctx.path,
|
|
3777
3939
|
status: response.status,
|
|
@@ -3784,6 +3946,7 @@ function logger(options = {}) {
|
|
|
3784
3946
|
const message = err instanceof Error ? err.message : String(err);
|
|
3785
3947
|
const status = err?.statusCode ?? 500;
|
|
3786
3948
|
const entry = {
|
|
3949
|
+
requestId: ctx.requestId,
|
|
3787
3950
|
method: ctx.method,
|
|
3788
3951
|
path: ctx.path,
|
|
3789
3952
|
status,
|
|
@@ -4406,6 +4569,12 @@ function formatErrorResponse(error, config) {
|
|
|
4406
4569
|
}
|
|
4407
4570
|
|
|
4408
4571
|
// src/runtime/createContext.ts
|
|
4572
|
+
function resolveRequestId(request) {
|
|
4573
|
+
const header = request.headers.get("x-request-id");
|
|
4574
|
+
const first = header?.split(",")[0]?.trim();
|
|
4575
|
+
if (first) return first;
|
|
4576
|
+
return crypto.randomUUID();
|
|
4577
|
+
}
|
|
4409
4578
|
function parseCookies(cookieHeader) {
|
|
4410
4579
|
const cookies = /* @__PURE__ */ new Map();
|
|
4411
4580
|
if (!cookieHeader) return cookies;
|
|
@@ -4439,7 +4608,13 @@ function createContextFromUrl(request, url, params, config = {}, ip = "", regist
|
|
|
4439
4608
|
for (const [key, val] of parsedCookies) {
|
|
4440
4609
|
cookiesObj[key] = val;
|
|
4441
4610
|
}
|
|
4611
|
+
const requestId = resolveRequestId(request);
|
|
4612
|
+
const log = createLogger("http", {
|
|
4613
|
+
fields: { requestId, method: request.method, path: url.pathname }
|
|
4614
|
+
});
|
|
4442
4615
|
const ctx = {
|
|
4616
|
+
requestId,
|
|
4617
|
+
log,
|
|
4443
4618
|
request,
|
|
4444
4619
|
params,
|
|
4445
4620
|
query: url.searchParams,
|
|
@@ -4824,6 +4999,9 @@ function getBuiltinInjectionValue(type, ctx, body) {
|
|
|
4824
4999
|
// 任务子系统:注入 TaskClient(入队/查询);未注册工厂(无 app 编排)时 undefined
|
|
4825
5000
|
case "tasks":
|
|
4826
5001
|
return ctx.registries ? ctx.registries.taskHandle.get(ctx) : void 0;
|
|
5002
|
+
// 请求级日志器:与 ctx.log 同一实例(scope http,自动带 requestId/method/path 字段)
|
|
5003
|
+
case "log":
|
|
5004
|
+
return ctx.log;
|
|
4827
5005
|
default:
|
|
4828
5006
|
return void 0;
|
|
4829
5007
|
}
|
|
@@ -6659,6 +6837,7 @@ var FAAPI_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6659
6837
|
"etag",
|
|
6660
6838
|
"bodyLimit",
|
|
6661
6839
|
"logger",
|
|
6840
|
+
"log",
|
|
6662
6841
|
"http2",
|
|
6663
6842
|
"trustedProxy",
|
|
6664
6843
|
"response",
|
|
@@ -6677,6 +6856,7 @@ async function createAppBase(options) {
|
|
|
6677
6856
|
);
|
|
6678
6857
|
}
|
|
6679
6858
|
const config = await loadConfig(rootDir, dist);
|
|
6859
|
+
configureLogging(config?.log);
|
|
6680
6860
|
const serialized = await importWithCacheBust(routesPath);
|
|
6681
6861
|
const hydrated = await hydrateRoutes(serialized);
|
|
6682
6862
|
let sorted = sortRoutes(hydrated.routes);
|
|
@@ -7375,11 +7555,13 @@ export {
|
|
|
7375
7555
|
ValidationError,
|
|
7376
7556
|
clearAgentHandleFactory,
|
|
7377
7557
|
collectRouteSchemaSources,
|
|
7558
|
+
configureLogging,
|
|
7378
7559
|
cors,
|
|
7379
7560
|
createProdApp as createApp,
|
|
7380
7561
|
createAppRegistries,
|
|
7381
7562
|
createCronScheduler,
|
|
7382
7563
|
createDevApp,
|
|
7564
|
+
createLogger,
|
|
7383
7565
|
createProdApp,
|
|
7384
7566
|
createProgram,
|
|
7385
7567
|
createPrograms,
|