cloudaxe-opencode/packages/opencode/src/util/log.ts

111 lines
2.9 KiB
TypeScript
Raw Normal View History

2025-05-31 18:41:00 +00:00
import path from "path"
import fs from "fs/promises"
import { Global } from "../global"
2025-05-18 01:31:42 +00:00
export namespace Log {
export const Default = create({ service: "default" })
2025-06-09 19:00:48 +00:00
export interface Options {
print: boolean
2025-05-31 18:41:00 +00:00
}
2025-05-18 18:28:08 +00:00
2025-06-09 19:00:48 +00:00
let logpath = ""
export function file() {
return logpath
}
export async function init(options: Options) {
const dir = path.join(Global.Path.data, "log")
await fs.mkdir(dir, { recursive: true })
cleanup(dir)
if (options.print) return
2025-06-27 02:30:44 +00:00
logpath = path.join(
dir,
new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log",
)
const logfile = Bun.file(logpath)
await fs.truncate(logpath).catch(() => {})
const writer = logfile.writer()
process.stderr.write = (msg) => {
writer.write(msg)
writer.flush()
return true
2025-05-31 18:41:00 +00:00
}
2025-05-18 18:28:08 +00:00
}
async function cleanup(dir: string) {
const entries = await fs.readdir(dir, { withFileTypes: true })
const files = entries
.filter((entry) => entry.isFile() && entry.name.endsWith(".log"))
.map((entry) => path.join(dir, entry.name))
2025-06-11 22:19:15 +00:00
if (files.length <= 5) return
const filesToDelete = files.slice(0, -10)
await Promise.all(
filesToDelete.map((file) => fs.unlink(file).catch(() => {})),
)
}
let last = Date.now()
2025-05-18 01:31:42 +00:00
export function create(tags?: Record<string, any>) {
2025-05-31 18:41:00 +00:00
tags = tags || {}
2025-05-18 01:31:42 +00:00
2025-05-18 18:13:04 +00:00
function build(message: any, extra?: Record<string, any>) {
const prefix = Object.entries({
...tags,
...extra,
})
2025-05-30 20:39:45 +00:00
.filter(([_, value]) => value !== undefined && value !== null)
2025-05-18 18:13:04 +00:00
.map(([key, value]) => `${key}=${value}`)
2025-05-31 18:41:00 +00:00
.join(" ")
const next = new Date()
const diff = next.getTime() - last
last = next.getTime()
2025-05-31 18:41:00 +00:00
return (
[next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message]
.filter(Boolean)
.join(" ") + "\n"
2025-05-31 18:41:00 +00:00
)
2025-05-18 18:13:04 +00:00
}
2025-05-18 01:31:42 +00:00
const result = {
info(message?: any, extra?: Record<string, any>) {
2025-06-20 04:57:28 +00:00
process.stderr.write("INFO " + build(message, extra))
2025-05-18 18:13:04 +00:00
},
error(message?: any, extra?: Record<string, any>) {
2025-06-20 04:57:28 +00:00
process.stderr.write("ERROR " + build(message, extra))
2025-05-18 01:31:42 +00:00
},
2025-05-31 22:42:43 +00:00
warn(message?: any, extra?: Record<string, any>) {
2025-06-20 04:57:28 +00:00
process.stderr.write("WARN " + build(message, extra))
2025-05-31 22:42:43 +00:00
},
2025-05-18 01:31:42 +00:00
tag(key: string, value: string) {
2025-05-31 18:41:00 +00:00
if (tags) tags[key] = value
return result
2025-05-18 01:31:42 +00:00
},
clone() {
2025-05-31 18:41:00 +00:00
return Log.create({ ...tags })
2025-05-18 01:31:42 +00:00
},
2025-06-15 17:33:24 +00:00
time(message: string, extra?: Record<string, any>) {
const now = Date.now()
result.info(message, { status: "started", ...extra })
function stop() {
result.info(message, {
status: "completed",
duration: Date.now() - now,
...extra,
})
}
return {
stop,
[Symbol.dispose]() {
stop()
},
}
},
2025-05-31 18:41:00 +00:00
}
2025-05-18 01:31:42 +00:00
2025-05-31 18:41:00 +00:00
return result
2025-05-18 01:31:42 +00:00
}
}