@lark-apaas/devtool-kits 1.2.5-alpha.2 → 1.2.5
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 +230 -178
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +230 -178
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2136,146 +2136,229 @@ async function readLogFilePage(filePath, page, pageSize) {
|
|
|
2136
2136
|
};
|
|
2137
2137
|
}
|
|
2138
2138
|
__name(readLogFilePage, "readLogFilePage");
|
|
2139
|
-
async function
|
|
2140
|
-
|
|
2139
|
+
async function readServerLogs(logDir, options = {}) {
|
|
2140
|
+
const limit = options.limit || 100;
|
|
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
|
+
}
|
|
2141
2164
|
return void 0;
|
|
2142
2165
|
}
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2166
|
+
let filteredLogs = allLogs;
|
|
2167
|
+
if (options.levels && options.levels.length > 0) {
|
|
2168
|
+
filteredLogs = allLogs.filter((log) => options.levels.includes(log.level));
|
|
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
|
|
2146
2177
|
};
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
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);
|
|
2202
|
-
}
|
|
2203
|
-
if (shouldIncludeInCompletedCalls(builder)) {
|
|
2204
|
-
completedCalls.push(builder);
|
|
2205
|
-
if (limit && completedCalls.length > limit) {
|
|
2206
|
-
completedCalls.shift();
|
|
2178
|
+
}
|
|
2179
|
+
__name(readServerLogs, "readServerLogs");
|
|
2180
|
+
async function readLogsBySource(logDir, source) {
|
|
2181
|
+
const { join: join6 } = await import("path");
|
|
2182
|
+
let filePath;
|
|
2183
|
+
let parser;
|
|
2184
|
+
if (source === "server") {
|
|
2185
|
+
filePath = join6(logDir, "server.log");
|
|
2186
|
+
parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
|
|
2187
|
+
} else if (source === "trace") {
|
|
2188
|
+
filePath = join6(logDir, "trace.log");
|
|
2189
|
+
parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "trace"), "parser");
|
|
2190
|
+
} else if (source === "server-std") {
|
|
2191
|
+
filePath = join6(logDir, "server.std.log");
|
|
2192
|
+
parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "server-std"), "parser");
|
|
2193
|
+
} else if (source === "client-std") {
|
|
2194
|
+
filePath = join6(logDir, "client.std.log");
|
|
2195
|
+
parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "client-std"), "parser");
|
|
2196
|
+
} else {
|
|
2197
|
+
console.warn(`[readLogsBySource] Unknown source: ${source}`);
|
|
2198
|
+
return [];
|
|
2199
|
+
}
|
|
2200
|
+
if (!await fileExists(filePath)) {
|
|
2201
|
+
console.warn(`[readLogsBySource] File not found: ${filePath}`);
|
|
2202
|
+
return [];
|
|
2203
|
+
}
|
|
2204
|
+
const logs = [];
|
|
2205
|
+
let stream = null;
|
|
2206
|
+
let rl = null;
|
|
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) {
|
|
2207
2223
|
}
|
|
2208
2224
|
}
|
|
2209
|
-
}
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
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;
|
|
2225
|
+
} catch (error) {
|
|
2226
|
+
console.error(`[readLogsBySource] Error reading ${filePath}:`, error);
|
|
2227
|
+
throw error;
|
|
2228
|
+
} finally {
|
|
2229
|
+
if (rl) {
|
|
2230
|
+
rl.close();
|
|
2224
2231
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
const entry = parseLogLine2(line);
|
|
2228
|
-
if (entry?.trace_id) {
|
|
2229
|
-
processLogEntry(entry);
|
|
2232
|
+
if (stream) {
|
|
2233
|
+
stream.close();
|
|
2230
2234
|
}
|
|
2231
|
-
}
|
|
2232
|
-
|
|
2233
|
-
return {
|
|
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
|
-
}))
|
|
2248
|
-
};
|
|
2235
|
+
}
|
|
2236
|
+
return logs;
|
|
2249
2237
|
}
|
|
2250
|
-
__name(
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2238
|
+
__name(readLogsBySource, "readLogsBySource");
|
|
2239
|
+
function parsePinoLog(line, source) {
|
|
2240
|
+
try {
|
|
2241
|
+
const pinoLog = JSON.parse(line);
|
|
2242
|
+
const id = generateUUID();
|
|
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;
|
|
2255
2271
|
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
const
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
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
|
+
};
|
|
2270
2294
|
}
|
|
2271
|
-
|
|
2272
|
-
|
|
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();
|
|
2302
|
+
}
|
|
2303
|
+
} catch (error) {
|
|
2304
|
+
timestamp = Date.now();
|
|
2305
|
+
}
|
|
2306
|
+
const level = extractLogLevel(content);
|
|
2273
2307
|
return {
|
|
2274
|
-
|
|
2275
|
-
|
|
2308
|
+
id,
|
|
2309
|
+
level,
|
|
2310
|
+
timestamp,
|
|
2311
|
+
message: content,
|
|
2312
|
+
context: null,
|
|
2313
|
+
traceId: null,
|
|
2314
|
+
userId: null,
|
|
2315
|
+
appId: null,
|
|
2316
|
+
tenantId: null,
|
|
2317
|
+
stack: null,
|
|
2318
|
+
meta: null,
|
|
2319
|
+
tags: [
|
|
2320
|
+
source
|
|
2321
|
+
]
|
|
2276
2322
|
};
|
|
2277
2323
|
}
|
|
2278
|
-
__name(
|
|
2324
|
+
__name(parseStdLog, "parseStdLog");
|
|
2325
|
+
function mapPinoLevelToServerLogLevel(pinoLevel) {
|
|
2326
|
+
if (typeof pinoLevel === "string") {
|
|
2327
|
+
const lower = pinoLevel.toLowerCase();
|
|
2328
|
+
if (lower === "fatal") return "fatal";
|
|
2329
|
+
if (lower === "error") return "error";
|
|
2330
|
+
if (lower === "warn" || lower === "warning") return "warn";
|
|
2331
|
+
if (lower === "info" || lower === "log") return "log";
|
|
2332
|
+
if (lower === "debug") return "debug";
|
|
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);
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
__name(generateUUID, "generateUUID");
|
|
2279
2362
|
|
|
2280
2363
|
// src/middlewares/dev-logs/controller.ts
|
|
2281
2364
|
function handleNotFound(res, filePath, message = "Log file not found") {
|
|
@@ -2369,57 +2452,32 @@ function createGetLogFileHandler(logDir) {
|
|
|
2369
2452
|
};
|
|
2370
2453
|
}
|
|
2371
2454
|
__name(createGetLogFileHandler, "createGetLogFileHandler");
|
|
2372
|
-
function
|
|
2373
|
-
const traceLogPath = (0, import_node_path7.join)(logDir, "trace.log");
|
|
2455
|
+
function createGetServerLogsHandler(logDir) {
|
|
2374
2456
|
return async (req, res) => {
|
|
2375
|
-
const
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
});
|
|
2380
|
-
}
|
|
2381
|
-
const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2382
|
-
const limit = parseLimit(req.query.limit, 10, 200);
|
|
2457
|
+
const limit = parseLimit(req.query.limit, 100, 1e3);
|
|
2458
|
+
const offset = parsePositiveInt(req.query.offset, 0);
|
|
2459
|
+
const levels = req.query.levels ? String(req.query.levels).split(",").map((l) => l.trim()).filter(Boolean) : void 0;
|
|
2460
|
+
const sources = req.query.sources ? String(req.query.sources).split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
2383
2461
|
try {
|
|
2384
|
-
const result = await
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
file: getRelativePath(traceLogPath),
|
|
2390
|
-
path: path7,
|
|
2391
|
-
...result
|
|
2462
|
+
const result = await readServerLogs(logDir, {
|
|
2463
|
+
limit,
|
|
2464
|
+
offset,
|
|
2465
|
+
levels,
|
|
2466
|
+
sources
|
|
2392
2467
|
});
|
|
2393
|
-
} catch (error) {
|
|
2394
|
-
handleError(res, error, "Failed to read trace log");
|
|
2395
|
-
}
|
|
2396
|
-
};
|
|
2397
|
-
}
|
|
2398
|
-
__name(createGetTriggerListHandler, "createGetTriggerListHandler");
|
|
2399
|
-
function createGetTriggerDetailHandler(logDir) {
|
|
2400
|
-
const traceLogPath = (0, import_node_path7.join)(logDir, "server.log");
|
|
2401
|
-
return async (req, res) => {
|
|
2402
|
-
const instanceID = (req.params.instanceID || "").trim();
|
|
2403
|
-
if (!instanceID) {
|
|
2404
|
-
return res.status(400).json({
|
|
2405
|
-
message: "instanceID is required"
|
|
2406
|
-
});
|
|
2407
|
-
}
|
|
2408
|
-
try {
|
|
2409
|
-
const result = await readTriggerDetail(traceLogPath, instanceID);
|
|
2410
2468
|
if (!result) {
|
|
2411
|
-
return
|
|
2469
|
+
return res.status(404).json({
|
|
2470
|
+
message: "No server log files found",
|
|
2471
|
+
hint: "Expected files: server.log, trace.log, server.std.log, client.std.log"
|
|
2472
|
+
});
|
|
2412
2473
|
}
|
|
2413
|
-
res.json(
|
|
2414
|
-
file: getRelativePath(traceLogPath),
|
|
2415
|
-
...result
|
|
2416
|
-
});
|
|
2474
|
+
res.json(result);
|
|
2417
2475
|
} catch (error) {
|
|
2418
|
-
handleError(res, error, "Failed to read
|
|
2476
|
+
handleError(res, error, "Failed to read server logs");
|
|
2419
2477
|
}
|
|
2420
2478
|
};
|
|
2421
2479
|
}
|
|
2422
|
-
__name(
|
|
2480
|
+
__name(createGetServerLogsHandler, "createGetServerLogsHandler");
|
|
2423
2481
|
|
|
2424
2482
|
// src/middlewares/dev-logs/health.controller.ts
|
|
2425
2483
|
var import_node_http2 = __toESM(require("http"), 1);
|
|
@@ -2495,8 +2553,7 @@ function createDevLogRouter(options = {}) {
|
|
|
2495
2553
|
router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
|
|
2496
2554
|
router.get("/trace/recent", createGetRecentTracesHandler(logDir));
|
|
2497
2555
|
router.get("/files/:fileName", createGetLogFileHandler(logDir));
|
|
2498
|
-
router.get("/
|
|
2499
|
-
router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
|
|
2556
|
+
router.get("/server-logs", createGetServerLogsHandler(logDir));
|
|
2500
2557
|
router.get("/health", createHealthCheckHandler());
|
|
2501
2558
|
return router;
|
|
2502
2559
|
}
|
|
@@ -2521,13 +2578,8 @@ var DEV_LOGS_ROUTES = [
|
|
|
2521
2578
|
},
|
|
2522
2579
|
{
|
|
2523
2580
|
method: "GET",
|
|
2524
|
-
path: "/
|
|
2525
|
-
description: "Get
|
|
2526
|
-
},
|
|
2527
|
-
{
|
|
2528
|
-
method: "GET",
|
|
2529
|
-
path: "/trace/trigger/:instanceID",
|
|
2530
|
-
description: "Get trigger detail (automation trigger) in trace.log by instanceID"
|
|
2581
|
+
path: "/server-logs",
|
|
2582
|
+
description: "Get server logs in ServerLog format (compatible with frontend)"
|
|
2531
2583
|
}
|
|
2532
2584
|
];
|
|
2533
2585
|
function createDevLogsMiddleware(options = {}) {
|