Download packages/core/src/telemetry/startupProfiler.test.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 12.5 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/core/src/telemetry/startupProfiler.test.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/core/src/telemetry/startupProfiler.test.ts
-
curl -L -o startupProfiler.test.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/core/src/telemetry/startupProfiler.test.ts
12.5 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; | |
| import { StartupProfiler } from './startupProfiler.js'; | |
| import type { Config } from '../config/config.js'; | |
| import { debugLogger } from '../utils/debugLogger.js'; | |
| // Mock the metrics module | |
| vi.mock('./metrics.js', () => ({ | |
| recordStartupPerformance: vi.fn(), | |
| })); | |
| // Mock loggers module | |
| vi.mock('./loggers.js', () => ({ | |
| logStartupStats: vi.fn(), | |
| })); | |
| // Mock os module | |
| vi.mock('node:os', () => ({ | |
| platform: vi.fn(() => 'darwin'), | |
| arch: vi.fn(() => 'x64'), | |
| release: vi.fn(() => '22.6.0'), | |
| })); | |
| // Mock fs module | |
| vi.mock('node:fs', () => ({ | |
| existsSync: vi.fn(() => false), | |
| createWriteStream: vi.fn(() => ({ | |
| write: vi.fn(), | |
| on: vi.fn(), | |
| })), | |
| })); | |
| describe('StartupProfiler', () => { | |
| let profiler: StartupProfiler; | |
| let mockConfig: Config; | |
| let recordStartupPerformance: ReturnType<typeof vi.fn>; | |
| let logStartupStats: ReturnType<typeof vi.fn>; | |
| beforeEach(async () => { | |
| vi.resetAllMocks(); | |
| // Get the mocked function | |
| const metricsModule = await import('./metrics.js'); | |
| recordStartupPerformance = | |
| metricsModule.recordStartupPerformance as ReturnType<typeof vi.fn>; | |
| const loggersModule = await import('./loggers.js'); | |
| logStartupStats = loggersModule.logStartupStats as ReturnType<typeof vi.fn>; | |
| // Create a fresh profiler instance | |
| profiler = StartupProfiler.getInstance(); | |
| // Clear any existing phases and performance entries | |
| profiler['phases'].clear(); | |
| performance.clearMarks(); | |
| performance.clearMeasures(); | |
| mockConfig = { | |
| getSessionId: () => 'test-session-id', | |
| getTelemetryEnabled: () => true, | |
| } as unknown as Config; | |
| }); | |
| afterEach(() => { | |
| vi.restoreAllMocks(); | |
| }); | |
| describe('getInstance', () => { | |
| it('should return a singleton instance', () => { | |
| const instance1 = StartupProfiler.getInstance(); | |
| const instance2 = StartupProfiler.getInstance(); | |
| expect(instance1).toBe(instance2); | |
| }); | |
| }); | |
| describe('start', () => { | |
| it('should create a performance mark for a phase', () => { | |
| profiler.start('test_phase'); | |
| const phase = profiler['phases'].get('test_phase'); | |
| expect(phase).toBeDefined(); | |
| expect(phase?.name).toBe('test_phase'); | |
| // Verify performance mark was created | |
| const marks = performance.getEntriesByType('mark'); | |
| const startMark = marks.find( | |
| (m) => m.name === 'startup:test_phase:start', | |
| ); | |
| expect(startMark).toBeDefined(); | |
| }); | |
| it('should record start time with details', () => { | |
| const details = { key: 'value', count: 42 }; | |
| profiler.start('test_phase', details); | |
| const phase = profiler['phases'].get('test_phase'); | |
| expect(phase?.details).toEqual(details); | |
| }); | |
| it('should return undefined when starting a phase that is already active', () => { | |
| profiler.start('test_phase'); | |
| const handle = profiler.start('test_phase'); | |
| expect(handle).toBeUndefined(); | |
| }); | |
| }); | |
| describe('end', () => { | |
| it('should create a performance measure for a started phase', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| // Verify performance measure was created | |
| const measures = performance.getEntriesByType('measure'); | |
| const measure = measures.find((m) => m.name === 'test_phase'); | |
| expect(measure).toBeDefined(); | |
| expect(measure?.duration).toBeGreaterThan(0); | |
| }); | |
| it('should merge details when ending a phase', () => { | |
| const handle = profiler.start('test_phase', { initial: 'value' }); | |
| handle?.end({ additional: 'data' }); | |
| const phase = profiler['phases'].get('test_phase'); | |
| expect(phase?.details).toEqual({ | |
| initial: 'value', | |
| additional: 'data', | |
| }); | |
| }); | |
| it('should overwrite details with same key', () => { | |
| const handle = profiler.start('test_phase', { key: 'original' }); | |
| handle?.end({ key: 'updated' }); | |
| const phase = profiler['phases'].get('test_phase'); | |
| expect(phase?.details).toEqual({ key: 'updated' }); | |
| }); | |
| }); | |
| describe('flush', () => { | |
| it('should call recordStartupPerformance for each completed phase', () => { | |
| const handle1 = profiler.start('phase1'); | |
| handle1?.end(); | |
| const handle2 = profiler.start('phase2'); | |
| handle2?.end(); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).toHaveBeenCalledTimes(2); | |
| }); | |
| it('should not record phases without duration', () => { | |
| profiler.start('incomplete_phase'); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).not.toHaveBeenCalled(); | |
| }); | |
| it('should include common details in all metrics', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.any(Number), | |
| expect.objectContaining({ | |
| phase: 'test_phase', | |
| details: expect.objectContaining({ | |
| os_platform: 'darwin', | |
| os_arch: 'x64', | |
| os_release: '22.6.0', | |
| is_docker: false, | |
| cpu_usage_user: expect.any(Number), | |
| cpu_usage_system: expect.any(Number), | |
| }), | |
| }), | |
| ); | |
| }); | |
| it('should merge phase-specific details with common details', () => { | |
| const handle = profiler.start('test_phase', { custom: 'value' }); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.any(Number), | |
| expect.objectContaining({ | |
| phase: 'test_phase', | |
| details: expect.objectContaining({ | |
| custom: 'value', | |
| os_platform: 'darwin', | |
| }), | |
| }), | |
| ); | |
| }); | |
| it('should clear phases after flushing', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(profiler['phases'].size).toBe(0); | |
| }); | |
| it('should detect Docker environment', async () => { | |
| const fs = await import('node:fs'); | |
| (fs.existsSync as ReturnType<typeof vi.fn>).mockReturnValue(true); | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.any(Number), | |
| expect.objectContaining({ | |
| details: expect.objectContaining({ | |
| is_docker: true, | |
| }), | |
| }), | |
| ); | |
| }); | |
| it('should calculate CPU usage correctly', () => { | |
| const cpuUsageSpy = vi.spyOn(process, 'cpuUsage'); | |
| // Mock start usage | |
| cpuUsageSpy.mockReturnValueOnce({ user: 1000, system: 500 }); | |
| // Mock diff usage (this is what process.cpuUsage(startUsage) returns) | |
| cpuUsageSpy.mockReturnValueOnce({ user: 100, system: 50 }); | |
| const handle = profiler.start('cpu_test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.any(Number), | |
| expect.objectContaining({ | |
| phase: 'cpu_test_phase', | |
| details: expect.objectContaining({ | |
| cpu_usage_user: 100, | |
| cpu_usage_system: 50, | |
| }), | |
| }), | |
| ); | |
| }); | |
| it('should use debug logging instead of standard logging', () => { | |
| const logSpy = vi.spyOn(debugLogger, 'log'); | |
| const debugSpy = vi.spyOn(debugLogger, 'debug'); | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(logSpy).not.toHaveBeenCalled(); | |
| expect(debugSpy).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('integration scenarios', () => { | |
| it('should handle a complete startup profiling workflow', () => { | |
| // Simulate startup sequence | |
| const totalHandle = profiler.start('total_startup'); | |
| const settingsHandle = profiler.start('load_settings'); | |
| settingsHandle?.end(); | |
| const argsHandle = profiler.start('parse_arguments'); | |
| argsHandle?.end(); | |
| const appHandle = profiler.start('initialize_app'); | |
| appHandle?.end(); | |
| totalHandle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).toHaveBeenCalledTimes(4); | |
| expect(recordStartupPerformance).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.any(Number), | |
| expect.objectContaining({ phase: 'total_startup' }), | |
| ); | |
| }); | |
| it('should handle nested timing correctly', () => { | |
| const outerHandle = profiler.start('outer'); | |
| const innerHandle = profiler.start('inner'); | |
| innerHandle?.end(); | |
| outerHandle?.end(); | |
| profiler.flush(mockConfig); | |
| const calls = recordStartupPerformance.mock.calls; | |
| const outerCall = calls.find((call) => call[2].phase === 'outer'); | |
| const innerCall = calls.find((call) => call[2].phase === 'inner'); | |
| expect(outerCall).toBeDefined(); | |
| expect(innerCall).toBeDefined(); | |
| // Outer duration should be >= inner duration | |
| expect(outerCall![1]).toBeGreaterThanOrEqual(innerCall![1]); | |
| }); | |
| }); | |
| describe('sanity checking', () => { | |
| it('should return undefined when starting a phase that is already active', () => { | |
| profiler.start('test_phase'); | |
| const handle = profiler.start('test_phase'); | |
| expect(handle).toBeUndefined(); | |
| }); | |
| it('should allow restarting a phase after it has ended', () => { | |
| const handle1 = profiler.start('test_phase'); | |
| handle1?.end(); | |
| // Should not throw | |
| expect(() => profiler.start('test_phase')).not.toThrow(); | |
| }); | |
| it('should not throw error when ending a phase that is already ended', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| // Calling end() again on the same handle should not throw | |
| expect(() => handle?.end()).not.toThrow(); | |
| }); | |
| it('should not record metrics for incomplete phases', () => { | |
| profiler.start('incomplete_phase'); | |
| // Never call end() | |
| profiler.flush(mockConfig); | |
| expect(recordStartupPerformance).not.toHaveBeenCalled(); | |
| }); | |
| it('should handle mix of complete and incomplete phases', () => { | |
| const completeHandle = profiler.start('complete_phase'); | |
| completeHandle?.end(); | |
| profiler.start('incomplete_phase'); | |
| // Never call end() | |
| profiler.flush(mockConfig); | |
| // Should only record the complete phase | |
| expect(recordStartupPerformance).toHaveBeenCalledTimes(1); | |
| expect(recordStartupPerformance).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.any(Number), | |
| expect.objectContaining({ phase: 'complete_phase' }), | |
| ); | |
| }); | |
| it('should log startup stats event', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| expect(logStartupStats).toHaveBeenCalledWith( | |
| mockConfig, | |
| expect.objectContaining({ | |
| phases: expect.arrayContaining([ | |
| expect.objectContaining({ | |
| name: 'test_phase', | |
| duration_ms: expect.any(Number), | |
| start_time_usec: expect.any(Number), | |
| end_time_usec: expect.any(Number), | |
| }), | |
| ]), | |
| os_platform: 'darwin', | |
| os_release: '22.6.0', | |
| is_docker: false, | |
| }), | |
| ); | |
| }); | |
| it('should log startup stats timestamps as rounded integers', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| const statsEvent = logStartupStats.mock.calls[0][1]; | |
| const phase = statsEvent.phases[0]; | |
| // Verify they are integers | |
| expect(Number.isInteger(phase.start_time_usec)).toBe(true); | |
| expect(Number.isInteger(phase.end_time_usec)).toBe(true); | |
| }); | |
| it('should log startup stats duration as rounded integers', () => { | |
| const handle = profiler.start('test_phase'); | |
| handle?.end(); | |
| profiler.flush(mockConfig); | |
| const statsEvent = logStartupStats.mock.calls[0][1]; | |
| const phase = statsEvent.phases[0]; | |
| // Verify they are integers | |
| expect(Number.isInteger(phase.duration_ms)).toBe(true); | |
| }); | |
| }); | |
| }); | |