UNPKG

@flanksource/clicky-ui

Version:

Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.

120 lines (119 loc) 4.56 kB
import { countThreadsByState, parseJvmThreadDump } from "./jvm-stacktrace.js"; function detectDumpFormat(text) { const trimmed = text.trim(); if (!trimmed) return "unknown"; if (/^"[^"]*"[^\n]*\b(prio=|tid=|nid=)/m.test(trimmed)) return "jvm"; if (/^goroutine\s+\d+\s+\[[^\]]+\]:/m.test(trimmed)) return "go"; return "unknown"; } function parseStackDump(text) { const format = detectDumpFormat(text); if (format === "jvm") { return { format: "jvm", threads: parseJvmThreadDump(text) }; } if (format === "go") { return { format: "go", goroutines: parseGoroutineDump(text) }; } return { format: "unknown", goroutines: [], threads: [] }; } function countStackByState(stack) { if (stack.format === "jvm") return countThreadsByState(stack.threads); if (stack.format === "go") return countGoroutinesByState(stack.goroutines); return /* @__PURE__ */ new Map(); } const headerRe = /^goroutine\s+(\d+)\s+\[(.+?)\]:$/; const fileRe = /^\s*(.+?):(\d+)(?:\s+\+0x[0-9a-f]+)?$/i; const goSrcPrefixRe = /^\/usr\/local\/go[\d.]+\/src\//; const goWorkspacePrefixRe = /^.*?\/go\/src\//; const goPkgModPrefixRe = /^.*?\/go\/pkg\/mod\//; function parseGoroutineDump(text) { var _a, _b; const trimmed = text.trim(); if (!trimmed) return []; const blocks = trimmed.split(/\n\s*\n+/); const goroutines = []; for (const block of blocks) { const lines = block.split("\n").map((line) => line.replace(/\r$/, "")); const header = (_a = lines[0]) == null ? void 0 : _a.trim(); const match = headerRe.exec(header || ""); if (!match) continue; const id = Number(match[1] ?? 0); const rawState = match[2] ?? ""; const state = normalizeState(rawState); const frames = []; for (let i = 1; i < lines.length; i++) { const line = lines[i]; if (line == null) continue; const trimmedLine = line.trim(); if (!trimmedLine) continue; const fileMatch = fileRe.exec(trimmedLine); const previousFrame = frames[frames.length - 1]; if (fileMatch && previousFrame && !previousFrame.file) { previousFrame.file = fileMatch[1] ?? ""; previousFrame.line = Number(fileMatch[2] ?? 0); continue; } const kind = trimmedLine.startsWith("created by ") ? "created_by" : "frame"; const functionName = kind === "created_by" ? trimmedLine.slice("created by ".length) : trimmedLine; frames.push({ functionName, displayName: sanitizeFunctionName(functionName), kind, runtime: isRuntimeFrame(functionName) }); } for (const frame of frames) { if (frame.file) { frame.file = normalizeFilePath(frame.file); frame.location = `${frame.file}${frame.line ? `:${frame.line}` : ""}`; } } const topFunction = (_b = frames.find((frame) => frame.kind === "frame")) == null ? void 0 : _b.functionName; goroutines.push({ id, state, rawState, frames, raw: block, userFrameCount: frames.filter((frame) => !frame.runtime && frame.kind === "frame").length, searchText: `${header} ${frames.map((frame) => `${frame.functionName} ${frame.file || ""}`).join("\n")}`.toLowerCase(), ...topFunction !== void 0 ? { topFunction } : {} }); } return goroutines; } function countGoroutinesByState(goroutines) { const counts = /* @__PURE__ */ new Map(); for (const goroutine of goroutines) { counts.set(goroutine.state, (counts.get(goroutine.state) || 0) + 1); } return counts; } function normalizeState(value) { return (value.split(",")[0] ?? "").trim().toLowerCase(); } function isRuntimeFrame(functionName) { return functionName.startsWith("runtime.") || functionName.startsWith("runtime/") || functionName.startsWith("internal/") || functionName.startsWith("runtime/internal/") || functionName.startsWith("syscall.") || functionName.startsWith("reflect."); } function sanitizeFunctionName(functionName) { let name = functionName.trim(); const paren = name.indexOf("("); if (paren !== -1) name = name.slice(0, paren); name = name.replace(/\.\(\*([^)]+)\)\./g, ".$1."); return stripPackageQualifier(name); } function stripPackageQualifier(name) { return name.replace(/^((?:[^./\s]+\/)+)([^./\s]+)\./, "$2."); } function normalizeFilePath(path) { return path.replace(goSrcPrefixRe, "").replace(goWorkspacePrefixRe, "").replace(goPkgModPrefixRe, ""); } export { countGoroutinesByState, countStackByState, detectDumpFormat, parseGoroutineDump, parseStackDump }; //# sourceMappingURL=stacktrace.js.map