Path: blob/main/extensions/copilot/src/platform/otel/common/test/serviceRobustness.spec.ts
13406 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { describe, expect, it } from 'vitest';6import { SpanStatusCode } from '../otelService';7import { CapturingOTelService } from './capturingOTelService';89/**10* Tests service robustness: buffer cap behavior, runWithTraceContext propagation,11* and capturing service correctness.12*/13describe('OTel Service Robustness', () => {1415describe('CapturingOTelService basics', () => {16it('reset clears all captured data', () => {17const otel = new CapturingOTelService();1819otel.startSpan('test', { attributes: {} });20otel.recordMetric('m', 1);21otel.incrementCounter('c');22otel.emitLogRecord('log');2324otel.reset();2526expect(otel.spans).toHaveLength(0);27expect(otel.metrics).toHaveLength(0);28expect(otel.counters).toHaveLength(0);29expect(otel.logRecords).toHaveLength(0);30});3132it('findSpans filters by name prefix', () => {33const otel = new CapturingOTelService();3435otel.startSpan('chat gpt-4o', { attributes: {} });36otel.startSpan('chat claude', { attributes: {} });37otel.startSpan('execute_tool read', { attributes: {} });3839expect(otel.findSpans('chat')).toHaveLength(2);40expect(otel.findSpans('execute_tool')).toHaveLength(1);41expect(otel.findSpans('invoke_agent')).toHaveLength(0);42});43});4445describe('runWithTraceContext', () => {46it('executes the function and returns its result', async () => {47const otel = new CapturingOTelService();48const ctx = { traceId: 'aaaa0000bbbb1111cccc2222dddd3333', spanId: 'eeee4444ffff5555' };4950const result = await otel.runWithTraceContext(ctx, async () => {51return 42;52});5354expect(result).toBe(42);55});5657it('propagates errors from the wrapped function', async () => {58const otel = new CapturingOTelService();59const ctx = { traceId: '00000000000000000000000000000000', spanId: '0000000000000000' };6061await expect(otel.runWithTraceContext(ctx, async () => {62throw new Error('test error');63})).rejects.toThrow('test error');64});65});6667describe('startActiveSpan lifecycle', () => {68it('ends span even when fn throws', async () => {69const otel = new CapturingOTelService();7071await expect(otel.startActiveSpan('test', { attributes: {} }, async () => {72throw new Error('boom');73})).rejects.toThrow('boom');7475expect(otel.spans[0].ended).toBe(true);76});7778it('returns fn result on success', async () => {79const otel = new CapturingOTelService();8081const result = await otel.startActiveSpan('test', { attributes: {} }, async (span) => {82span.setStatus(SpanStatusCode.OK);83return 'hello';84});8586expect(result).toBe('hello');87expect(otel.spans[0].statusCode).toBe(SpanStatusCode.OK);88});89});9091describe('storeTraceContext edge cases', () => {92it('overwriting a key replaces the context', () => {93const otel = new CapturingOTelService();94const ctx1 = { traceId: 'aaaa', spanId: 'bbbb' };95const ctx2 = { traceId: 'cccc', spanId: 'dddd' };9697otel.storeTraceContext('key', ctx1);98otel.storeTraceContext('key', ctx2);99100expect(otel.getStoredTraceContext('key')).toEqual(ctx2);101});102});103});104105106