Skip to main content
Glama
IBM
by IBM
instrumentation.test.ts3.55 kB
/** * @fileoverview Tests for OpenTelemetry instrumentation. * @module tests/utils/telemetry/instrumentation.test */ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { NodeSDK } from "@opentelemetry/sdk-node"; // Mock dependencies const mockSpanProcessor = { onEnd: vi.fn(), shutdown: vi.fn().mockResolvedValue(undefined), forceFlush: vi.fn().mockResolvedValue(undefined), onStart: vi.fn(), constructor: { name: "FileSpanProcessor" }, }; vi.mock("@opentelemetry/sdk-node", () => { const NodeSDK = vi.fn(() => ({ start: vi.fn(), shutdown: vi.fn().mockResolvedValue(undefined), spanProcessors: [mockSpanProcessor], })); return { NodeSDK }; }); vi.mock("winston", () => { const mTransports = { File: vi.fn(), Console: vi.fn(), }; const mFormat = { combine: vi.fn(), timestamp: vi.fn(), json: vi.fn(), }; const mLogger = { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn(), verbose: vi.fn(), on: vi.fn().mockReturnThis(), end: vi.fn(), }; const createLoggerMock = vi.fn(() => mLogger); const winstonMock = { createLogger: createLoggerMock, format: mFormat, transports: mTransports, }; return { ...winstonMock, default: winstonMock, }; }); vi.mock("../../../src/config/index.js", () => ({ config: { openTelemetry: { enabled: true, serviceName: "test-service", serviceVersion: "1.0.0", logLevel: "INFO", samplingRatio: 1, tracesEndpoint: "", metricsEndpoint: "", }, logsPath: "/tmp/logs", environment: "test", }, })); describe("OpenTelemetry Instrumentation", () => { let instrumentation: typeof import("../../../src/utils/telemetry/instrumentation.js"); beforeEach(async () => { vi.resetModules(); instrumentation = await import( "../../../src/utils/telemetry/instrumentation.js" ); }); afterEach(() => { vi.clearAllMocks(); }); describe("FileSpanProcessor", () => { it("should log spans to a file", async () => { const readableSpan = { spanContext: () => ({ traceId: "trace1", spanId: "span1" }), name: "test-span", kind: 0, startTime: [100, 200], endTime: [101, 200], duration: [1, 0], status: { code: 0 }, attributes: {}, events: [], }; // We need to manually call the onEnd method of the processor that was created inside instrumentation.ts // The mockSpanProcessor is not the same instance, so we'll test the mock directly mockSpanProcessor.onEnd(readableSpan); // Verify that the span processor's onEnd method was called with the span expect(mockSpanProcessor.onEnd).toHaveBeenCalledWith(readableSpan); }); }); describe("SDK Initialization", () => { it("should initialize NodeSDK with correct parameters", () => { expect(NodeSDK).toHaveBeenCalledWith( expect.objectContaining({ sampler: expect.any(Object), resource: expect.any(Object), spanProcessors: expect.any(Array), }), ); }); }); describe("shutdownOpenTelemetry", () => { it("should call sdk.shutdown if sdk is initialized", async () => { const { sdk, shutdownOpenTelemetry } = instrumentation; const shutdownSpy = vi .spyOn(sdk as NodeSDK, "shutdown") .mockResolvedValue(undefined); await shutdownOpenTelemetry(); expect(shutdownSpy).toHaveBeenCalled(); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IBM/ibmi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server