- querySessions, createSession, getSession, updateSession, cancelSession - getTraces, getLogs, getScreenshots - Full TypeScript types for all diagnostics entities
300 lines
9.5 KiB
TypeScript
300 lines
9.5 KiB
TypeScript
/**
|
|
* Diagnostics Client Library
|
|
* Admin dashboard client for debug sessions, traces, and logs
|
|
*/
|
|
|
|
import { createApiClient } from '@bytelyst/api-client';
|
|
import type { ApiClient } from '@bytelyst/api-client';
|
|
|
|
// =============================================================================
|
|
// Types
|
|
// =============================================================================
|
|
|
|
export interface DebugSession {
|
|
id: string;
|
|
productId: string;
|
|
targetUserId?: string;
|
|
targetAnonymousId?: string;
|
|
targetDeviceId?: string;
|
|
targetSessionId?: string;
|
|
status: 'pending' | 'active' | 'paused' | 'completed' | 'cancelled';
|
|
collectionLevel: 'standard' | 'debug' | 'trace';
|
|
captureLogs: boolean;
|
|
captureNetwork: boolean;
|
|
captureScreenshots: boolean;
|
|
screenshotOnError: boolean;
|
|
maxDurationMinutes: number;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
startedAt?: string;
|
|
endedAt?: string;
|
|
expiresAt: string;
|
|
logCount: number;
|
|
traceCount: number;
|
|
screenshotCount: number;
|
|
createdBy: string;
|
|
updatedBy?: string;
|
|
userConsent?: {
|
|
consentedAt: string;
|
|
consentMethod: 'prompt' | 'pre_consent' | 'auto';
|
|
};
|
|
}
|
|
|
|
export interface CreateSessionRequest {
|
|
targetUserId?: string;
|
|
targetAnonymousId?: string;
|
|
targetDeviceId?: string;
|
|
targetSessionId?: string;
|
|
collectionLevel: 'standard' | 'debug' | 'trace';
|
|
captureLogs?: boolean;
|
|
captureNetwork?: boolean;
|
|
captureScreenshots?: boolean;
|
|
screenshotOnError?: boolean;
|
|
maxDurationMinutes?: number;
|
|
}
|
|
|
|
export interface UpdateSessionRequest {
|
|
status?: 'active' | 'paused' | 'completed' | 'cancelled';
|
|
collectionLevel?: 'standard' | 'debug' | 'trace';
|
|
captureLogs?: boolean;
|
|
captureNetwork?: boolean;
|
|
captureScreenshots?: boolean;
|
|
screenshotOnError?: boolean;
|
|
maxDurationMinutes?: number;
|
|
}
|
|
|
|
export interface QuerySessionsOptions {
|
|
productId: string;
|
|
status?: string;
|
|
targetUserId?: string;
|
|
targetDeviceId?: string;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
limit?: number;
|
|
offset?: number;
|
|
}
|
|
|
|
export interface QuerySessionsResult {
|
|
sessions: DebugSession[];
|
|
total: number;
|
|
limit: number;
|
|
offset: number;
|
|
}
|
|
|
|
export interface TraceSpan {
|
|
id: string;
|
|
sessionId: string;
|
|
productId: string;
|
|
traceId: string;
|
|
parentId?: string;
|
|
spanId: string;
|
|
name: string;
|
|
kind?: 'internal' | 'server' | 'client' | 'producer' | 'consumer';
|
|
startTime: string;
|
|
endTime?: string;
|
|
durationMs?: number;
|
|
attributes: Record<string, unknown>;
|
|
status: 'ok' | 'error' | 'unset';
|
|
statusMessage?: string;
|
|
events?: Array<{
|
|
name: string;
|
|
timestamp: string;
|
|
attributes?: Record<string, unknown>;
|
|
}>;
|
|
}
|
|
|
|
export interface LogEntry {
|
|
id: string;
|
|
sessionId: string;
|
|
productId: string;
|
|
level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
message: string;
|
|
messageHash?: string;
|
|
timestamp: string;
|
|
receivedAt?: string;
|
|
module: string;
|
|
file?: string;
|
|
line?: number;
|
|
function?: string;
|
|
threadId?: string;
|
|
correlationId?: string;
|
|
context: Record<string, unknown>;
|
|
redaction?: {
|
|
fieldsRedacted: string[];
|
|
patternsMatched: string[];
|
|
};
|
|
}
|
|
|
|
export interface QueryTracesOptions {
|
|
sessionId: string;
|
|
productId: string;
|
|
startTime?: string;
|
|
endTime?: string;
|
|
name?: string;
|
|
status?: string;
|
|
limit?: number;
|
|
offset?: number;
|
|
}
|
|
|
|
export interface QueryLogsOptions {
|
|
sessionId: string;
|
|
productId: string;
|
|
levels?: ('debug' | 'info' | 'warn' | 'error' | 'fatal')[];
|
|
module?: string;
|
|
search?: string;
|
|
startTime?: string;
|
|
endTime?: string;
|
|
limit?: number;
|
|
offset?: number;
|
|
}
|
|
|
|
// =============================================================================
|
|
// Client Factory
|
|
// =============================================================================
|
|
|
|
export interface DiagnosticsClientConfig {
|
|
baseUrl: string;
|
|
productId: string;
|
|
getAuthToken: () => string | null;
|
|
}
|
|
|
|
export function createDiagnosticsClient(config: DiagnosticsClientConfig) {
|
|
const client = createApiClient({
|
|
baseUrl: config.baseUrl,
|
|
getToken: config.getAuthToken,
|
|
}) as ApiClient;
|
|
|
|
return {
|
|
// -------------------------------------------------------------------------
|
|
// Sessions
|
|
// -------------------------------------------------------------------------
|
|
|
|
async querySessions(options: QuerySessionsOptions): Promise<QuerySessionsResult> {
|
|
const params = new URLSearchParams();
|
|
params.set('productId', options.productId);
|
|
if (options.status) params.set('status', options.status);
|
|
if (options.targetUserId) params.set('targetUserId', options.targetUserId);
|
|
if (options.targetDeviceId) params.set('targetDeviceId', options.targetDeviceId);
|
|
if (options.startDate) params.set('startDate', options.startDate);
|
|
if (options.endDate) params.set('endDate', options.endDate);
|
|
if (options.limit) params.set('limit', options.limit.toString());
|
|
if (options.offset) params.set('offset', options.offset.toString());
|
|
|
|
const result = await client.safeFetch<QuerySessionsResult>(`/api/diagnostics/sessions?${params.toString()}`);
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
|
|
async createSession(request: CreateSessionRequest): Promise<DebugSession> {
|
|
const result = await client.safeFetch<DebugSession>('/api/diagnostics/sessions', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(request),
|
|
});
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
|
|
async getSession(sessionId: string): Promise<DebugSession> {
|
|
const result = await client.safeFetch<DebugSession>(`/api/diagnostics/sessions/${sessionId}`);
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
|
|
async updateSession(sessionId: string, request: UpdateSessionRequest): Promise<DebugSession> {
|
|
const result = await client.safeFetch<DebugSession>(`/api/diagnostics/sessions/${sessionId}`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(request),
|
|
});
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
|
|
async cancelSession(sessionId: string, reason?: string): Promise<void> {
|
|
const result = await client.safeFetch<void>(`/api/diagnostics/sessions/${sessionId}`, {
|
|
method: 'DELETE',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ reason }),
|
|
});
|
|
if (result.error) throw new Error(result.error);
|
|
},
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Traces
|
|
// -------------------------------------------------------------------------
|
|
|
|
async getTraces(options: QueryTracesOptions): Promise<{ traces: TraceSpan[]; total: number }> {
|
|
const params = new URLSearchParams();
|
|
params.set('productId', options.productId);
|
|
if (options.startTime) params.set('startTime', options.startTime);
|
|
if (options.endTime) params.set('endTime', options.endTime);
|
|
if (options.name) params.set('name', options.name);
|
|
if (options.status) params.set('status', options.status);
|
|
if (options.limit) params.set('limit', options.limit.toString());
|
|
if (options.offset) params.set('offset', options.offset.toString());
|
|
|
|
const result = await client.safeFetch<{ traces: TraceSpan[]; total: number }>(
|
|
`/api/diagnostics/sessions/${options.sessionId}/traces?${params.toString()}`
|
|
);
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Logs
|
|
// -------------------------------------------------------------------------
|
|
|
|
async getLogs(options: QueryLogsOptions): Promise<{ logs: LogEntry[]; total: number }> {
|
|
const params = new URLSearchParams();
|
|
params.set('productId', options.productId);
|
|
if (options.levels) params.set('levels', options.levels.join(','));
|
|
if (options.module) params.set('module', options.module);
|
|
if (options.search) params.set('search', options.search);
|
|
if (options.startTime) params.set('startTime', options.startTime);
|
|
if (options.endTime) params.set('endTime', options.endTime);
|
|
if (options.limit) params.set('limit', options.limit.toString());
|
|
if (options.offset) params.set('offset', options.offset.toString());
|
|
|
|
const result = await client.safeFetch<{ logs: LogEntry[]; total: number }>(
|
|
`/api/diagnostics/sessions/${options.sessionId}/logs?${params.toString()}`
|
|
);
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Screenshots
|
|
// -------------------------------------------------------------------------
|
|
|
|
async getScreenshots(sessionId: string, productId: string): Promise<
|
|
Array<{
|
|
id: string;
|
|
blobUrl: string;
|
|
capturedAt: string;
|
|
trigger: string;
|
|
width: number;
|
|
height: number;
|
|
}>
|
|
> {
|
|
const params = new URLSearchParams();
|
|
params.set('productId', productId);
|
|
|
|
const result = await client.safeFetch<
|
|
Array<{
|
|
id: string;
|
|
blobUrl: string;
|
|
capturedAt: string;
|
|
trigger: string;
|
|
width: number;
|
|
height: number;
|
|
}>
|
|
>(`/api/diagnostics/sessions/${sessionId}/screenshots?${params.toString()}`);
|
|
if (result.error) throw new Error(result.error);
|
|
return result.data!;
|
|
},
|
|
};
|
|
}
|
|
|
|
export type DiagnosticsClient = ReturnType<typeof createDiagnosticsClient>;
|