@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.js
CHANGED
|
@@ -2095,146 +2095,229 @@ async function readLogFilePage(filePath, page, pageSize) {
|
|
|
2095
2095
|
};
|
|
2096
2096
|
}
|
|
2097
2097
|
__name(readLogFilePage, "readLogFilePage");
|
|
2098
|
-
async function
|
|
2099
|
-
|
|
2098
|
+
async function readServerLogs(logDir, options = {}) {
|
|
2099
|
+
const limit = options.limit || 100;
|
|
2100
|
+
const offset = options.offset || 0;
|
|
2101
|
+
const sources = options.sources || [
|
|
2102
|
+
"server",
|
|
2103
|
+
"trace",
|
|
2104
|
+
"server-std",
|
|
2105
|
+
"client-std"
|
|
2106
|
+
];
|
|
2107
|
+
const allLogs = [];
|
|
2108
|
+
const errors = [];
|
|
2109
|
+
for (const source of sources) {
|
|
2110
|
+
try {
|
|
2111
|
+
const logs = await readLogsBySource(logDir, source);
|
|
2112
|
+
allLogs.push(...logs);
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
const errorMsg = `Failed to read ${source}: ${error instanceof Error ? error.message : String(error)}`;
|
|
2115
|
+
errors.push(errorMsg);
|
|
2116
|
+
console.warn(`[readServerLogs] ${errorMsg}`);
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
if (allLogs.length === 0) {
|
|
2120
|
+
if (errors.length > 0) {
|
|
2121
|
+
console.warn(`[readServerLogs] No logs found. Errors: ${errors.join(", ")}`);
|
|
2122
|
+
}
|
|
2100
2123
|
return void 0;
|
|
2101
2124
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2125
|
+
let filteredLogs = allLogs;
|
|
2126
|
+
if (options.levels && options.levels.length > 0) {
|
|
2127
|
+
filteredLogs = allLogs.filter((log) => options.levels.includes(log.level));
|
|
2128
|
+
}
|
|
2129
|
+
filteredLogs.sort((a, b) => b.timestamp - a.timestamp);
|
|
2130
|
+
const total = filteredLogs.length;
|
|
2131
|
+
const paginatedLogs = filteredLogs.slice(offset, offset + limit);
|
|
2132
|
+
return {
|
|
2133
|
+
logs: paginatedLogs,
|
|
2134
|
+
total,
|
|
2135
|
+
hasMore: offset + limit < total
|
|
2105
2136
|
};
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
}, "updateBuilderMetadata");
|
|
2154
|
-
const handleRequestCompleted = /* @__PURE__ */ __name((builder, entry, message) => {
|
|
2155
|
-
builder.hasCompleted = true;
|
|
2156
|
-
builder.endTime = entry.time;
|
|
2157
|
-
builder.statusCode = extractNumber(message, /status_code:\s*(\d+)/);
|
|
2158
|
-
builder.durationMs = extractNumber(message, /duration_ms:\s*(\d+)/);
|
|
2159
|
-
if (!builder.path && entry.path) {
|
|
2160
|
-
builder.path = String(entry.path);
|
|
2161
|
-
}
|
|
2162
|
-
if (shouldIncludeInCompletedCalls(builder)) {
|
|
2163
|
-
completedCalls.push(builder);
|
|
2164
|
-
if (limit && completedCalls.length > limit) {
|
|
2165
|
-
completedCalls.shift();
|
|
2137
|
+
}
|
|
2138
|
+
__name(readServerLogs, "readServerLogs");
|
|
2139
|
+
async function readLogsBySource(logDir, source) {
|
|
2140
|
+
const { join: join6 } = await import("path");
|
|
2141
|
+
let filePath;
|
|
2142
|
+
let parser;
|
|
2143
|
+
if (source === "server") {
|
|
2144
|
+
filePath = join6(logDir, "server.log");
|
|
2145
|
+
parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
|
|
2146
|
+
} else if (source === "trace") {
|
|
2147
|
+
filePath = join6(logDir, "trace.log");
|
|
2148
|
+
parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "trace"), "parser");
|
|
2149
|
+
} else if (source === "server-std") {
|
|
2150
|
+
filePath = join6(logDir, "server.std.log");
|
|
2151
|
+
parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "server-std"), "parser");
|
|
2152
|
+
} else if (source === "client-std") {
|
|
2153
|
+
filePath = join6(logDir, "client.std.log");
|
|
2154
|
+
parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "client-std"), "parser");
|
|
2155
|
+
} else {
|
|
2156
|
+
console.warn(`[readLogsBySource] Unknown source: ${source}`);
|
|
2157
|
+
return [];
|
|
2158
|
+
}
|
|
2159
|
+
if (!await fileExists(filePath)) {
|
|
2160
|
+
console.warn(`[readLogsBySource] File not found: ${filePath}`);
|
|
2161
|
+
return [];
|
|
2162
|
+
}
|
|
2163
|
+
const logs = [];
|
|
2164
|
+
let stream = null;
|
|
2165
|
+
let rl = null;
|
|
2166
|
+
try {
|
|
2167
|
+
stream = createReadStream(filePath, {
|
|
2168
|
+
encoding: "utf8"
|
|
2169
|
+
});
|
|
2170
|
+
rl = createInterface({
|
|
2171
|
+
input: stream,
|
|
2172
|
+
crlfDelay: Infinity
|
|
2173
|
+
});
|
|
2174
|
+
for await (const line of rl) {
|
|
2175
|
+
if (!line.trim()) continue;
|
|
2176
|
+
try {
|
|
2177
|
+
const log = parser(line);
|
|
2178
|
+
if (log) {
|
|
2179
|
+
logs.push(log);
|
|
2180
|
+
}
|
|
2181
|
+
} catch (parseError) {
|
|
2166
2182
|
}
|
|
2167
2183
|
}
|
|
2168
|
-
}
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
builder = createTraceBuilder(traceId);
|
|
2175
|
-
builders.set(traceId, builder);
|
|
2176
|
-
}
|
|
2177
|
-
updateBuilderMetadata(builder, entry);
|
|
2178
|
-
if (!builder.hasCompleted && (message.includes("HTTP request completed") || message.includes("HTTP request failed"))) {
|
|
2179
|
-
handleRequestCompleted(builder, entry, message);
|
|
2180
|
-
}
|
|
2181
|
-
if (message.includes("HTTP request started") && !builder.startTime) {
|
|
2182
|
-
builder.startTime = entry.time;
|
|
2184
|
+
} catch (error) {
|
|
2185
|
+
console.error(`[readLogsBySource] Error reading ${filePath}:`, error);
|
|
2186
|
+
throw error;
|
|
2187
|
+
} finally {
|
|
2188
|
+
if (rl) {
|
|
2189
|
+
rl.close();
|
|
2183
2190
|
}
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
const entry = parseLogLine2(line);
|
|
2187
|
-
if (entry?.trace_id) {
|
|
2188
|
-
processLogEntry(entry);
|
|
2191
|
+
if (stream) {
|
|
2192
|
+
stream.close();
|
|
2189
2193
|
}
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
|
-
return {
|
|
2193
|
-
page: 1,
|
|
2194
|
-
pageSize: completedCalls.length,
|
|
2195
|
-
totalCalls: completedCalls.length,
|
|
2196
|
-
totalPages: 1,
|
|
2197
|
-
calls: completedCalls.map((builder) => ({
|
|
2198
|
-
traceId: builder.traceId,
|
|
2199
|
-
method: builder.method,
|
|
2200
|
-
path: builder.path,
|
|
2201
|
-
startTime: builder.startTime,
|
|
2202
|
-
endTime: builder.endTime,
|
|
2203
|
-
statusCode: builder.statusCode,
|
|
2204
|
-
durationMs: builder.durationMs,
|
|
2205
|
-
entries: builder.entries.slice().reverse()
|
|
2206
|
-
}))
|
|
2207
|
-
};
|
|
2194
|
+
}
|
|
2195
|
+
return logs;
|
|
2208
2196
|
}
|
|
2209
|
-
__name(
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2197
|
+
__name(readLogsBySource, "readLogsBySource");
|
|
2198
|
+
function parsePinoLog(line, source) {
|
|
2199
|
+
try {
|
|
2200
|
+
const pinoLog = JSON.parse(line);
|
|
2201
|
+
const id = generateUUID();
|
|
2202
|
+
return {
|
|
2203
|
+
id,
|
|
2204
|
+
level: mapPinoLevelToServerLogLevel(pinoLog.level),
|
|
2205
|
+
timestamp: new Date(pinoLog.time).getTime(),
|
|
2206
|
+
message: pinoLog.message || pinoLog.msg || "",
|
|
2207
|
+
context: pinoLog.context || null,
|
|
2208
|
+
traceId: pinoLog.trace_id || null,
|
|
2209
|
+
userId: pinoLog.user_id || null,
|
|
2210
|
+
appId: pinoLog.app_id || null,
|
|
2211
|
+
tenantId: pinoLog.tenant_id || null,
|
|
2212
|
+
stack: pinoLog.stack || null,
|
|
2213
|
+
meta: {
|
|
2214
|
+
pid: pinoLog.pid,
|
|
2215
|
+
hostname: pinoLog.hostname,
|
|
2216
|
+
path: pinoLog.path,
|
|
2217
|
+
method: pinoLog.method,
|
|
2218
|
+
statusCode: pinoLog.status_code,
|
|
2219
|
+
durationMs: pinoLog.duration_ms,
|
|
2220
|
+
ip: pinoLog.ip,
|
|
2221
|
+
requestBody: pinoLog.request_body,
|
|
2222
|
+
responseBody: pinoLog.response_body
|
|
2223
|
+
},
|
|
2224
|
+
tags: [
|
|
2225
|
+
source
|
|
2226
|
+
]
|
|
2227
|
+
};
|
|
2228
|
+
} catch (error) {
|
|
2229
|
+
return null;
|
|
2214
2230
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
const
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2231
|
+
}
|
|
2232
|
+
__name(parsePinoLog, "parsePinoLog");
|
|
2233
|
+
function parseStdLog(line, source) {
|
|
2234
|
+
const id = generateUUID();
|
|
2235
|
+
const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
|
|
2236
|
+
if (!match) {
|
|
2237
|
+
return {
|
|
2238
|
+
id,
|
|
2239
|
+
level: "log",
|
|
2240
|
+
timestamp: Date.now(),
|
|
2241
|
+
message: line,
|
|
2242
|
+
context: null,
|
|
2243
|
+
traceId: null,
|
|
2244
|
+
userId: null,
|
|
2245
|
+
appId: null,
|
|
2246
|
+
tenantId: null,
|
|
2247
|
+
stack: null,
|
|
2248
|
+
meta: null,
|
|
2249
|
+
tags: [
|
|
2250
|
+
source
|
|
2251
|
+
]
|
|
2252
|
+
};
|
|
2229
2253
|
}
|
|
2230
|
-
|
|
2231
|
-
|
|
2254
|
+
const [, timeStr, , content] = match;
|
|
2255
|
+
let timestamp;
|
|
2256
|
+
try {
|
|
2257
|
+
const isoStr = timeStr.replace(" ", "T");
|
|
2258
|
+
timestamp = new Date(isoStr).getTime();
|
|
2259
|
+
if (isNaN(timestamp)) {
|
|
2260
|
+
timestamp = Date.now();
|
|
2261
|
+
}
|
|
2262
|
+
} catch (error) {
|
|
2263
|
+
timestamp = Date.now();
|
|
2264
|
+
}
|
|
2265
|
+
const level = extractLogLevel(content);
|
|
2232
2266
|
return {
|
|
2233
|
-
|
|
2234
|
-
|
|
2267
|
+
id,
|
|
2268
|
+
level,
|
|
2269
|
+
timestamp,
|
|
2270
|
+
message: content,
|
|
2271
|
+
context: null,
|
|
2272
|
+
traceId: null,
|
|
2273
|
+
userId: null,
|
|
2274
|
+
appId: null,
|
|
2275
|
+
tenantId: null,
|
|
2276
|
+
stack: null,
|
|
2277
|
+
meta: null,
|
|
2278
|
+
tags: [
|
|
2279
|
+
source
|
|
2280
|
+
]
|
|
2235
2281
|
};
|
|
2236
2282
|
}
|
|
2237
|
-
__name(
|
|
2283
|
+
__name(parseStdLog, "parseStdLog");
|
|
2284
|
+
function mapPinoLevelToServerLogLevel(pinoLevel) {
|
|
2285
|
+
if (typeof pinoLevel === "string") {
|
|
2286
|
+
const lower = pinoLevel.toLowerCase();
|
|
2287
|
+
if (lower === "fatal") return "fatal";
|
|
2288
|
+
if (lower === "error") return "error";
|
|
2289
|
+
if (lower === "warn" || lower === "warning") return "warn";
|
|
2290
|
+
if (lower === "info" || lower === "log") return "log";
|
|
2291
|
+
if (lower === "debug") return "debug";
|
|
2292
|
+
if (lower === "trace" || lower === "verbose") return "verbose";
|
|
2293
|
+
return "log";
|
|
2294
|
+
}
|
|
2295
|
+
if (pinoLevel >= 60) return "fatal";
|
|
2296
|
+
if (pinoLevel >= 50) return "error";
|
|
2297
|
+
if (pinoLevel >= 40) return "warn";
|
|
2298
|
+
if (pinoLevel >= 30) return "log";
|
|
2299
|
+
if (pinoLevel >= 20) return "debug";
|
|
2300
|
+
return "verbose";
|
|
2301
|
+
}
|
|
2302
|
+
__name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
|
|
2303
|
+
function extractLogLevel(text) {
|
|
2304
|
+
const lower = text.toLowerCase();
|
|
2305
|
+
if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
|
|
2306
|
+
if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
|
|
2307
|
+
if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
|
|
2308
|
+
if (lower.includes("debug") || lower.includes("<d>")) return "debug";
|
|
2309
|
+
if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
|
|
2310
|
+
return "log";
|
|
2311
|
+
}
|
|
2312
|
+
__name(extractLogLevel, "extractLogLevel");
|
|
2313
|
+
function generateUUID() {
|
|
2314
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
2315
|
+
const r = Math.random() * 16 | 0;
|
|
2316
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
2317
|
+
return v.toString(16);
|
|
2318
|
+
});
|
|
2319
|
+
}
|
|
2320
|
+
__name(generateUUID, "generateUUID");
|
|
2238
2321
|
|
|
2239
2322
|
// src/middlewares/dev-logs/controller.ts
|
|
2240
2323
|
function handleNotFound(res, filePath, message = "Log file not found") {
|
|
@@ -2328,57 +2411,32 @@ function createGetLogFileHandler(logDir) {
|
|
|
2328
2411
|
};
|
|
2329
2412
|
}
|
|
2330
2413
|
__name(createGetLogFileHandler, "createGetLogFileHandler");
|
|
2331
|
-
function
|
|
2332
|
-
const traceLogPath = join3(logDir, "trace.log");
|
|
2414
|
+
function createGetServerLogsHandler(logDir) {
|
|
2333
2415
|
return async (req, res) => {
|
|
2334
|
-
const
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
});
|
|
2339
|
-
}
|
|
2340
|
-
const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2341
|
-
const limit = parseLimit(req.query.limit, 10, 200);
|
|
2416
|
+
const limit = parseLimit(req.query.limit, 100, 1e3);
|
|
2417
|
+
const offset = parsePositiveInt(req.query.offset, 0);
|
|
2418
|
+
const levels = req.query.levels ? String(req.query.levels).split(",").map((l) => l.trim()).filter(Boolean) : void 0;
|
|
2419
|
+
const sources = req.query.sources ? String(req.query.sources).split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
2342
2420
|
try {
|
|
2343
|
-
const result = await
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
file: getRelativePath(traceLogPath),
|
|
2349
|
-
path: path7,
|
|
2350
|
-
...result
|
|
2421
|
+
const result = await readServerLogs(logDir, {
|
|
2422
|
+
limit,
|
|
2423
|
+
offset,
|
|
2424
|
+
levels,
|
|
2425
|
+
sources
|
|
2351
2426
|
});
|
|
2352
|
-
} catch (error) {
|
|
2353
|
-
handleError(res, error, "Failed to read trace log");
|
|
2354
|
-
}
|
|
2355
|
-
};
|
|
2356
|
-
}
|
|
2357
|
-
__name(createGetTriggerListHandler, "createGetTriggerListHandler");
|
|
2358
|
-
function createGetTriggerDetailHandler(logDir) {
|
|
2359
|
-
const traceLogPath = join3(logDir, "server.log");
|
|
2360
|
-
return async (req, res) => {
|
|
2361
|
-
const instanceID = (req.params.instanceID || "").trim();
|
|
2362
|
-
if (!instanceID) {
|
|
2363
|
-
return res.status(400).json({
|
|
2364
|
-
message: "instanceID is required"
|
|
2365
|
-
});
|
|
2366
|
-
}
|
|
2367
|
-
try {
|
|
2368
|
-
const result = await readTriggerDetail(traceLogPath, instanceID);
|
|
2369
2427
|
if (!result) {
|
|
2370
|
-
return
|
|
2428
|
+
return res.status(404).json({
|
|
2429
|
+
message: "No server log files found",
|
|
2430
|
+
hint: "Expected files: server.log, trace.log, server.std.log, client.std.log"
|
|
2431
|
+
});
|
|
2371
2432
|
}
|
|
2372
|
-
res.json(
|
|
2373
|
-
file: getRelativePath(traceLogPath),
|
|
2374
|
-
...result
|
|
2375
|
-
});
|
|
2433
|
+
res.json(result);
|
|
2376
2434
|
} catch (error) {
|
|
2377
|
-
handleError(res, error, "Failed to read
|
|
2435
|
+
handleError(res, error, "Failed to read server logs");
|
|
2378
2436
|
}
|
|
2379
2437
|
};
|
|
2380
2438
|
}
|
|
2381
|
-
__name(
|
|
2439
|
+
__name(createGetServerLogsHandler, "createGetServerLogsHandler");
|
|
2382
2440
|
|
|
2383
2441
|
// src/middlewares/dev-logs/health.controller.ts
|
|
2384
2442
|
import http2 from "http";
|
|
@@ -2454,8 +2512,7 @@ function createDevLogRouter(options = {}) {
|
|
|
2454
2512
|
router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
|
|
2455
2513
|
router.get("/trace/recent", createGetRecentTracesHandler(logDir));
|
|
2456
2514
|
router.get("/files/:fileName", createGetLogFileHandler(logDir));
|
|
2457
|
-
router.get("/
|
|
2458
|
-
router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
|
|
2515
|
+
router.get("/server-logs", createGetServerLogsHandler(logDir));
|
|
2459
2516
|
router.get("/health", createHealthCheckHandler());
|
|
2460
2517
|
return router;
|
|
2461
2518
|
}
|
|
@@ -2480,13 +2537,8 @@ var DEV_LOGS_ROUTES = [
|
|
|
2480
2537
|
},
|
|
2481
2538
|
{
|
|
2482
2539
|
method: "GET",
|
|
2483
|
-
path: "/
|
|
2484
|
-
description: "Get
|
|
2485
|
-
},
|
|
2486
|
-
{
|
|
2487
|
-
method: "GET",
|
|
2488
|
-
path: "/trace/trigger/:instanceID",
|
|
2489
|
-
description: "Get trigger detail (automation trigger) in trace.log by instanceID"
|
|
2540
|
+
path: "/server-logs",
|
|
2541
|
+
description: "Get server logs in ServerLog format (compatible with frontend)"
|
|
2490
2542
|
}
|
|
2491
2543
|
];
|
|
2492
2544
|
function createDevLogsMiddleware(options = {}) {
|