@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.js
CHANGED
|
@@ -2095,229 +2095,147 @@ async function readLogFilePage(filePath, page, pageSize) {
|
|
|
2095
2095
|
};
|
|
2096
2096
|
}
|
|
2097
2097
|
__name(readLogFilePage, "readLogFilePage");
|
|
2098
|
-
async function
|
|
2099
|
-
|
|
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
|
-
}
|
|
2098
|
+
async function readTriggerList(filePath, trigger, path7, limit) {
|
|
2099
|
+
if (!await fileExists(filePath)) {
|
|
2123
2100
|
return void 0;
|
|
2124
2101
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
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
|
|
2102
|
+
const config = {
|
|
2103
|
+
maxEntriesPerTrace: 10,
|
|
2104
|
+
chunkSize: 64 * 1024
|
|
2136
2105
|
};
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
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) {
|
|
2106
|
+
const builders = /* @__PURE__ */ new Map();
|
|
2107
|
+
const completedCalls = [];
|
|
2108
|
+
const createTraceBuilder = /* @__PURE__ */ __name((traceId) => ({
|
|
2109
|
+
traceId,
|
|
2110
|
+
entries: [],
|
|
2111
|
+
method: void 0,
|
|
2112
|
+
path: void 0,
|
|
2113
|
+
startTime: void 0,
|
|
2114
|
+
endTime: void 0,
|
|
2115
|
+
statusCode: void 0,
|
|
2116
|
+
durationMs: void 0,
|
|
2117
|
+
hasCompleted: false
|
|
2118
|
+
}), "createTraceBuilder");
|
|
2119
|
+
const shouldIncludeInCompletedCalls = /* @__PURE__ */ __name((builder) => {
|
|
2120
|
+
const alreadyAdded = completedCalls.some((call) => call.traceId === builder.traceId);
|
|
2121
|
+
if (alreadyAdded) {
|
|
2122
|
+
return false;
|
|
2123
|
+
}
|
|
2124
|
+
if (!builder.hasCompleted) {
|
|
2125
|
+
return false;
|
|
2126
|
+
}
|
|
2127
|
+
const isAutomationTrigger = builder.path?.endsWith(path7);
|
|
2128
|
+
if (!isAutomationTrigger) {
|
|
2129
|
+
return false;
|
|
2130
|
+
}
|
|
2131
|
+
if (trigger && builder.entries.length > 0) {
|
|
2132
|
+
const requestEntry = builder.entries.find((e) => e.request_body?.trigger);
|
|
2133
|
+
if (requestEntry?.request_body?.trigger) {
|
|
2134
|
+
return String(requestEntry.request_body.trigger) === trigger;
|
|
2182
2135
|
}
|
|
2136
|
+
return false;
|
|
2183
2137
|
}
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
if (
|
|
2189
|
-
|
|
2138
|
+
return true;
|
|
2139
|
+
}, "shouldIncludeInCompletedCalls");
|
|
2140
|
+
const updateBuilderMetadata = /* @__PURE__ */ __name((builder, entry) => {
|
|
2141
|
+
if (entry.method && !builder.method) builder.method = String(entry.method);
|
|
2142
|
+
if (entry.path && !builder.path) builder.path = String(entry.path);
|
|
2143
|
+
builder.entries.push(entry);
|
|
2144
|
+
if (builder.entries.length > config.maxEntriesPerTrace) {
|
|
2145
|
+
builder.entries.shift();
|
|
2190
2146
|
}
|
|
2191
|
-
if (
|
|
2192
|
-
|
|
2147
|
+
if (shouldIncludeInCompletedCalls(builder)) {
|
|
2148
|
+
completedCalls.push(builder);
|
|
2149
|
+
if (limit && completedCalls.length > limit) {
|
|
2150
|
+
completedCalls.shift();
|
|
2151
|
+
}
|
|
2193
2152
|
}
|
|
2194
|
-
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
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;
|
|
2230
|
-
}
|
|
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
|
-
};
|
|
2253
|
-
}
|
|
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();
|
|
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);
|
|
2261
2161
|
}
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2162
|
+
if (shouldIncludeInCompletedCalls(builder)) {
|
|
2163
|
+
completedCalls.push(builder);
|
|
2164
|
+
if (limit && completedCalls.length > limit) {
|
|
2165
|
+
completedCalls.shift();
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}, "handleRequestCompleted");
|
|
2169
|
+
const processLogEntry = /* @__PURE__ */ __name((entry) => {
|
|
2170
|
+
const { trace_id: traceId, message = "" } = entry;
|
|
2171
|
+
if (!traceId) return;
|
|
2172
|
+
let builder = builders.get(traceId);
|
|
2173
|
+
if (!builder) {
|
|
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;
|
|
2183
|
+
}
|
|
2184
|
+
}, "processLogEntry");
|
|
2185
|
+
const processLine = /* @__PURE__ */ __name((line) => {
|
|
2186
|
+
const entry = parseLogLine2(line);
|
|
2187
|
+
if (entry?.trace_id) {
|
|
2188
|
+
processLogEntry(entry);
|
|
2189
|
+
}
|
|
2190
|
+
}, "processLine");
|
|
2191
|
+
await readFileReverse(filePath, config.chunkSize, processLine);
|
|
2266
2192
|
return {
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
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
|
+
}))
|
|
2281
2207
|
};
|
|
2282
2208
|
}
|
|
2283
|
-
__name(
|
|
2284
|
-
function
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
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);
|
|
2209
|
+
__name(readTriggerList, "readTriggerList");
|
|
2210
|
+
async function readTriggerDetail(filePath, path7, instanceID) {
|
|
2211
|
+
const exists = await fileExists(filePath);
|
|
2212
|
+
if (!exists) {
|
|
2213
|
+
return void 0;
|
|
2214
|
+
}
|
|
2215
|
+
const matches = [];
|
|
2216
|
+
const stream = createReadStream(filePath, {
|
|
2217
|
+
encoding: "utf8"
|
|
2318
2218
|
});
|
|
2219
|
+
const rl = createInterface({
|
|
2220
|
+
input: stream,
|
|
2221
|
+
crlfDelay: Infinity
|
|
2222
|
+
});
|
|
2223
|
+
for await (const line of rl) {
|
|
2224
|
+
const entry = parseLogLine2(line);
|
|
2225
|
+
if (!entry) continue;
|
|
2226
|
+
const isAutomationTrigger = entry.path?.endsWith(path7);
|
|
2227
|
+
const hasInstanceID = entry.message?.includes(`instanceID=${instanceID}`);
|
|
2228
|
+
if (!isAutomationTrigger || !hasInstanceID) continue;
|
|
2229
|
+
matches.push(entry);
|
|
2230
|
+
}
|
|
2231
|
+
rl.close();
|
|
2232
|
+
stream.close();
|
|
2233
|
+
return {
|
|
2234
|
+
instanceID,
|
|
2235
|
+
entries: matches
|
|
2236
|
+
};
|
|
2319
2237
|
}
|
|
2320
|
-
__name(
|
|
2238
|
+
__name(readTriggerDetail, "readTriggerDetail");
|
|
2321
2239
|
|
|
2322
2240
|
// src/middlewares/dev-logs/controller.ts
|
|
2323
2241
|
function handleNotFound(res, filePath, message = "Log file not found") {
|
|
@@ -2411,32 +2329,58 @@ function createGetLogFileHandler(logDir) {
|
|
|
2411
2329
|
};
|
|
2412
2330
|
}
|
|
2413
2331
|
__name(createGetLogFileHandler, "createGetLogFileHandler");
|
|
2414
|
-
function
|
|
2332
|
+
function createGetTriggerListHandler(logDir) {
|
|
2333
|
+
const traceLogPath = join3(logDir, "trace.log");
|
|
2415
2334
|
return async (req, res) => {
|
|
2416
|
-
const
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2335
|
+
const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
|
|
2336
|
+
if (!trigger) {
|
|
2337
|
+
return res.status(400).json({
|
|
2338
|
+
message: "trigger is required"
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2342
|
+
const limit = parseLimit(req.query.limit, 10, 200);
|
|
2420
2343
|
try {
|
|
2421
|
-
const result = await
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2344
|
+
const result = await readTriggerList(traceLogPath, trigger, path7, limit);
|
|
2345
|
+
if (!result) {
|
|
2346
|
+
return handleNotFound(res, traceLogPath);
|
|
2347
|
+
}
|
|
2348
|
+
res.json({
|
|
2349
|
+
file: getRelativePath(traceLogPath),
|
|
2350
|
+
path: path7,
|
|
2351
|
+
...result
|
|
2426
2352
|
});
|
|
2353
|
+
} catch (error) {
|
|
2354
|
+
handleError(res, error, "Failed to read trace log");
|
|
2355
|
+
}
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
__name(createGetTriggerListHandler, "createGetTriggerListHandler");
|
|
2359
|
+
function createGetTriggerDetailHandler(logDir) {
|
|
2360
|
+
const traceLogPath = join3(logDir, "server.log");
|
|
2361
|
+
return async (req, res) => {
|
|
2362
|
+
const instanceID = (req.params.instanceID || "").trim();
|
|
2363
|
+
if (!instanceID) {
|
|
2364
|
+
return res.status(400).json({
|
|
2365
|
+
message: "instanceID is required"
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2368
|
+
const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2369
|
+
try {
|
|
2370
|
+
const result = await readTriggerDetail(traceLogPath, path7, instanceID);
|
|
2427
2371
|
if (!result) {
|
|
2428
|
-
return res
|
|
2429
|
-
message: "No server log files found",
|
|
2430
|
-
hint: "Expected files: server.log, trace.log, server.std.log, client.std.log"
|
|
2431
|
-
});
|
|
2372
|
+
return handleNotFound(res, traceLogPath);
|
|
2432
2373
|
}
|
|
2433
|
-
res.json(
|
|
2374
|
+
res.json({
|
|
2375
|
+
file: getRelativePath(traceLogPath),
|
|
2376
|
+
...result
|
|
2377
|
+
});
|
|
2434
2378
|
} catch (error) {
|
|
2435
|
-
handleError(res, error, "Failed to read
|
|
2379
|
+
handleError(res, error, "Failed to read trace log");
|
|
2436
2380
|
}
|
|
2437
2381
|
};
|
|
2438
2382
|
}
|
|
2439
|
-
__name(
|
|
2383
|
+
__name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
|
|
2440
2384
|
|
|
2441
2385
|
// src/middlewares/dev-logs/health.controller.ts
|
|
2442
2386
|
import http2 from "http";
|
|
@@ -2512,7 +2456,8 @@ function createDevLogRouter(options = {}) {
|
|
|
2512
2456
|
router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
|
|
2513
2457
|
router.get("/trace/recent", createGetRecentTracesHandler(logDir));
|
|
2514
2458
|
router.get("/files/:fileName", createGetLogFileHandler(logDir));
|
|
2515
|
-
router.get("/
|
|
2459
|
+
router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
|
|
2460
|
+
router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
|
|
2516
2461
|
router.get("/health", createHealthCheckHandler());
|
|
2517
2462
|
return router;
|
|
2518
2463
|
}
|
|
@@ -2537,8 +2482,13 @@ var DEV_LOGS_ROUTES = [
|
|
|
2537
2482
|
},
|
|
2538
2483
|
{
|
|
2539
2484
|
method: "GET",
|
|
2540
|
-
path: "/
|
|
2541
|
-
description: "Get
|
|
2485
|
+
path: "/trace/trigger/list",
|
|
2486
|
+
description: "Get trigger list (automation trigger) in trace.log"
|
|
2487
|
+
},
|
|
2488
|
+
{
|
|
2489
|
+
method: "GET",
|
|
2490
|
+
path: "/trace/trigger/:instanceID",
|
|
2491
|
+
description: "Get trigger detail (automation trigger) in trace.log by instanceID"
|
|
2542
2492
|
}
|
|
2543
2493
|
];
|
|
2544
2494
|
function createDevLogsMiddleware(options = {}) {
|