mirror of
https://github.com/Kaelio/ktx.git
synced 2026-07-19 11:41:02 +02:00
feat(telemetry): collect PostHog $exception error reports in CLI and daemon (#262)
* feat(telemetry): add node exception reporter * feat(telemetry): report node cli exceptions * feat(telemetry): add daemon exception reporter * feat(telemetry): report daemon exceptions * docs(telemetry): document error reports * fix(telemetry): pass redaction snapshots from node call sites * test(telemetry): verify prepared node exception payload * fix(telemetry): close daemon exception lifecycle gaps * test(telemetry): verify prepared daemon exception payload * test(telemetry): close error collection acceptance gaps * test(telemetry): close posthog exception acceptance gaps
This commit is contained in:
parent
c3d8cedb0b
commit
fb7b94b60e
36 changed files with 2870 additions and 140 deletions
|
|
@ -10,6 +10,12 @@ import type { KtxConnectionDriver, KtxScanConnector } from '../src/context/scan/
|
|||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { runKtxConnection } from '../src/connection.js';
|
||||
|
||||
const reportExceptionMock = vi.hoisted(() => vi.fn(async () => {}));
|
||||
|
||||
vi.mock('../src/telemetry/exception.js', () => ({
|
||||
reportException: reportExceptionMock,
|
||||
}));
|
||||
|
||||
function stripAnsi(s: string): string {
|
||||
return s.replace(/\[[0-9;]*m/g, '');
|
||||
}
|
||||
|
|
@ -72,6 +78,7 @@ describe('runKtxConnection', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), 'ktx-cli-connection-'));
|
||||
reportExceptionMock.mockClear();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
|
@ -165,12 +172,13 @@ describe('runKtxConnection', () => {
|
|||
it('records the raw errorDetail in connection_test telemetry when a native test fails', async () => {
|
||||
vi.stubEnv('KTX_TELEMETRY_DEBUG', '1');
|
||||
vi.stubEnv('CI', '');
|
||||
vi.stubEnv('DATABASE_URL', 'postgres://svc:db-url-password@db.example.test/analytics'); // pragma: allowlist secret
|
||||
const projectDir = join(tempDir, 'project');
|
||||
await initKtxProject({ projectDir });
|
||||
await writeConnections(projectDir, {
|
||||
warehouse: { driver: 'sqlite' },
|
||||
warehouse: { driver: 'postgres', url: 'env:DATABASE_URL' },
|
||||
});
|
||||
const { connector } = nativeConnector('sqlite', { success: false, error: 'database file is unreadable' });
|
||||
const { connector } = nativeConnector('postgres', { success: false, error: 'database file is unreadable' });
|
||||
const io = makeIo();
|
||||
|
||||
const code = await runKtxConnection({ command: 'test', projectDir, connectionId: 'warehouse' }, io.io, {
|
||||
|
|
@ -181,6 +189,16 @@ describe('runKtxConnection', () => {
|
|||
expect(io.stderr()).toContain('"event":"connection_test"');
|
||||
expect(io.stderr()).toContain('"outcome":"error"');
|
||||
expect(io.stderr()).toContain('"errorDetail":"database file is unreadable"');
|
||||
expect(reportExceptionMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
context: expect.objectContaining({ source: 'connection test', handled: true, fatal: false }),
|
||||
projectDir,
|
||||
redactionSecrets: expect.arrayContaining([
|
||||
'postgres://svc:db-url-password@db.example.test/analytics', // pragma: allowlist secret
|
||||
'db-url-password',
|
||||
]),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('preserves the driver error class and code in connection_test telemetry', async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue