@lark-apaas/devtool-kits 1.2.4 → 1.2.5-alpha.1
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 +255 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +255 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2136,6 +2136,229 @@ async function readLogFilePage(filePath, page, pageSize) {
|
|
|
2136
2136
|
};
|
|
2137
2137
|
}
|
|
2138
2138
|
__name(readLogFilePage, "readLogFilePage");
|
|
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
|
+
}
|
|
2164
|
+
return void 0;
|
|
2165
|
+
}
|
|
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
|
|
2177
|
+
};
|
|
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) {
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
} catch (error) {
|
|
2226
|
+
console.error(`[readLogsBySource] Error reading ${filePath}:`, error);
|
|
2227
|
+
throw error;
|
|
2228
|
+
} finally {
|
|
2229
|
+
if (rl) {
|
|
2230
|
+
rl.close();
|
|
2231
|
+
}
|
|
2232
|
+
if (stream) {
|
|
2233
|
+
stream.close();
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
return logs;
|
|
2237
|
+
}
|
|
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;
|
|
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();
|
|
2302
|
+
}
|
|
2303
|
+
} catch (error) {
|
|
2304
|
+
timestamp = Date.now();
|
|
2305
|
+
}
|
|
2306
|
+
const level = extractLogLevel(content);
|
|
2307
|
+
return {
|
|
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
|
+
]
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
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");
|
|
2139
2362
|
|
|
2140
2363
|
// src/middlewares/dev-logs/controller.ts
|
|
2141
2364
|
function handleNotFound(res, filePath, message = "Log file not found") {
|
|
@@ -2229,6 +2452,32 @@ function createGetLogFileHandler(logDir) {
|
|
|
2229
2452
|
};
|
|
2230
2453
|
}
|
|
2231
2454
|
__name(createGetLogFileHandler, "createGetLogFileHandler");
|
|
2455
|
+
function createGetServerLogsHandler(logDir) {
|
|
2456
|
+
return async (req, res) => {
|
|
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;
|
|
2461
|
+
try {
|
|
2462
|
+
const result = await readServerLogs(logDir, {
|
|
2463
|
+
limit,
|
|
2464
|
+
offset,
|
|
2465
|
+
levels,
|
|
2466
|
+
sources
|
|
2467
|
+
});
|
|
2468
|
+
if (!result) {
|
|
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
|
+
});
|
|
2473
|
+
}
|
|
2474
|
+
res.json(result);
|
|
2475
|
+
} catch (error) {
|
|
2476
|
+
handleError(res, error, "Failed to read server logs");
|
|
2477
|
+
}
|
|
2478
|
+
};
|
|
2479
|
+
}
|
|
2480
|
+
__name(createGetServerLogsHandler, "createGetServerLogsHandler");
|
|
2232
2481
|
|
|
2233
2482
|
// src/middlewares/dev-logs/health.controller.ts
|
|
2234
2483
|
var import_node_http2 = __toESM(require("http"), 1);
|
|
@@ -2304,6 +2553,7 @@ function createDevLogRouter(options = {}) {
|
|
|
2304
2553
|
router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
|
|
2305
2554
|
router.get("/trace/recent", createGetRecentTracesHandler(logDir));
|
|
2306
2555
|
router.get("/files/:fileName", createGetLogFileHandler(logDir));
|
|
2556
|
+
router.get("/server-logs", createGetServerLogsHandler(logDir));
|
|
2307
2557
|
router.get("/health", createHealthCheckHandler());
|
|
2308
2558
|
return router;
|
|
2309
2559
|
}
|
|
@@ -2325,6 +2575,11 @@ var DEV_LOGS_ROUTES = [
|
|
|
2325
2575
|
method: "GET",
|
|
2326
2576
|
path: "/files/:fileName",
|
|
2327
2577
|
description: "Get paginated log file content by file name"
|
|
2578
|
+
},
|
|
2579
|
+
{
|
|
2580
|
+
method: "GET",
|
|
2581
|
+
path: "/server-logs",
|
|
2582
|
+
description: "Get server logs in ServerLog format (compatible with frontend)"
|
|
2328
2583
|
}
|
|
2329
2584
|
];
|
|
2330
2585
|
function createDevLogsMiddleware(options = {}) {
|