Buckets:
| import { Formatter, Logger, type LogLevel } from "effect" | |
| import path from "path" | |
| import { Global } from "../global" | |
| import { runID } from "./shared" | |
| function formatter(id: string = runID) { | |
| return Logger.map(Logger.formatStructured, (output) => { | |
| const messages = Array.isArray(output.message) ? output.message : [output.message] | |
| return [ | |
| ["timestamp", output.timestamp], | |
| ["level", output.level], | |
| ["run", id], | |
| ...messages.flatMap((value) => (plain(value) ? flatten(value) : [["message", value] as const])), | |
| ...(output.cause === undefined ? [] : [["cause", output.cause] as const]), | |
| ...flatten(output.spans), | |
| ...flatten(output.annotations), | |
| ] | |
| .map(([key, value]) => `${key}=${format(value)}`) | |
| .join(" ") | |
| }) | |
| } | |
| function flatten( | |
| input: Record<string, unknown>, | |
| prefix = "", | |
| seen = new WeakSet<object>(), | |
| ): Array<readonly [string, unknown]> { | |
| if (seen.has(input)) return [[prefix, "[Circular]"]] | |
| seen.add(input) | |
| const entries = Object.entries(input) | |
| if (entries.length === 0 && prefix) return [[prefix, input]] | |
| return entries.flatMap(([key, value]) => { | |
| const path = prefix ? `${prefix}.${key}` : key | |
| return plain(value) ? flatten(value, path, seen) : [[path, value] as const] | |
| }) | |
| } | |
| function plain(input: unknown): input is Record<string, unknown> { | |
| if (input === null || typeof input !== "object" || Array.isArray(input)) return false | |
| const prototype = Object.getPrototypeOf(input) | |
| return prototype === Object.prototype || prototype === null | |
| } | |
| function format(input: unknown) { | |
| const value = typeof input === "string" ? input : Formatter.format(input) | |
| return /^[^\s="\\]+$/.test(value) ? value : JSON.stringify(value) | |
| } | |
| export function fileLogger(file = path.join(Global.Path.log, "opencode.log"), id: string = runID) { | |
| // Do not set batchWindow to 0; it causes high idle CPU usage. | |
| return Logger.toFile(formatter(id), file, { flag: "a" }) | |
| } | |
| const stderrLogger = Logger.make((options) => process.stderr.write(formatter().log(options) + "\n")) | |
| export function minimumLogLevel() { | |
| const value = process.env.OPENCODE_LOG_LEVEL?.toUpperCase() | |
| const levels = { | |
| DEBUG: "Debug", | |
| INFO: "Info", | |
| WARN: "Warn", | |
| ERROR: "Error", | |
| } as const satisfies Record<string, LogLevel.LogLevel> | |
| return value && value in levels ? levels[value as keyof typeof levels] : levels.INFO | |
| } | |
| export function loggers() { | |
| return process.env.OPENCODE_PRINT_LOGS === "1" ? [fileLogger(), stderrLogger] : [fileLogger()] | |
| } | |
| export * as Logging from "./logging" | |
Xet Storage Details
- Size:
- 2.56 kB
- Xet hash:
- 693cc9fb35553990797f888335c7fe1a00f12ce0fd85534db3cf60f470e1c780
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.