Skip to content

Commit 2bcafc8

Browse files
Memtensor-AIMemOS AutoDevjiachengzhen
authored
test(logging): verify standalone bootstrap writes memos.log (#2147) (#2150)
* fix(local-plugin): call initLogger in bootstrapMemoryCoreFull `bootstrapMemoryCoreFull` in `apps/memos-local-plugin/core/pipeline/memory-core.ts` never invoked `initLogger(config, home)` after `loadConfig(home)`. The logger stayed in the `bootstrapConsoleOnly()` fallback (console + memory buffer + SSE broadcast only), so the `FileRotatingTransport` / `JsonlEventsTransport` sinks were never wired and `MEMOS_HOME/logs/` (memos.log, error.log, audit.log, llm.jsonl, perf.jsonl, events.jsonl) was left empty even though `config.logging.file.enabled` defaults to true. The fix adds `initLogger` to the logger import and calls it after the config is resolved and before the first `rootLogger.child(...)` call. `initLogger` is idempotent and swaps the active root in place, so existing child handles keep working. A new regression test `tests/unit/pipeline/bootstrap-init-logger.test.ts` boots the pipeline against a tmp home, emits a marker line, and asserts that `memos.log` is created on disk and contains the marker. It fails on the previous code (ENOENT for memos.log) and passes with this fix. Fixes #2147 * style(hermes): format daemon manager --------- Co-authored-by: MemOS AutoDev <autodev@memtensor.local> Co-authored-by: jiachengzhen <jiacz@memtensor.cn>
1 parent 44fc2b5 commit 2bcafc8

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

apps/memos-local-plugin/adapters/hermes/memos_provider/daemon_manager.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ def _rebuild_if_stale() -> bool:
215215
return False
216216

217217

218-
219218
def ensure_bridge_running(*, probe_only: bool = False) -> bool:
220219
"""Return True when the bridge is (or can be) operational.
221220
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Regression test for issue #2147:
3+
* The standalone bridge must request logger initialization after config is
4+
* resolved so file transports (memos.log, error.log, audit.log, llm.jsonl,
5+
* perf.jsonl, events.jsonl) are created on disk. Before the fix, the bridge
6+
* left the logger in `bootstrapConsoleOnly()` mode, so `home.logsDir` remained
7+
* empty even though `config.logging.file.enabled` defaults to `true`.
8+
*
9+
* The assertion is deliberately tight: emit a distinctive marker line
10+
* through `rootLogger.child(...)` after bootstrap, flush the logger, then
11+
* confirm the marker landed in `memos.log`. Any regression that leaves the
12+
* console-only sinks in place would make `memos.log` either missing or
13+
* marker-free.
14+
*/
15+
16+
import { afterEach, describe, expect, it } from "vitest";
17+
import { promises as fs } from "node:fs";
18+
import { join } from "node:path";
19+
20+
import { makeTmpHome, type TmpHomeContext } from "../../helpers/tmp-home.js";
21+
import { bootstrapMemoryCoreFull } from "../../../core/pipeline/memory-core.js";
22+
import {
23+
initTestLogger,
24+
rootLogger,
25+
shutdownLogger,
26+
} from "../../../core/logger/index.js";
27+
import type { MemoryCore } from "../../../agent-contract/memory-core.js";
28+
29+
describe("bootstrapMemoryCoreFull -> initLogger", () => {
30+
let home: TmpHomeContext | null = null;
31+
let core: MemoryCore | null = null;
32+
33+
afterEach(async () => {
34+
if (core) await core.shutdown();
35+
await shutdownLogger();
36+
if (home) await home.cleanup();
37+
core = null;
38+
home = null;
39+
initTestLogger();
40+
});
41+
42+
it("wires file transports when initLogging is set", async () => {
43+
home = await makeTmpHome({ agent: "openclaw" });
44+
45+
// Sanity check: fixture leaves logsDir empty before bootstrap.
46+
const before = await fs.readdir(home.home.logsDir);
47+
expect(before).toEqual([]);
48+
49+
const result = await bootstrapMemoryCoreFull({
50+
agent: "openclaw",
51+
home: home.home,
52+
config: home.config,
53+
pkgVersion: "issue-2147-test",
54+
initLogging: true,
55+
});
56+
core = result.core;
57+
58+
// Distinctive marker so we can grep memos.log without depending on
59+
// whichever config warnings bootstrap emitted.
60+
const marker = "issue-2147.marker.line.abcdef";
61+
rootLogger.child({ channel: "core.pipeline.bootstrap" }).info(marker, {
62+
probe: "bootstrap-init-logger",
63+
});
64+
await rootLogger.flush();
65+
66+
const memosLogPath = join(home.home.logsDir, "memos.log");
67+
const stat = await fs.stat(memosLogPath);
68+
expect(stat.isFile()).toBe(true);
69+
expect(stat.size).toBeGreaterThan(0);
70+
71+
const text = await fs.readFile(memosLogPath, "utf8");
72+
expect(text).toContain(marker);
73+
});
74+
});

0 commit comments

Comments
 (0)