mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 01:31:08 +00:00
refactor: simplify gateway startup logs
This commit is contained in:
@@ -27,13 +27,14 @@ const gatewayLog = createSubsystemLogger("gateway");
|
||||
type GatewayRunSignalAction = "stop" | "restart";
|
||||
|
||||
export async function runGatewayLoop(params: {
|
||||
start: () => Promise<Awaited<ReturnType<typeof startGatewayServer>>>;
|
||||
start: (params?: {
|
||||
startupStartedAt?: number;
|
||||
}) => Promise<Awaited<ReturnType<typeof startGatewayServer>>>;
|
||||
runtime: RuntimeEnv;
|
||||
lockPort?: number;
|
||||
}) {
|
||||
gatewayLog.info("acquiring gateway lock...");
|
||||
let startupStartedAt = Date.now();
|
||||
let lock = await acquireGatewayLock({ port: params.lockPort });
|
||||
gatewayLog.info("gateway lock acquired");
|
||||
let server: Awaited<ReturnType<typeof startGatewayServer>> | null = null;
|
||||
let shuttingDown = false;
|
||||
let restartResolver: (() => void) | null = null;
|
||||
@@ -57,6 +58,7 @@ export async function runGatewayLoop(params: {
|
||||
};
|
||||
const reacquireLockForInProcessRestart = async (): Promise<boolean> => {
|
||||
try {
|
||||
startupStartedAt = Date.now();
|
||||
lock = await acquireGatewayLock({ port: params.lockPort });
|
||||
return true;
|
||||
} catch (err) {
|
||||
@@ -231,7 +233,7 @@ export async function runGatewayLoop(params: {
|
||||
for (;;) {
|
||||
onIteration();
|
||||
try {
|
||||
server = await params.start();
|
||||
server = await params.start({ startupStartedAt });
|
||||
isFirstStart = false;
|
||||
} catch (err) {
|
||||
// On initial startup, let the error propagate so the outer handler
|
||||
|
||||
@@ -457,16 +457,17 @@ async function runGatewayCommand(opts: GatewayRunOpts) {
|
||||
}
|
||||
: undefined;
|
||||
|
||||
gatewayLog.info("starting gateway…");
|
||||
gatewayLog.info("starting...");
|
||||
const startLoop = async () =>
|
||||
await runGatewayLoop({
|
||||
runtime: defaultRuntime,
|
||||
lockPort: port,
|
||||
start: async () =>
|
||||
start: async ({ startupStartedAt } = {}) =>
|
||||
await startGatewayServer(port, {
|
||||
bind,
|
||||
auth: authOverride,
|
||||
tailscale: tailscaleOverride,
|
||||
startupStartedAt,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { logGatewayStartup } from "./server-startup-log.js";
|
||||
|
||||
describe("gateway startup log", () => {
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("warns when dangerous config flags are enabled", () => {
|
||||
const info = vi.fn();
|
||||
const warn = vi.fn();
|
||||
@@ -15,6 +19,7 @@ describe("gateway startup log", () => {
|
||||
},
|
||||
},
|
||||
bindHost: "127.0.0.1",
|
||||
pluginCount: 0,
|
||||
port: 18789,
|
||||
log: { info, warn },
|
||||
isNixMode: false,
|
||||
@@ -35,6 +40,7 @@ describe("gateway startup log", () => {
|
||||
logGatewayStartup({
|
||||
cfg: {},
|
||||
bindHost: "127.0.0.1",
|
||||
pluginCount: 0,
|
||||
port: 18789,
|
||||
log: { info, warn },
|
||||
isNixMode: false,
|
||||
@@ -43,7 +49,10 @@ describe("gateway startup log", () => {
|
||||
expect(warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("logs all listen endpoints on a single line", () => {
|
||||
it("logs a compact ready line with plugin count and duration", () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-04-03T10:00:16.000Z"));
|
||||
|
||||
const info = vi.fn();
|
||||
const warn = vi.fn();
|
||||
|
||||
@@ -51,16 +60,16 @@ describe("gateway startup log", () => {
|
||||
cfg: {},
|
||||
bindHost: "127.0.0.1",
|
||||
bindHosts: ["127.0.0.1", "::1"],
|
||||
pluginCount: 8,
|
||||
port: 18789,
|
||||
startupStartedAt: Date.parse("2026-04-03T10:00:00.000Z"),
|
||||
log: { info, warn },
|
||||
isNixMode: false,
|
||||
});
|
||||
|
||||
const listenMessages = info.mock.calls
|
||||
const readyMessages = info.mock.calls
|
||||
.map((call) => call[0])
|
||||
.filter((message) => message.startsWith("listening on "));
|
||||
expect(listenMessages).toEqual([
|
||||
`listening on ws://127.0.0.1:18789, ws://[::1]:18789 (PID ${process.pid})`,
|
||||
]);
|
||||
.filter((message) => message.startsWith("ready ("));
|
||||
expect(readyMessages).toEqual(["ready (8 plugins, 16.0s)"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,8 @@ export function logGatewayStartup(params: {
|
||||
bindHost: string;
|
||||
bindHosts?: string[];
|
||||
port: number;
|
||||
pluginCount: number;
|
||||
startupStartedAt?: number;
|
||||
tlsEnabled?: boolean;
|
||||
log: { info: (msg: string, meta?: Record<string, unknown>) => void; warn: (msg: string) => void };
|
||||
isNixMode: boolean;
|
||||
@@ -23,12 +25,13 @@ export function logGatewayStartup(params: {
|
||||
params.log.info(`agent model: ${modelRef}`, {
|
||||
consoleMessage: `agent model: ${chalk.whiteBright(modelRef)}`,
|
||||
});
|
||||
const scheme = params.tlsEnabled ? "wss" : "ws";
|
||||
const formatHost = (host: string) => (host.includes(":") ? `[${host}]` : host);
|
||||
const hosts =
|
||||
params.bindHosts && params.bindHosts.length > 0 ? params.bindHosts : [params.bindHost];
|
||||
const listenEndpoints = hosts.map((host) => `${scheme}://${formatHost(host)}:${params.port}`);
|
||||
params.log.info(`listening on ${listenEndpoints.join(", ")} (PID ${process.pid})`);
|
||||
const startupDurationMs =
|
||||
typeof params.startupStartedAt === "number" ? Date.now() - params.startupStartedAt : null;
|
||||
const startupDurationLabel =
|
||||
startupDurationMs == null ? null : `${(startupDurationMs / 1000).toFixed(1)}s`;
|
||||
params.log.info(
|
||||
`ready (${params.pluginCount} ${params.pluginCount === 1 ? "plugin" : "plugins"}${startupDurationLabel ? `, ${startupDurationLabel}` : ""})`,
|
||||
);
|
||||
params.log.info(`log file: ${getResolvedLoggerSettings().file}`);
|
||||
if (params.isNixMode) {
|
||||
params.log.info("gateway: running in Nix mode (config managed externally)");
|
||||
|
||||
@@ -373,6 +373,10 @@ export type GatewayServerOptions = {
|
||||
runtime: import("../runtime.js").RuntimeEnv,
|
||||
prompter: import("../wizard/prompts.js").WizardPrompter,
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* Optional startup timestamp used for concise readiness logging.
|
||||
*/
|
||||
startupStartedAt?: number;
|
||||
};
|
||||
|
||||
export async function startGatewayServer(
|
||||
@@ -606,7 +610,6 @@ export async function startGatewayServer(
|
||||
let pluginRegistry = emptyPluginRegistry;
|
||||
let baseGatewayMethods = baseMethods;
|
||||
if (!minimalTestGateway) {
|
||||
log.info("loading plugins...");
|
||||
({ pluginRegistry, gatewayMethods: baseGatewayMethods } = loadGatewayStartupPlugins({
|
||||
cfg: gatewayPluginConfigAtStart,
|
||||
workspaceDir: defaultWorkspaceDir,
|
||||
@@ -616,7 +619,6 @@ export async function startGatewayServer(
|
||||
pluginIds: startupPluginIds,
|
||||
preferSetupRuntimeForChannelPlugins: deferredConfiguredChannelPluginIds.length > 0,
|
||||
}));
|
||||
log.info(`plugins loaded (${pluginRegistry.plugins.length} plugins)`);
|
||||
} else {
|
||||
setActivePluginRegistry(emptyPluginRegistry);
|
||||
}
|
||||
@@ -1340,8 +1342,10 @@ export async function startGatewayServer(
|
||||
bindHosts: httpBindHosts,
|
||||
port,
|
||||
tlsEnabled: gatewayTls.enabled,
|
||||
pluginCount: pluginRegistry.plugins.length,
|
||||
log,
|
||||
isNixMode,
|
||||
startupStartedAt: opts.startupStartedAt,
|
||||
});
|
||||
stopGatewayUpdateCheck = minimalTestGateway
|
||||
? () => {}
|
||||
|
||||
Reference in New Issue
Block a user