113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import { TelemetryCollector } from '../src/telemetry.js';
|
|
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
|
|
describe('TelemetryCollector', () => {
|
|
let tmpDir: string;
|
|
|
|
beforeEach(() => {
|
|
tmpDir = path.join(os.tmpdir(), `waggle-telemetry-test-${Date.now()}`);
|
|
fs.mkdirSync(tmpDir, { recursive: true });
|
|
});
|
|
|
|
it('records events when enabled', () => {
|
|
const collector = new TelemetryCollector(tmpDir, true);
|
|
collector.recordToolUse('web_search');
|
|
collector.recordToolUse('web_search');
|
|
collector.recordToolUse('save_memory');
|
|
|
|
const report = collector.getReport();
|
|
expect(report.totalEvents).toBe(3);
|
|
const webSearch = report.events.find(e => e.name === 'web_search');
|
|
expect(webSearch?.count).toBe(2);
|
|
});
|
|
|
|
it('silently drops events when disabled', () => {
|
|
const collector = new TelemetryCollector(tmpDir, false);
|
|
collector.recordToolUse('web_search');
|
|
collector.recordCommand('/research');
|
|
collector.recordError('timeout');
|
|
|
|
const report = collector.getReport();
|
|
expect(report.totalEvents).toBe(0);
|
|
});
|
|
|
|
it('no PII in collected data — tool names only', () => {
|
|
const collector = new TelemetryCollector(tmpDir, true);
|
|
collector.recordToolUse('connector_github_create_issue');
|
|
collector.recordError('api_timeout');
|
|
collector.recordCapabilityGap('email sending');
|
|
|
|
const report = collector.getReport();
|
|
for (const event of report.events) {
|
|
// Only category, name, count, date — no message content or file paths
|
|
expect(Object.keys(event).sort()).toEqual(['category', 'count', 'date', 'name']);
|
|
}
|
|
});
|
|
|
|
it('daily aggregation: same-day events merge counts', () => {
|
|
const collector = new TelemetryCollector(tmpDir, true);
|
|
collector.recordToolUse('bash');
|
|
collector.recordToolUse('bash');
|
|
collector.recordToolUse('bash');
|
|
|
|
const report = collector.getReport();
|
|
const bashEvents = report.events.filter(e => e.name === 'bash');
|
|
expect(bashEvents).toHaveLength(1);
|
|
expect(bashEvents[0].count).toBe(3);
|
|
});
|
|
|
|
it('flush writes to telemetry.json', () => {
|
|
const collector = new TelemetryCollector(tmpDir, true);
|
|
collector.recordToolUse('search_memory');
|
|
collector.flush();
|
|
|
|
const filePath = path.join(tmpDir, 'telemetry.json');
|
|
expect(fs.existsSync(filePath)).toBe(true);
|
|
|
|
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
expect(data).toHaveLength(1);
|
|
expect(data[0].name).toBe('search_memory');
|
|
|
|
collector.close();
|
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('report covers last N days', () => {
|
|
const collector = new TelemetryCollector(tmpDir, true);
|
|
collector.recordToolUse('today_tool');
|
|
|
|
const report = collector.getReport(7);
|
|
expect(report.events.length).toBeGreaterThan(0);
|
|
expect(report.dateRange.from).toBeTruthy();
|
|
});
|
|
|
|
it('setEnabled toggles collection', () => {
|
|
const collector = new TelemetryCollector(tmpDir, false);
|
|
expect(collector.isEnabled()).toBe(false);
|
|
|
|
collector.setEnabled(true);
|
|
expect(collector.isEnabled()).toBe(true);
|
|
|
|
collector.recordToolUse('test_tool');
|
|
expect(collector.getReport().totalEvents).toBe(1);
|
|
});
|
|
|
|
it('recordSession aggregates duration and interaction count', () => {
|
|
const collector = new TelemetryCollector(tmpDir, true);
|
|
collector.recordSession(30000, 15);
|
|
collector.recordSession(20000, 10);
|
|
|
|
const report = collector.getReport();
|
|
const duration = report.events.find(e => e.name === 'duration_total_ms');
|
|
const interactions = report.events.find(e => e.name === 'interaction_count');
|
|
const sessions = report.events.find(e => e.name === 'session_count');
|
|
|
|
expect(duration?.count).toBe(50000);
|
|
expect(interactions?.count).toBe(25);
|
|
expect(sessions?.count).toBe(2);
|
|
});
|
|
});
|