

















@@ -41,6 +41,7 @@ type AcpRuntimeTurnResult = Awaited<AcpRuntimeTurn["result"]>;
4141const ENABLE_STARTUP_PROBE_ENV = "OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE";
4242const SKIP_RUNTIME_PROBE_ENV = "OPENCLAW_SKIP_ACPX_RUNTIME_PROBE";
4343const ACPX_BACKEND_ID = "acpx";
44+const ACPX_STARTUP_TRACE_PREFIX = "sidecars.plugin-services.acpx.acpx-runtime";
44454546type AcpxRuntimeModule = typeof import("./runtime.js");
4647let runtimeModulePromise: Promise<AcpxRuntimeModule> | null = null;
@@ -374,6 +375,24 @@ function resolveAllowedAgentsProbeAgent(ctx: OpenClawPluginServiceContext): stri
374375return undefined;
375376}
376377378+async function measureAcpxStartup<T>(
379+ctx: OpenClawPluginServiceContext,
380+name: string,
381+run: () => T | Promise<T>,
382+): Promise<T> {
383+return ctx.startupTrace
384+ ? await ctx.startupTrace.measure(`${ACPX_STARTUP_TRACE_PREFIX}.${name}`, run)
385+ : await run();
386+}
387+388+function detailAcpxStartup(
389+ctx: OpenClawPluginServiceContext,
390+name: string,
391+metrics: ReadonlyArray<readonly [string, number | string]>,
392+): void {
393+ctx.startupTrace?.detail?.(`${ACPX_STARTUP_TRACE_PREFIX}.${name}`, metrics);
394+}
395+377396function shouldRunStartupProbe(env: NodeJS.ProcessEnv = process.env): boolean {
378397return env[ENABLE_STARTUP_PROBE_ENV] !== "0";
379398}
@@ -490,29 +509,39 @@ export function createAcpxRuntimeService(
490509return;
491510}
492511493-const basePluginConfig = resolveAcpxPluginConfig({
494-rawConfig: params.pluginConfig,
495-workspaceDir: ctx.workspaceDir,
496-});
512+const basePluginConfig = await measureAcpxStartup(ctx, "config.resolve", () =>
513+resolveAcpxPluginConfig({
514+rawConfig: params.pluginConfig,
515+workspaceDir: ctx.workspaceDir,
516+}),
517+);
497518const effectiveBasePluginConfig: ResolvedAcpxPluginConfig = {
498519 ...basePluginConfig,
499520probeAgent: basePluginConfig.probeAgent ?? resolveAllowedAgentsProbeAgent(ctx),
500521};
501-const pluginConfig = await prepareAcpxCodexAuthConfig({
502-pluginConfig: effectiveBasePluginConfig,
503-stateDir: ctx.stateDir,
504-logger: ctx.logger,
505-});
522+const pluginConfig = await measureAcpxStartup(ctx, "config.prepare-codex-auth", () =>
523+prepareAcpxCodexAuthConfig({
524+pluginConfig: effectiveBasePluginConfig,
525+stateDir: ctx.stateDir,
526+logger: ctx.logger,
527+}),
528+);
506529const wrapperRoot = path.join(ctx.stateDir, "acpx");
507-await fs.mkdir(pluginConfig.stateDir, { recursive: true });
508-await fs.mkdir(wrapperRoot, { recursive: true });
509-const gatewayInstanceId = await resolveGatewayInstanceId(ctx.stateDir);
510-const processLeaseStore = createAcpxProcessLeaseStore({ stateDir: wrapperRoot });
511-const startupReap = await reapOpenAcpxProcessLeases({
512- gatewayInstanceId,
513-leaseStore: processLeaseStore,
514-deps: params.processCleanupDeps,
530+await measureAcpxStartup(ctx, "filesystem.prepare", async () => {
531+await fs.mkdir(pluginConfig.stateDir, { recursive: true });
532+await fs.mkdir(wrapperRoot, { recursive: true });
515533});
534+const gatewayInstanceId = await measureAcpxStartup(ctx, "gateway-instance-id", () =>
535+resolveGatewayInstanceId(ctx.stateDir),
536+);
537+const processLeaseStore = createAcpxProcessLeaseStore({ stateDir: wrapperRoot });
538+const startupReap = await measureAcpxStartup(ctx, "process-leases.reap", () =>
539+reapOpenAcpxProcessLeases({
540+ gatewayInstanceId,
541+leaseStore: processLeaseStore,
542+deps: params.processCleanupDeps,
543+}),
544+);
516545if (startupReap.terminatedPids.length > 0) {
517546ctx.logger.info(
518547`reaped ${startupReap.terminatedPids.length} stale OpenClaw-owned ACPX process${startupReap.terminatedPids.length === 1 ? "" : "es"}`,
@@ -523,29 +552,38 @@ export function createAcpxRuntimeService(
523552logger: ctx.logger,
524553});
525554526-runtime = params.runtimeFactory
527- ? await params.runtimeFactory({
528- pluginConfig,
529- gatewayInstanceId,
530- processLeaseStore,
531- wrapperRoot,
532-logger: ctx.logger,
533-})
534- : createLazyDefaultRuntime({
535- pluginConfig,
536- gatewayInstanceId,
537- processLeaseStore,
538- wrapperRoot,
539-logger: ctx.logger,
540-});
555+const startedRuntime = await measureAcpxStartup(ctx, "runtime.create", () =>
556+params.runtimeFactory
557+ ? params.runtimeFactory({
558+ pluginConfig,
559+ gatewayInstanceId,
560+ processLeaseStore,
561+ wrapperRoot,
562+logger: ctx.logger,
563+})
564+ : createLazyDefaultRuntime({
565+ pluginConfig,
566+ gatewayInstanceId,
567+ processLeaseStore,
568+ wrapperRoot,
569+logger: ctx.logger,
570+}),
571+);
572+runtime = startedRuntime;
541573542574const shouldProbeRuntime = shouldProbeRuntimeAtStartup();
543-registerAcpRuntimeBackend({
544-id: ACPX_BACKEND_ID,
545- runtime,
546- ...(shouldProbeRuntime ? { healthy: () => runtime?.isHealthy() ?? false } : {}),
575+detailAcpxStartup(ctx, "probe-policy", [
576+["startupProbeEnabledCount", shouldProbeRuntime ? 1 : 0],
577+["probeAgent", pluginConfig.probeAgent ?? "default"],
578+]);
579+await measureAcpxStartup(ctx, "backend.register", () => {
580+registerAcpRuntimeBackend({
581+id: ACPX_BACKEND_ID,
582+runtime: startedRuntime,
583+ ...(shouldProbeRuntime ? { healthy: () => runtime?.isHealthy() ?? false } : {}),
584+});
585+ctx.logger.info(`embedded acpx runtime backend registered (cwd: ${pluginConfig.cwd})`);
547586});
548-ctx.logger.info(`embedded acpx runtime backend registered (cwd: ${pluginConfig.cwd})`);
549587550588if (!shouldProbeRuntime) {
551589return;
@@ -554,30 +592,35 @@ export function createAcpxRuntimeService(
554592lifecycleRevision += 1;
555593const currentRevision = lifecycleRevision;
556594try {
557-if (runtime) {
558-await withStartupProbeTimeout({
559-promise: runtime.probeAvailability(),
595+await measureAcpxStartup(ctx, "probe.availability", () =>
596+withStartupProbeTimeout({
597+promise: startedRuntime.probeAvailability(),
560598timeoutSeconds: pluginConfig.timeoutSeconds ?? DEFAULT_ACPX_TIMEOUT_SECONDS,
561-});
562-}
599+}),
600+);
563601if (currentRevision !== lifecycleRevision) {
564602return;
565603}
566-if (runtime?.isHealthy()) {
604+if (startedRuntime.isHealthy()) {
605+detailAcpxStartup(ctx, "probe.result", [["healthyCount", 1]]);
567606ctx.logger.info("embedded acpx runtime backend ready");
568607return;
569608}
570-const doctorReport = await runtime?.doctor?.();
609+const doctorReport = await measureAcpxStartup(ctx, "probe.doctor", () =>
610+startedRuntime.doctor?.(),
611+);
571612if (currentRevision !== lifecycleRevision) {
572613return;
573614}
615+detailAcpxStartup(ctx, "probe.result", [["healthyCount", 0]]);
574616ctx.logger.warn(
575617`embedded acpx runtime backend probe failed: ${doctorReport ? formatDoctorFailureMessage(doctorReport) : "backend remained unhealthy after probe"}`,
576618);
577619} catch (err) {
578620if (currentRevision !== lifecycleRevision) {
579621return;
580622}
623+detailAcpxStartup(ctx, "probe.result", [["healthyCount", 0]]);
581624ctx.logger.warn(`embedded acpx runtime setup failed: ${formatErrorMessage(err)}`);
582625}
583626},
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。