75 lines
2.1 KiB
TypeScript
75 lines
2.1 KiB
TypeScript
import { promises as fs } from 'fs';
|
|
import type { AuditEvent, AuditQuery } from './types.js';
|
|
|
|
export async function queryAuditLogs(logPath: string, query: AuditQuery): Promise<AuditEvent[]> {
|
|
const logs: AuditEvent[] = [];
|
|
|
|
try {
|
|
const content = await fs.readFile(logPath, 'utf-8');
|
|
const lines = content.split('\n').filter(line => line.trim() !== '');
|
|
|
|
for (const line of lines) {
|
|
try {
|
|
const event: AuditEvent = JSON.parse(line);
|
|
if (matchesQuery(event, query)) {
|
|
logs.push(event);
|
|
}
|
|
} catch {
|
|
// Skip malformed lines
|
|
}
|
|
}
|
|
} catch (err) {
|
|
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
return logs.sort((a, b) => a.timestamp - b.timestamp);
|
|
}
|
|
|
|
function matchesQuery(event: AuditEvent, query: AuditQuery): boolean {
|
|
if (query.start_time && event.timestamp < query.start_time) {
|
|
return false;
|
|
}
|
|
if (query.end_time && event.timestamp > query.end_time) {
|
|
return false;
|
|
}
|
|
if (query.event_types && !query.event_types.includes(event.event_type)) {
|
|
return false;
|
|
}
|
|
if (query.level && event.level !== query.level) {
|
|
return false;
|
|
}
|
|
if (query.session_id) {
|
|
const eventSessionId = (event.event as Record<string, unknown>).session_id as string | undefined;
|
|
if (eventSessionId !== query.session_id) {
|
|
return false;
|
|
}
|
|
}
|
|
if (query.tool_name) {
|
|
const eventToolName = (event.event as Record<string, unknown>).tool_name as string | undefined;
|
|
if (eventToolName !== query.tool_name) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
export async function exportAuditLogs(logPath: string, query: AuditQuery, format: 'json' | 'csv'): Promise<string> {
|
|
const logs = await queryAuditLogs(logPath, query);
|
|
|
|
if (format === 'json') {
|
|
return JSON.stringify(logs, null, 2);
|
|
}
|
|
|
|
// CSV format
|
|
const headers = ['timestamp', 'level', 'event_type', 'event'];
|
|
const rows = logs.map(log => {
|
|
const eventStr = JSON.stringify(log.event).replace(/"/g, '""');
|
|
return `${log.timestamp},${log.level},${log.event_type},"${eventStr}"`;
|
|
});
|
|
|
|
return [headers.join(','), ...rows].join('\n');
|
|
}
|