

























@@ -166,12 +166,14 @@ function createTraceOnlyContext(endpoint: string): OpenClawPluginServiceContext
166166type RegisteredLogTransport = (logObj: Record<string, unknown>) => void;
167167function setupRegisteredTransports() {
168168const registeredTransports: RegisteredLogTransport[] = [];
169-const stopTransport = vi.fn();
169+const stopTransports: ReturnType<typeof vi.fn>[] = [];
170170registerLogTransportMock.mockImplementation((transport) => {
171171registeredTransports.push(transport);
172+const stopTransport = vi.fn();
173+stopTransports.push(stopTransport);
172174return stopTransport;
173175});
174-return { registeredTransports, stopTransport };
176+return { registeredTransports, stopTransports };
175177}
176178177179async function emitAndCaptureLog(logObj: Record<string, unknown>) {
@@ -283,6 +285,73 @@ describe("diagnostics-otel service", () => {
283285await service.stop?.(ctx);
284286});
285287288+test("restarts without retaining prior listeners or log transports", async () => {
289+const { registeredTransports, stopTransports } = setupRegisteredTransports();
290+291+const service = createDiagnosticsOtelService();
292+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true, logs: true });
293+await service.start(ctx);
294+await service.start(ctx);
295+296+expect(registerLogTransportMock).toHaveBeenCalledTimes(2);
297+expect(registeredTransports).toHaveLength(2);
298+expect(stopTransports[0]).toHaveBeenCalledTimes(1);
299+expect(logShutdown).toHaveBeenCalledTimes(1);
300+expect(sdkShutdown).toHaveBeenCalledTimes(1);
301+302+telemetryState.tracer.startSpan.mockClear();
303+emitDiagnosticEvent({
304+type: "message.processed",
305+channel: "telegram",
306+outcome: "completed",
307+durationMs: 10,
308+});
309+expect(telemetryState.tracer.startSpan).toHaveBeenCalledTimes(1);
310+311+await service.stop?.(ctx);
312+expect(stopTransports[1]).toHaveBeenCalledTimes(1);
313+expect(logShutdown).toHaveBeenCalledTimes(2);
314+expect(sdkShutdown).toHaveBeenCalledTimes(2);
315+316+telemetryState.tracer.startSpan.mockClear();
317+emitDiagnosticEvent({
318+type: "message.processed",
319+channel: "telegram",
320+outcome: "completed",
321+durationMs: 10,
322+});
323+expect(telemetryState.tracer.startSpan).not.toHaveBeenCalled();
324+});
325+326+test("tears down active handles when restarted with diagnostics disabled", async () => {
327+const { stopTransports } = setupRegisteredTransports();
328+329+const service = createDiagnosticsOtelService();
330+const enabledCtx = createOtelContext(OTEL_TEST_ENDPOINT, {
331+traces: true,
332+metrics: true,
333+logs: true,
334+});
335+await service.start(enabledCtx);
336+await service.start({
337+ ...enabledCtx,
338+config: { diagnostics: { enabled: false } },
339+});
340+341+expect(stopTransports[0]).toHaveBeenCalledTimes(1);
342+expect(logShutdown).toHaveBeenCalledTimes(1);
343+expect(sdkShutdown).toHaveBeenCalledTimes(1);
344+345+telemetryState.tracer.startSpan.mockClear();
346+emitDiagnosticEvent({
347+type: "message.processed",
348+channel: "telegram",
349+outcome: "completed",
350+durationMs: 10,
351+});
352+expect(telemetryState.tracer.startSpan).not.toHaveBeenCalled();
353+});
354+286355test("appends signal path when endpoint contains non-signal /v1 segment", async () => {
287356const service = createDiagnosticsOtelService();
288357const ctx = createTraceOnlyContext("https://www.comet.com/opik/api/v1/private/otel");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。