@lark-apaas/devtool-kits 1.2.5-alpha.1 → 1.2.5-alpha.3
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/index.cjs +180 -230
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +180 -230
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2136,229 +2136,147 @@ async function readLogFilePage(filePath, page, pageSize) {
|
|
|
2136
2136
|
};
|
|
2137
2137
|
}
|
|
2138
2138
|
__name(readLogFilePage, "readLogFilePage");
|
|
2139
|
-
async function
|
|
2140
|
-
|
|
2141
|
-
const offset = options.offset || 0;
|
|
2142
|
-
const sources = options.sources || [
|
|
2143
|
-
"server",
|
|
2144
|
-
"trace",
|
|
2145
|
-
"server-std",
|
|
2146
|
-
"client-std"
|
|
2147
|
-
];
|
|
2148
|
-
const allLogs = [];
|
|
2149
|
-
const errors = [];
|
|
2150
|
-
for (const source of sources) {
|
|
2151
|
-
try {
|
|
2152
|
-
const logs = await readLogsBySource(logDir, source);
|
|
2153
|
-
allLogs.push(...logs);
|
|
2154
|
-
} catch (error) {
|
|
2155
|
-
const errorMsg = `Failed to read ${source}: ${error instanceof Error ? error.message : String(error)}`;
|
|
2156
|
-
errors.push(errorMsg);
|
|
2157
|
-
console.warn(`[readServerLogs] ${errorMsg}`);
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
if (allLogs.length === 0) {
|
|
2161
|
-
if (errors.length > 0) {
|
|
2162
|
-
console.warn(`[readServerLogs] No logs found. Errors: ${errors.join(", ")}`);
|
|
2163
|
-
}
|
|
2139
|
+
async function readTriggerList(filePath, trigger, path7, limit) {
|
|
2140
|
+
if (!await fileExists(filePath)) {
|
|
2164
2141
|
return void 0;
|
|
2165
2142
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
}
|
|
2170
|
-
filteredLogs.sort((a, b) => b.timestamp - a.timestamp);
|
|
2171
|
-
const total = filteredLogs.length;
|
|
2172
|
-
const paginatedLogs = filteredLogs.slice(offset, offset + limit);
|
|
2173
|
-
return {
|
|
2174
|
-
logs: paginatedLogs,
|
|
2175
|
-
total,
|
|
2176
|
-
hasMore: offset + limit < total
|
|
2143
|
+
const config = {
|
|
2144
|
+
maxEntriesPerTrace: 10,
|
|
2145
|
+
chunkSize: 64 * 1024
|
|
2177
2146
|
};
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
try {
|
|
2208
|
-
stream = (0, import_node_fs7.createReadStream)(filePath, {
|
|
2209
|
-
encoding: "utf8"
|
|
2210
|
-
});
|
|
2211
|
-
rl = (0, import_node_readline.createInterface)({
|
|
2212
|
-
input: stream,
|
|
2213
|
-
crlfDelay: Infinity
|
|
2214
|
-
});
|
|
2215
|
-
for await (const line of rl) {
|
|
2216
|
-
if (!line.trim()) continue;
|
|
2217
|
-
try {
|
|
2218
|
-
const log = parser(line);
|
|
2219
|
-
if (log) {
|
|
2220
|
-
logs.push(log);
|
|
2221
|
-
}
|
|
2222
|
-
} catch (parseError) {
|
|
2147
|
+
const builders = /* @__PURE__ */ new Map();
|
|
2148
|
+
const completedCalls = [];
|
|
2149
|
+
const createTraceBuilder = /* @__PURE__ */ __name((traceId) => ({
|
|
2150
|
+
traceId,
|
|
2151
|
+
entries: [],
|
|
2152
|
+
method: void 0,
|
|
2153
|
+
path: void 0,
|
|
2154
|
+
startTime: void 0,
|
|
2155
|
+
endTime: void 0,
|
|
2156
|
+
statusCode: void 0,
|
|
2157
|
+
durationMs: void 0,
|
|
2158
|
+
hasCompleted: false
|
|
2159
|
+
}), "createTraceBuilder");
|
|
2160
|
+
const shouldIncludeInCompletedCalls = /* @__PURE__ */ __name((builder) => {
|
|
2161
|
+
const alreadyAdded = completedCalls.some((call) => call.traceId === builder.traceId);
|
|
2162
|
+
if (alreadyAdded) {
|
|
2163
|
+
return false;
|
|
2164
|
+
}
|
|
2165
|
+
if (!builder.hasCompleted) {
|
|
2166
|
+
return false;
|
|
2167
|
+
}
|
|
2168
|
+
const isAutomationTrigger = builder.path?.endsWith(path7);
|
|
2169
|
+
if (!isAutomationTrigger) {
|
|
2170
|
+
return false;
|
|
2171
|
+
}
|
|
2172
|
+
if (trigger && builder.entries.length > 0) {
|
|
2173
|
+
const requestEntry = builder.entries.find((e) => e.request_body?.trigger);
|
|
2174
|
+
if (requestEntry?.request_body?.trigger) {
|
|
2175
|
+
return String(requestEntry.request_body.trigger) === trigger;
|
|
2223
2176
|
}
|
|
2177
|
+
return false;
|
|
2224
2178
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
if (
|
|
2230
|
-
|
|
2179
|
+
return true;
|
|
2180
|
+
}, "shouldIncludeInCompletedCalls");
|
|
2181
|
+
const updateBuilderMetadata = /* @__PURE__ */ __name((builder, entry) => {
|
|
2182
|
+
if (entry.method && !builder.method) builder.method = String(entry.method);
|
|
2183
|
+
if (entry.path && !builder.path) builder.path = String(entry.path);
|
|
2184
|
+
builder.entries.push(entry);
|
|
2185
|
+
if (builder.entries.length > config.maxEntriesPerTrace) {
|
|
2186
|
+
builder.entries.shift();
|
|
2231
2187
|
}
|
|
2232
|
-
if (
|
|
2233
|
-
|
|
2188
|
+
if (shouldIncludeInCompletedCalls(builder)) {
|
|
2189
|
+
completedCalls.push(builder);
|
|
2190
|
+
if (limit && completedCalls.length > limit) {
|
|
2191
|
+
completedCalls.shift();
|
|
2192
|
+
}
|
|
2234
2193
|
}
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
return {
|
|
2244
|
-
id,
|
|
2245
|
-
level: mapPinoLevelToServerLogLevel(pinoLog.level),
|
|
2246
|
-
timestamp: new Date(pinoLog.time).getTime(),
|
|
2247
|
-
message: pinoLog.message || pinoLog.msg || "",
|
|
2248
|
-
context: pinoLog.context || null,
|
|
2249
|
-
traceId: pinoLog.trace_id || null,
|
|
2250
|
-
userId: pinoLog.user_id || null,
|
|
2251
|
-
appId: pinoLog.app_id || null,
|
|
2252
|
-
tenantId: pinoLog.tenant_id || null,
|
|
2253
|
-
stack: pinoLog.stack || null,
|
|
2254
|
-
meta: {
|
|
2255
|
-
pid: pinoLog.pid,
|
|
2256
|
-
hostname: pinoLog.hostname,
|
|
2257
|
-
path: pinoLog.path,
|
|
2258
|
-
method: pinoLog.method,
|
|
2259
|
-
statusCode: pinoLog.status_code,
|
|
2260
|
-
durationMs: pinoLog.duration_ms,
|
|
2261
|
-
ip: pinoLog.ip,
|
|
2262
|
-
requestBody: pinoLog.request_body,
|
|
2263
|
-
responseBody: pinoLog.response_body
|
|
2264
|
-
},
|
|
2265
|
-
tags: [
|
|
2266
|
-
source
|
|
2267
|
-
]
|
|
2268
|
-
};
|
|
2269
|
-
} catch (error) {
|
|
2270
|
-
return null;
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
__name(parsePinoLog, "parsePinoLog");
|
|
2274
|
-
function parseStdLog(line, source) {
|
|
2275
|
-
const id = generateUUID();
|
|
2276
|
-
const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
|
|
2277
|
-
if (!match) {
|
|
2278
|
-
return {
|
|
2279
|
-
id,
|
|
2280
|
-
level: "log",
|
|
2281
|
-
timestamp: Date.now(),
|
|
2282
|
-
message: line,
|
|
2283
|
-
context: null,
|
|
2284
|
-
traceId: null,
|
|
2285
|
-
userId: null,
|
|
2286
|
-
appId: null,
|
|
2287
|
-
tenantId: null,
|
|
2288
|
-
stack: null,
|
|
2289
|
-
meta: null,
|
|
2290
|
-
tags: [
|
|
2291
|
-
source
|
|
2292
|
-
]
|
|
2293
|
-
};
|
|
2294
|
-
}
|
|
2295
|
-
const [, timeStr, , content] = match;
|
|
2296
|
-
let timestamp;
|
|
2297
|
-
try {
|
|
2298
|
-
const isoStr = timeStr.replace(" ", "T");
|
|
2299
|
-
timestamp = new Date(isoStr).getTime();
|
|
2300
|
-
if (isNaN(timestamp)) {
|
|
2301
|
-
timestamp = Date.now();
|
|
2194
|
+
}, "updateBuilderMetadata");
|
|
2195
|
+
const handleRequestCompleted = /* @__PURE__ */ __name((builder, entry, message) => {
|
|
2196
|
+
builder.hasCompleted = true;
|
|
2197
|
+
builder.endTime = entry.time;
|
|
2198
|
+
builder.statusCode = extractNumber(message, /status_code:\s*(\d+)/);
|
|
2199
|
+
builder.durationMs = extractNumber(message, /duration_ms:\s*(\d+)/);
|
|
2200
|
+
if (!builder.path && entry.path) {
|
|
2201
|
+
builder.path = String(entry.path);
|
|
2302
2202
|
}
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2203
|
+
if (shouldIncludeInCompletedCalls(builder)) {
|
|
2204
|
+
completedCalls.push(builder);
|
|
2205
|
+
if (limit && completedCalls.length > limit) {
|
|
2206
|
+
completedCalls.shift();
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
}, "handleRequestCompleted");
|
|
2210
|
+
const processLogEntry = /* @__PURE__ */ __name((entry) => {
|
|
2211
|
+
const { trace_id: traceId, message = "" } = entry;
|
|
2212
|
+
if (!traceId) return;
|
|
2213
|
+
let builder = builders.get(traceId);
|
|
2214
|
+
if (!builder) {
|
|
2215
|
+
builder = createTraceBuilder(traceId);
|
|
2216
|
+
builders.set(traceId, builder);
|
|
2217
|
+
}
|
|
2218
|
+
updateBuilderMetadata(builder, entry);
|
|
2219
|
+
if (!builder.hasCompleted && (message.includes("HTTP request completed") || message.includes("HTTP request failed"))) {
|
|
2220
|
+
handleRequestCompleted(builder, entry, message);
|
|
2221
|
+
}
|
|
2222
|
+
if (message.includes("HTTP request started") && !builder.startTime) {
|
|
2223
|
+
builder.startTime = entry.time;
|
|
2224
|
+
}
|
|
2225
|
+
}, "processLogEntry");
|
|
2226
|
+
const processLine = /* @__PURE__ */ __name((line) => {
|
|
2227
|
+
const entry = parseLogLine2(line);
|
|
2228
|
+
if (entry?.trace_id) {
|
|
2229
|
+
processLogEntry(entry);
|
|
2230
|
+
}
|
|
2231
|
+
}, "processLine");
|
|
2232
|
+
await readFileReverse(filePath, config.chunkSize, processLine);
|
|
2307
2233
|
return {
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2234
|
+
page: 1,
|
|
2235
|
+
pageSize: completedCalls.length,
|
|
2236
|
+
totalCalls: completedCalls.length,
|
|
2237
|
+
totalPages: 1,
|
|
2238
|
+
calls: completedCalls.map((builder) => ({
|
|
2239
|
+
traceId: builder.traceId,
|
|
2240
|
+
method: builder.method,
|
|
2241
|
+
path: builder.path,
|
|
2242
|
+
startTime: builder.startTime,
|
|
2243
|
+
endTime: builder.endTime,
|
|
2244
|
+
statusCode: builder.statusCode,
|
|
2245
|
+
durationMs: builder.durationMs,
|
|
2246
|
+
entries: builder.entries.slice().reverse()
|
|
2247
|
+
}))
|
|
2322
2248
|
};
|
|
2323
2249
|
}
|
|
2324
|
-
__name(
|
|
2325
|
-
function
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
if (lower === "trace" || lower === "verbose") return "verbose";
|
|
2334
|
-
return "log";
|
|
2335
|
-
}
|
|
2336
|
-
if (pinoLevel >= 60) return "fatal";
|
|
2337
|
-
if (pinoLevel >= 50) return "error";
|
|
2338
|
-
if (pinoLevel >= 40) return "warn";
|
|
2339
|
-
if (pinoLevel >= 30) return "log";
|
|
2340
|
-
if (pinoLevel >= 20) return "debug";
|
|
2341
|
-
return "verbose";
|
|
2342
|
-
}
|
|
2343
|
-
__name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
|
|
2344
|
-
function extractLogLevel(text) {
|
|
2345
|
-
const lower = text.toLowerCase();
|
|
2346
|
-
if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
|
|
2347
|
-
if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
|
|
2348
|
-
if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
|
|
2349
|
-
if (lower.includes("debug") || lower.includes("<d>")) return "debug";
|
|
2350
|
-
if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
|
|
2351
|
-
return "log";
|
|
2352
|
-
}
|
|
2353
|
-
__name(extractLogLevel, "extractLogLevel");
|
|
2354
|
-
function generateUUID() {
|
|
2355
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
2356
|
-
const r = Math.random() * 16 | 0;
|
|
2357
|
-
const v = c === "x" ? r : r & 3 | 8;
|
|
2358
|
-
return v.toString(16);
|
|
2250
|
+
__name(readTriggerList, "readTriggerList");
|
|
2251
|
+
async function readTriggerDetail(filePath, path7, instanceID) {
|
|
2252
|
+
const exists = await fileExists(filePath);
|
|
2253
|
+
if (!exists) {
|
|
2254
|
+
return void 0;
|
|
2255
|
+
}
|
|
2256
|
+
const matches = [];
|
|
2257
|
+
const stream = (0, import_node_fs7.createReadStream)(filePath, {
|
|
2258
|
+
encoding: "utf8"
|
|
2359
2259
|
});
|
|
2260
|
+
const rl = (0, import_node_readline.createInterface)({
|
|
2261
|
+
input: stream,
|
|
2262
|
+
crlfDelay: Infinity
|
|
2263
|
+
});
|
|
2264
|
+
for await (const line of rl) {
|
|
2265
|
+
const entry = parseLogLine2(line);
|
|
2266
|
+
if (!entry) continue;
|
|
2267
|
+
const isAutomationTrigger = entry.path?.endsWith(path7);
|
|
2268
|
+
const hasInstanceID = entry.message?.includes(`instanceID=${instanceID}`);
|
|
2269
|
+
if (!isAutomationTrigger || !hasInstanceID) continue;
|
|
2270
|
+
matches.push(entry);
|
|
2271
|
+
}
|
|
2272
|
+
rl.close();
|
|
2273
|
+
stream.close();
|
|
2274
|
+
return {
|
|
2275
|
+
instanceID,
|
|
2276
|
+
entries: matches
|
|
2277
|
+
};
|
|
2360
2278
|
}
|
|
2361
|
-
__name(
|
|
2279
|
+
__name(readTriggerDetail, "readTriggerDetail");
|
|
2362
2280
|
|
|
2363
2281
|
// src/middlewares/dev-logs/controller.ts
|
|
2364
2282
|
function handleNotFound(res, filePath, message = "Log file not found") {
|
|
@@ -2452,32 +2370,58 @@ function createGetLogFileHandler(logDir) {
|
|
|
2452
2370
|
};
|
|
2453
2371
|
}
|
|
2454
2372
|
__name(createGetLogFileHandler, "createGetLogFileHandler");
|
|
2455
|
-
function
|
|
2373
|
+
function createGetTriggerListHandler(logDir) {
|
|
2374
|
+
const traceLogPath = (0, import_node_path7.join)(logDir, "trace.log");
|
|
2456
2375
|
return async (req, res) => {
|
|
2457
|
-
const
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2376
|
+
const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
|
|
2377
|
+
if (!trigger) {
|
|
2378
|
+
return res.status(400).json({
|
|
2379
|
+
message: "trigger is required"
|
|
2380
|
+
});
|
|
2381
|
+
}
|
|
2382
|
+
const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2383
|
+
const limit = parseLimit(req.query.limit, 10, 200);
|
|
2461
2384
|
try {
|
|
2462
|
-
const result = await
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2385
|
+
const result = await readTriggerList(traceLogPath, trigger, path7, limit);
|
|
2386
|
+
if (!result) {
|
|
2387
|
+
return handleNotFound(res, traceLogPath);
|
|
2388
|
+
}
|
|
2389
|
+
res.json({
|
|
2390
|
+
file: getRelativePath(traceLogPath),
|
|
2391
|
+
path: path7,
|
|
2392
|
+
...result
|
|
2467
2393
|
});
|
|
2394
|
+
} catch (error) {
|
|
2395
|
+
handleError(res, error, "Failed to read trace log");
|
|
2396
|
+
}
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
__name(createGetTriggerListHandler, "createGetTriggerListHandler");
|
|
2400
|
+
function createGetTriggerDetailHandler(logDir) {
|
|
2401
|
+
const traceLogPath = (0, import_node_path7.join)(logDir, "server.log");
|
|
2402
|
+
return async (req, res) => {
|
|
2403
|
+
const instanceID = (req.params.instanceID || "").trim();
|
|
2404
|
+
if (!instanceID) {
|
|
2405
|
+
return res.status(400).json({
|
|
2406
|
+
message: "instanceID is required"
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2410
|
+
try {
|
|
2411
|
+
const result = await readTriggerDetail(traceLogPath, path7, instanceID);
|
|
2468
2412
|
if (!result) {
|
|
2469
|
-
return res
|
|
2470
|
-
message: "No server log files found",
|
|
2471
|
-
hint: "Expected files: server.log, trace.log, server.std.log, client.std.log"
|
|
2472
|
-
});
|
|
2413
|
+
return handleNotFound(res, traceLogPath);
|
|
2473
2414
|
}
|
|
2474
|
-
res.json(
|
|
2415
|
+
res.json({
|
|
2416
|
+
file: getRelativePath(traceLogPath),
|
|
2417
|
+
...result
|
|
2418
|
+
});
|
|
2475
2419
|
} catch (error) {
|
|
2476
|
-
handleError(res, error, "Failed to read
|
|
2420
|
+
handleError(res, error, "Failed to read trace log");
|
|
2477
2421
|
}
|
|
2478
2422
|
};
|
|
2479
2423
|
}
|
|
2480
|
-
__name(
|
|
2424
|
+
__name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
|
|
2481
2425
|
|
|
2482
2426
|
// src/middlewares/dev-logs/health.controller.ts
|
|
2483
2427
|
var import_node_http2 = __toESM(require("http"), 1);
|
|
@@ -2553,7 +2497,8 @@ function createDevLogRouter(options = {}) {
|
|
|
2553
2497
|
router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
|
|
2554
2498
|
router.get("/trace/recent", createGetRecentTracesHandler(logDir));
|
|
2555
2499
|
router.get("/files/:fileName", createGetLogFileHandler(logDir));
|
|
2556
|
-
router.get("/
|
|
2500
|
+
router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
|
|
2501
|
+
router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
|
|
2557
2502
|
router.get("/health", createHealthCheckHandler());
|
|
2558
2503
|
return router;
|
|
2559
2504
|
}
|
|
@@ -2578,8 +2523,13 @@ var DEV_LOGS_ROUTES = [
|
|
|
2578
2523
|
},
|
|
2579
2524
|
{
|
|
2580
2525
|
method: "GET",
|
|
2581
|
-
path: "/
|
|
2582
|
-
description: "Get
|
|
2526
|
+
path: "/trace/trigger/list",
|
|
2527
|
+
description: "Get trigger list (automation trigger) in trace.log"
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
method: "GET",
|
|
2531
|
+
path: "/trace/trigger/:instanceID",
|
|
2532
|
+
description: "Get trigger detail (automation trigger) in trace.log by instanceID"
|
|
2583
2533
|
}
|
|
2584
2534
|
];
|
|
2585
2535
|
function createDevLogsMiddleware(options = {}) {
|