mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Logger: serialize errors
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { serializeError } from '~/common/util/errorUtils';
|
||||
|
||||
import type { ClientLogger, LogEntry, LogLevel, LogOptions, LogSource } from './logger.types';
|
||||
import { LoggerActions, useLoggerStore } from './store-logger';
|
||||
|
||||
@@ -85,7 +87,7 @@ class LoggerImplementation implements ClientLogger {
|
||||
// combine options
|
||||
const finalOptions = options || {};
|
||||
const finalSource = source || finalOptions.source || 'unknown';
|
||||
const finalDetails = details || finalOptions.details;
|
||||
const finalDetails = serializeError(details || finalOptions.details); // serializeError because otherwise 'Error' wouldn't be serializable, and would appear as {}
|
||||
|
||||
// prepare actions - handle both options.action and options.actions
|
||||
let actions = finalOptions.actions || [];
|
||||
|
||||
@@ -41,7 +41,7 @@ export function LogEntryDetails(props: {
|
||||
|
||||
return (
|
||||
<Card variant='outlined' sx={{ backgroundColor: 'background.popup' }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography level='title-md'>{entry.message}</Typography>
|
||||
<Button
|
||||
size='sm'
|
||||
|
||||
@@ -99,7 +99,7 @@ export function LogViewerDialog(props: {
|
||||
title='Client Logs'
|
||||
unfilterBackdrop
|
||||
// themedColor='neutral'
|
||||
sx={{ maxWidth: undefined }}
|
||||
sx={{ maxWidth: undefined, overflow: 'hidden' }}
|
||||
>
|
||||
<Box sx={{ display: 'flex', flexDirection: { xs: 'column', md: 'row' }, gap: 2, mb: 1 }}>
|
||||
|
||||
@@ -159,7 +159,7 @@ export function LogViewerDialog(props: {
|
||||
<Typography level='body-lg'>No logs to display</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ minHeight: '12rem', maxHeight: 'calc(100vh - 18rem)', overflow: 'auto', my: 1 }}>
|
||||
<Box sx={{ minHeight: '12rem', overflow: 'auto', my: 1 }}>
|
||||
<Table
|
||||
size='sm'
|
||||
variant='outlined'
|
||||
@@ -177,7 +177,7 @@ export function LogViewerDialog(props: {
|
||||
<th style={{ width: '30px' }}></th>
|
||||
<th style={{ width: '120px' }}>Time</th>
|
||||
<th style={{ width: '80px' }}>Level</th>
|
||||
<th style={{ width: '100px' }}>Source</th>
|
||||
<th style={{ width: '120px' }}>Source</th>
|
||||
<th style={{ minWidth: '100px' }}>Message</th>
|
||||
<th style={{ width: '100px' }}>Actions</th>
|
||||
</tr>
|
||||
@@ -201,7 +201,7 @@ export function LogViewerDialog(props: {
|
||||
{entry.level}
|
||||
</Chip>
|
||||
</td>
|
||||
<td>{entry.source}</td>
|
||||
<td style={{ whiteSpace: 'nowrap' }}>{entry.source}</td>
|
||||
<td className='agi-ellipsize'>{entry.message}</td>
|
||||
<td>
|
||||
{entry.actions && entry.actions.length > 0 && (
|
||||
|
||||
@@ -55,3 +55,40 @@ function safeObjectToString(obj: object): string {
|
||||
}
|
||||
return `{ ${pairs.join(', ')} }`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize an error object to a plain object for storage or transmission.
|
||||
*/
|
||||
export function serializeError(value: any): any {
|
||||
// handle Error objects
|
||||
if (value instanceof Error) {
|
||||
return {
|
||||
_isError: true, // Mark as serialized error for identification
|
||||
name: value.name ?? 'SError',
|
||||
message: value.message ?? 'No SMessage',
|
||||
...(value.stack !== undefined && { stack: value.stack }), // Include stack if available
|
||||
...(value.cause !== undefined && { cause: serializeError(value.cause) }), // Recursively serialize cause
|
||||
// Capture other properties
|
||||
...Object.fromEntries(
|
||||
Object.entries(value).filter(([k]) => !['name', 'message', 'stack', 'cause'].includes(k)),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
// handle objects that might contain errors
|
||||
if (value && typeof value === 'object') {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(serializeError);
|
||||
}
|
||||
|
||||
const result: Record<string, any> = {};
|
||||
for (const [key, val] of Object.entries(value)) {
|
||||
result[key] = serializeError(val);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return primitives as-is
|
||||
return value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user