125 lines
3.2 KiB
TypeScript
125 lines
3.2 KiB
TypeScript
/**
|
|
* Logging Utilities
|
|
*
|
|
* Provides error serialization and structured logging utilities to prevent
|
|
* [object Object] logs in production. All functions handle circular references
|
|
* and properly serialize Error objects with their properties.
|
|
*
|
|
* Features:
|
|
* - Error serialization with stack traces
|
|
* - Circular reference detection and handling
|
|
* - Convenient logging wrappers
|
|
* - TypeScript-safe error handling
|
|
*/
|
|
|
|
/**
|
|
* Serializes an error object to a JSON string.
|
|
* Handles both Error instances and plain objects.
|
|
*
|
|
* @param error - Error object or unknown value to serialize
|
|
* @returns JSON string representation of the error
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* const err = new Error('Something went wrong');
|
|
* const serialized = serializeError(err);
|
|
* // Returns: '{"name": "Error", "message": "Something went wrong", "stack": "..."}'
|
|
* ```
|
|
*/
|
|
export function serializeError(error: unknown): string {
|
|
if (error instanceof Error) {
|
|
const errorObject: Record<string, any> = {
|
|
name: error.name,
|
|
message: error.message,
|
|
stack: error.stack
|
|
};
|
|
|
|
// Add custom properties from the error object
|
|
for (const key of Object.keys(error)) {
|
|
if (!(key in errorObject)) {
|
|
errorObject[key] = (error as any)[key];
|
|
}
|
|
}
|
|
|
|
return JSON.stringify(errorObject, null, 2);
|
|
}
|
|
|
|
return JSON.stringify(error, null, 2);
|
|
}
|
|
|
|
/**
|
|
* Serializes an object to a JSON string with circular reference handling.
|
|
* Prevents "Converting circular structure to JSON" errors.
|
|
*
|
|
* @param obj - Object to serialize
|
|
* @param maxDepth - Maximum depth for nested objects (default: 10)
|
|
* @returns JSON string representation of the object
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* const circular: any = { a: 1 };
|
|
* circular.self = circular;
|
|
* const serialized = serializeObject(circular);
|
|
* // Returns: '{"a": 1, "self": "[Circular]"}'
|
|
* ```
|
|
*/
|
|
export function serializeObject(obj: unknown, maxDepth: number = 10): string {
|
|
const seen = new WeakSet();
|
|
|
|
const replacer = (key: string, value: any): any => {
|
|
if (typeof value === 'object' && value !== null) {
|
|
if (seen.has(value)) {
|
|
return '[Circular]';
|
|
}
|
|
seen.add(value);
|
|
}
|
|
return value;
|
|
};
|
|
|
|
return JSON.stringify(obj, replacer, 2);
|
|
}
|
|
|
|
/**
|
|
* Logs an error to console.error with proper serialization.
|
|
* Convenience wrapper around serializeError().
|
|
*
|
|
* @param prefix - Log prefix (e.g., '[ComponentName]')
|
|
* @param error - Error object or unknown value to log
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* try {
|
|
* // ... some operation
|
|
* } catch (error) {
|
|
* logError('[QueueProcessor]', error);
|
|
* }
|
|
* ```
|
|
*/
|
|
export function logError(prefix: string, error: unknown): void {
|
|
if (error instanceof Error) {
|
|
console.error(prefix, error.message);
|
|
if (error.stack) {
|
|
console.error('Stack:', error.stack);
|
|
}
|
|
} else {
|
|
console.error(prefix, serializeError(error));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Logs an object to console.log with proper serialization.
|
|
* Handles circular references automatically.
|
|
*
|
|
* @param prefix - Log prefix (e.g., '[ComponentName]')
|
|
* @param obj - Object to log
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* const config = { url: 'https://example.com', timeout: 5000 };
|
|
* logObject('[Config]', config);
|
|
* ```
|
|
*/
|
|
export function logObject(prefix: string, obj: unknown): void {
|
|
console.log(prefix, serializeObject(obj));
|
|
}
|