mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-09 15:59:30 +00:00
fix(logging): keep bounded log text UTF-16 safe (#102560)
* fix(logging): use truncateUtf16Safe in diagnostic log text clamp Replace naive .slice(0, maxChars) with truncateUtf16Safe() in clampDiagnosticLogText() — the core helper used by all diagnostic log output (sanitizeDiagnosticLogText, formatDiagnosticAttributes, etc.). This prevents surrogate pair splitting across the entire diagnostic logging subsystem. Co-Authored-By: Claude <noreply@anthropic.com> * fix(logging): preserve UTF-16 in bounded log text --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
parent
f7cc6ebe1e
commit
0de5d37f92
3 changed files with 32 additions and 2 deletions
|
|
@ -143,6 +143,23 @@ describe("diagnostic log events", () => {
|
|||
expect(Object.hasOwn(event, "argsJson")).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps bounded diagnostic messages UTF-16 safe", async () => {
|
||||
const received: Array<Extract<DiagnosticEventPayload, { type: "log.record" }>> = [];
|
||||
const unsubscribe = onInternalDiagnosticEvent((event) => {
|
||||
if (event.type === "log.record") {
|
||||
received.push(event);
|
||||
}
|
||||
});
|
||||
const prefix = "x".repeat(4_095);
|
||||
|
||||
getChildLogger({ subsystem: "diagnostic" }).info(`${prefix}😀tail`);
|
||||
await flushDiagnosticEvents();
|
||||
unsubscribe();
|
||||
|
||||
// The post-redaction bound keeps the first dot from the initial truncation marker.
|
||||
expect(received.at(-1)?.message).toBe(`${prefix}....(truncated)`);
|
||||
});
|
||||
|
||||
it("drops sensitive, blocked, and excess log attribute keys without copying large objects", async () => {
|
||||
const received: Array<Extract<DiagnosticEventPayload, { type: "log.record" }>> = [];
|
||||
const unsubscribe = onInternalDiagnosticEvent((evt) => {
|
||||
|
|
|
|||
|
|
@ -192,6 +192,18 @@ describe("file log redaction", () => {
|
|||
expect(record.message).toBe("request completed");
|
||||
});
|
||||
|
||||
it("keeps bounded file-log messages UTF-16 safe", () => {
|
||||
const logPath = logPathTracker.nextPath();
|
||||
setLoggerOverride({ level: "info", file: logPath });
|
||||
const prefix = "x".repeat(4_095);
|
||||
|
||||
getLogger().info(`${prefix}😀tail`);
|
||||
|
||||
const [line] = fs.readFileSync(logPath, "utf8").trim().split("\n");
|
||||
const record = JSON.parse(line ?? "{}") as Record<string, unknown>;
|
||||
expect(record.message).toBe(`${prefix}...(truncated)`);
|
||||
});
|
||||
|
||||
it("retries hostname resolution after an empty value and caches the first real value", () => {
|
||||
const logPath = logPathTracker.nextPath();
|
||||
setLoggerOverride({ level: "info", file: logPath });
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
|
||||
import { Logger as TsLogger } from "tslog";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import {
|
||||
|
|
@ -90,7 +91,7 @@ let cachedHostname: string | null = null;
|
|||
type DiagnosticLogAttributes = Record<string, string | number | boolean>;
|
||||
|
||||
function clampDiagnosticLogText(value: string, maxChars: number): string {
|
||||
return value.length > maxChars ? `${value.slice(0, maxChars)}...(truncated)` : value;
|
||||
return value.length > maxChars ? `${truncateUtf16Safe(value, maxChars)}...(truncated)` : value;
|
||||
}
|
||||
|
||||
function sanitizeDiagnosticLogText(value: string, maxChars: number): string {
|
||||
|
|
@ -217,7 +218,7 @@ function getSortedNumericLogArgs(logObj: TsLogRecord): unknown[] {
|
|||
}
|
||||
|
||||
function clampFileLogText(value: string, maxChars: number): string {
|
||||
return value.length > maxChars ? `${value.slice(0, maxChars)}...(truncated)` : value;
|
||||
return value.length > maxChars ? `${truncateUtf16Safe(value, maxChars)}...(truncated)` : value;
|
||||
}
|
||||
|
||||
function normalizeFileLogContextValue(value: unknown): string | undefined {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue