Correct misaligned instance names on forwarded log messages

The instance name on a log line is whatever the host sent, so a host can
attribute a line for one of its own instances to the wrong name. Compare
it with the name the controller has on record and replace it when they
differ.

Host connections can live for days, so the warning suppression expires
after five minutes instead of latching for the life of the connection,
and the bogus instance and misaligned name warnings share it so the two
together cannot spam the log.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
bbassieandClaude Opus 5 committed 2026-09-13 17:09:53 +00:00
1 parent cf4e85c6ee
commit 70c823ae9f
2 files changed
+106 -20

No files matched your search

+67 -5
View File
@@ -21,15 +21,20 @@ class MockSaves {
deleteMany(saves) { for (const s of saves) { this.saves.delete(s.id); } }
}
// Mock instances manager where instance id -> assigned host id.
function makeInstances(assignments) {
// Mock instances manager where instance id -> assigned host id, and
// optionally instance id -> the name the controller has on record.
function makeInstances(assignments, names = new Map()) {
return {
get(id) {
if (!assignments.has(id)) {
return undefined;
}
const host = assignments.get(id);
return { config: { get: name => (name === "instance.assigned_host" ? host : undefined) } };
return { config: { get(field) {
if (field === "instance.assigned_host") { return host; }
if (field === "instance.name") { return names.get(id); }
return undefined;
} } };
},
};
}
@@ -80,16 +85,34 @@ describe("controller/src/HostConnection", function() {
describe(".handleLogMessageEvent()", function() {
// Instance 1 is on host 10, instance 2 is on host 20.
const assignments = new Map([[1, 10], [2, 20]]);
const names = new Map([[1, "one"], [2, "two"]]);
function run(hostId, info) {
let warnings = [];
let originalWarn;
beforeEach(function() {
warnings = [];
originalWarn = lib.logger.warn;
lib.logger.warn = msg => { warnings.push(msg); };
});
afterEach(function() {
lib.logger.warn = originalWarn;
});
// Handlers call other methods on this, so inherit the prototype.
function makeConnection(hostId) {
const logged = [];
const ctx = Object.assign(Object.create(HostConnection.prototype), {
info: { id: hostId, name: `host-${hostId}` },
_controller: {
instances: makeInstances(assignments),
instances: makeInstances(assignments, names),
clusterLogger: { log(entry) { logged.push(entry); } },
},
});
return [ctx, logged];
}
function run(hostId, info) {
const [ctx, logged] = makeConnection(hostId);
ctx.handleLogMessageEvent(new lib.LogMessageEvent(info));
return logged;
}
@@ -100,6 +123,45 @@ describe("controller/src/HostConnection", function() {
level: "info", message: "hello", instance_id: 1, instance_name: "one",
host_id: 10, host_name: "host-10",
}]);
assert.deepEqual(warnings, [], "a matching name must not warn");
});
it("corrects an instance name which does not match the controller", async function() {
const logged = run(10, { level: "info", message: "hi", instance_id: 1, instance_name: "wrong" });
assert.deepEqual(logged, [{
level: "info", message: "hi", instance_id: 1, instance_name: "one",
host_id: 10, host_name: "host-10",
}]);
assert.equal(warnings.length, 1, "a misaligned name must warn");
});
it("warns about a misaligned name again after five minutes", async function() {
const [ctx, logged] = makeConnection(10);
const info = { level: "info", message: "hi", instance_id: 1, instance_name: "wrong" };
ctx.handleLogMessageEvent(new lib.LogMessageEvent(info));
ctx.handleLogMessageEvent(new lib.LogMessageEvent(info));
assert.equal(warnings.length, 1, "the warning must not repeat immediately");
// Pretend the last warning happened just over five minutes ago.
ctx._lastLogMessageWarnMs -= 5 * 60 * 1000 + 1;
ctx.handleLogMessageEvent(new lib.LogMessageEvent(info));
assert.equal(warnings.length, 2, "the warning must resurface after the timeout");
assert.equal(logged.length, 3);
assert.deepEqual(logged.map(e => e.instance_name), ["one", "one", "one"]);
});
it("shares the warning suppression between bogus id and misaligned name", async function() {
const [ctx, logged] = makeConnection(10);
// Instance 2 is on host 20, so this line is bogus.
ctx.handleLogMessageEvent(new lib.LogMessageEvent(
{ level: "info", message: "hi", instance_id: 2, instance_name: "two" }
));
assert.equal(warnings.length, 1);
ctx.handleLogMessageEvent(new lib.LogMessageEvent(
{ level: "info", message: "hi", instance_id: 1, instance_name: "wrong" }
));
assert.equal(warnings.length, 1, "both warnings must share the suppression");
assert.equal(logged[1].instance_name, "one", "the name is still corrected while suppressed");
});
it("logs host level messages unchanged", async function() {