[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
96
electron/plugins/pluginLogger.cjs
Normal file
96
electron/plugins/pluginLogger.cjs
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("node:fs/promises");
|
||||
const path = require("node:path");
|
||||
|
||||
const { PLUGIN_LOG_MAX_BYTES, PLUGIN_LOG_MAX_FILES } = require("./constants.cjs");
|
||||
const { assertPluginStorageSegment } = require("./paths.cjs");
|
||||
|
||||
const SENSITIVE_KEY = /(?:password|passwd|token|secret|private.?key|credential|authorization|cookie)/iu;
|
||||
|
||||
function redactLogValue(value, key = "", depth = 0) {
|
||||
if (SENSITIVE_KEY.test(key)) return "[REDACTED]";
|
||||
if (depth >= 8) return "[TRUNCATED]";
|
||||
if (value == null || typeof value === "boolean" || typeof value === "number") return value;
|
||||
if (typeof value === "string") return value.slice(0, 2_048);
|
||||
if (Array.isArray(value)) {
|
||||
const output = [];
|
||||
for (let index = 0; index < Math.min(value.length, 64); index += 1) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
||||
output.push(descriptor && "value" in descriptor
|
||||
? redactLogValue(descriptor.value, "", depth + 1)
|
||||
: "[UNAVAILABLE]");
|
||||
}
|
||||
return output;
|
||||
}
|
||||
if (typeof value === "object") {
|
||||
const output = {};
|
||||
for (const entryKey of Object.keys(value).slice(0, 64)) {
|
||||
if (SENSITIVE_KEY.test(entryKey)) {
|
||||
output[entryKey.slice(0, 128)] = "[REDACTED]";
|
||||
continue;
|
||||
}
|
||||
const descriptor = Object.getOwnPropertyDescriptor(value, entryKey);
|
||||
output[entryKey.slice(0, 128)] = descriptor && "value" in descriptor
|
||||
? redactLogValue(descriptor.value, entryKey, depth + 1)
|
||||
: "[UNAVAILABLE]";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
return "[UNSUPPORTED]";
|
||||
}
|
||||
|
||||
class PluginLogger {
|
||||
constructor(options) {
|
||||
this.pluginId = assertPluginStorageSegment(options.pluginId, "ID");
|
||||
this.directory = path.join(options.logsDirectory, this.pluginId);
|
||||
this.maxBytes = options.maxBytes ?? PLUGIN_LOG_MAX_BYTES;
|
||||
this.maxFiles = options.maxFiles ?? PLUGIN_LOG_MAX_FILES;
|
||||
this.maxPendingBytes = options.maxPendingBytes ?? Math.min(this.maxBytes, 256 * 1024);
|
||||
this.pendingBytes = 0;
|
||||
this.queue = Promise.resolve();
|
||||
}
|
||||
|
||||
write(level, message, fields) {
|
||||
const record = JSON.stringify({
|
||||
timestamp: new Date().toISOString(),
|
||||
level: ["debug", "info", "warn", "error"].includes(level) ? level : "info",
|
||||
message: String(message ?? "").slice(0, 2_048),
|
||||
...(fields === undefined ? {} : { fields: redactLogValue(fields) }),
|
||||
});
|
||||
const line = `${record}\n`;
|
||||
const bytes = Buffer.byteLength(line);
|
||||
if (this.pendingBytes + bytes > this.maxPendingBytes) return Promise.resolve();
|
||||
this.pendingBytes += bytes;
|
||||
this.queue = this.queue
|
||||
.then(() => this.#append(line))
|
||||
.catch(() => {})
|
||||
.finally(() => { this.pendingBytes -= bytes; });
|
||||
return this.queue;
|
||||
}
|
||||
|
||||
async #append(line) {
|
||||
await fs.mkdir(this.directory, { recursive: true, mode: 0o700 });
|
||||
const activePath = path.join(this.directory, "runtime.log");
|
||||
let size = 0;
|
||||
try { size = (await fs.stat(activePath)).size; } catch {}
|
||||
if (size + Buffer.byteLength(line) > this.maxBytes) await this.#rotate();
|
||||
await fs.appendFile(activePath, line, { encoding: "utf8", mode: 0o600 });
|
||||
}
|
||||
|
||||
async #rotate() {
|
||||
await fs.rm(path.join(this.directory, `runtime.${this.maxFiles}.log`), { force: true });
|
||||
for (let index = this.maxFiles - 1; index >= 1; index -= 1) {
|
||||
try {
|
||||
await fs.rename(
|
||||
path.join(this.directory, index === 1 ? "runtime.log" : `runtime.${index - 1}.log`),
|
||||
path.join(this.directory, `runtime.${index}.log`),
|
||||
);
|
||||
} catch (error) {
|
||||
if (error?.code !== "ENOENT") throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { PluginLogger, redactLogValue };
|
||||
Reference in New Issue
Block a user