Skip to content

Commit da56861

Browse files
feat: cLog
1 parent 1132af4 commit da56861

File tree

3 files changed

+578
-143
lines changed

3 files changed

+578
-143
lines changed

lib/compress-logger.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import * as fs from "fs"
2+
import * as path from "path"
3+
4+
// =============================================================================
5+
// Dedicated compress diagnostics logger for DCP
6+
// Buffered async file writes, always-on when compress is invoked
7+
// Logs to .logs/dcp-compress.log relative to cwd
8+
// =============================================================================
9+
10+
const LOG_DIR = path.join(process.cwd(), ".logs")
11+
const LOG_FILE = path.join(LOG_DIR, "dcp-compress.log")
12+
const WRITE_INTERVAL_MS = 100
13+
const MAX_DATA_CHARS = 20000
14+
15+
let buffer: string[] = []
16+
let scheduled = false
17+
let initialized = false
18+
19+
function init(): boolean {
20+
if (initialized) return true
21+
try {
22+
if (!fs.existsSync(LOG_DIR)) {
23+
fs.mkdirSync(LOG_DIR, { recursive: true })
24+
}
25+
fs.writeFileSync(LOG_FILE, "")
26+
initialized = true
27+
return true
28+
} catch {
29+
return false
30+
}
31+
}
32+
33+
async function flush(): Promise<void> {
34+
if (buffer.length === 0) {
35+
scheduled = false
36+
return
37+
}
38+
const chunk = buffer.join("")
39+
buffer = []
40+
scheduled = false
41+
try {
42+
await fs.promises.appendFile(LOG_FILE, chunk)
43+
} catch {}
44+
}
45+
46+
function schedule(): void {
47+
if (!scheduled) {
48+
scheduled = true
49+
setTimeout(flush, WRITE_INTERVAL_MS)
50+
}
51+
}
52+
53+
type Level = "DEBUG" | "INFO" | "WARN" | "ERROR"
54+
55+
function truncate(str: string, max: number): string {
56+
if (str.length <= max) return str
57+
return `${str.substring(0, max)}...`
58+
}
59+
60+
function formatNumber(n: number): string {
61+
return n.toLocaleString("en-US")
62+
}
63+
64+
function indent(lines: string, spaces: number): string {
65+
const prefix = " ".repeat(spaces)
66+
return lines
67+
.split("\n")
68+
.map((line) => (line ? prefix + line : ""))
69+
.join("\n")
70+
}
71+
72+
function formatValue(value: unknown, depth = 0): string {
73+
if (value === null) return "null"
74+
if (value === undefined) return "undefined"
75+
if (typeof value === "boolean") return value ? "true" : "false"
76+
if (typeof value === "number") return formatNumber(value)
77+
if (typeof value === "string") {
78+
if (value.length > 120) {
79+
return `"${truncate(value, 120)}"`
80+
}
81+
return `"${value}"`
82+
}
83+
84+
if (Array.isArray(value)) {
85+
if (value.length === 0) return "[]"
86+
if (depth > 3) {
87+
return `[${value.length} items]`
88+
}
89+
const items = value
90+
.slice(0, 10)
91+
.map((v) => `- ${formatValue(v, depth + 1)}`)
92+
.join("\n")
93+
const omitted = value.length > 10 ? `\n... (${value.length - 10} more)` : ""
94+
return `\n${indent(items, 2)}${omitted}`
95+
}
96+
97+
if (typeof value === "object") {
98+
const entries = Object.entries(value)
99+
if (entries.length === 0) return "{}"
100+
if (depth > 3) {
101+
return `{${entries.length} keys}`
102+
}
103+
const lines = entries
104+
.slice(0, 15)
105+
.map(([k, v]) => `${k}: ${formatValue(v, depth + 1)}`)
106+
.join("\n")
107+
const omitted = entries.length > 15 ? `\n... (${entries.length - 15} more)` : ""
108+
return `\n${indent(lines, 2)}${omitted}`
109+
}
110+
111+
return String(value)
112+
}
113+
114+
function write(level: Level, category: string, message: string, data?: unknown): void {
115+
if (!init()) return
116+
const ts = new Date().toISOString()
117+
let output = `[${ts}] [${level}] [${category}]\n${indent(message, 2)}`
118+
if (data !== undefined) {
119+
const formatted = formatValue(data)
120+
output += `\n${indent(formatted, 2)}`
121+
}
122+
buffer.push(`${output}\n\n`)
123+
schedule()
124+
}
125+
126+
export const clog = {
127+
debug: (category: string, message: string, data?: unknown) =>
128+
write("DEBUG", category, message, data),
129+
info: (category: string, message: string, data?: unknown) =>
130+
write("INFO", category, message, data),
131+
warn: (category: string, message: string, data?: unknown) =>
132+
write("WARN", category, message, data),
133+
error: (category: string, message: string, data?: unknown) =>
134+
write("ERROR", category, message, data),
135+
flush,
136+
}
137+
138+
export const C = {
139+
COMPRESS: "COMPRESS",
140+
BOUNDARY: "BOUNDARY",
141+
STATE: "STATE",
142+
} as const

0 commit comments

Comments
 (0)