UNPKG

@sixbell-telco/sdk

Version:

A collection of reusable components designed for use in Sixbell Telco Angular projects

540 lines (419 loc) โ€ข 14.1 kB
# Logger Utility A comprehensive, theme-aware logging service for the Sixbell Telco SDK with support for multiple log levels, console output, in-memory storage, and persistent IndexedDB logging. ## Features - ๐Ÿ“Š **6 Log Levels**: trace, debug, info, warn, error, fatal - ๐ŸŽจ **Theme-Aware**: Automatic dark/light mode color schemes - ๐Ÿ’พ **Persistent Storage**: Optional IndexedDB logging with retention policies - ๐Ÿ”‡ **Silent Mode**: Log without console output - ๐Ÿ“ **Context Support**: Add component, action, and custom metadata to logs - ๐Ÿ” **Flexible Filtering**: Log level thresholds to control output - ๐Ÿญ **Factory Pattern**: DI-ready provider for easy Angular integration - ๐Ÿ“ฅ **Log Download**: Export logs as JSON files - ๐Ÿงช **Fully Tested**: 50+ tests covering all functionality ## Installation The logger is included in the UI kit. Import from: ```typescript import { LoggerService } from '@sixbell-telco/sdk/utils/logger'; import { provideLogger } from '@sixbell-telco/sdk/utils/logger'; ``` ## Quick Start ### Basic Usage ```typescript import { Component, inject } from '@angular/core'; import { LoggerService } from '@sixbell-telco/sdk/utils/logger'; @Component({ selector: 'app-example', template: `<div>Check console for logs</div>`, }) export class ExampleComponent { private logger = inject(LoggerService); ngOnInit() { this.logger.info('Component initialized'); this.logger.warn('This is a warning'); this.logger.error('Something went wrong', new Error('Details here')); } } ``` ### Setup in Application Configure the logger in your application bootstrap: ```typescript import { bootstrapApplication } from '@angular/platform-browser'; import { provideLogger } from '@sixbell-telco/sdk/utils/logger'; import { AppComponent } from './app.component'; bootstrapApplication(AppComponent, { providers: [ provideLogger({ enableLogging: true, logLevel: 'debug', showTimestamp: true, isDarkMode: false, }), ], }); ``` Or in NgModule: ```typescript import { NgModule } from '@angular/core'; import { provideLogger } from '@sixbell-telco/sdk/utils/logger'; @NgModule({ providers: [ provideLogger({ enableLogging: true, logLevel: 'info', }), ], }) export class AppModule {} ``` ## Log Levels Log levels are ordered by severity. The logger will only output messages at or above the configured threshold. | Level | Value | Use Case | Color | | --------- | ----- | ----------------------------------- | ------------ | | **trace** | 0 | Very detailed debugging information | Gray | | **debug** | 1 | General debugging information | Blue | | **info** | 2 | Informational messages | Green | | **warn** | 3 | Warning conditions | Orange | | **error** | 4 | Error conditions | Red | | **fatal** | 5 | Fatal errors that may crash the app | White on Red | ### Example: Log Level Filtering ```typescript // With logLevel: 'warn', only warn, error, and fatal will appear logger.configure({ logLevel: 'warn' }); logger.debug('Not shown'); // โœ— Below threshold logger.info('Not shown'); // โœ— Below threshold logger.warn('Will show'); // โœ“ At threshold logger.error('Will show'); // โœ“ Above threshold logger.fatal('Will show'); // โœ“ Above threshold ``` ## API Reference ### Configuration ```typescript interface LoggerConfig { enableLogging?: boolean; // Enable/disable logging (default: false) logLevel?: LogLevel; // Minimum level to log (default: 'error') showTimestamp?: boolean; // Show time in logs (default: false) showDate?: boolean; // Show date + time (default: false) silentMode?: boolean; // Log without console output (default: false) persistToIndexedDB?: boolean; // Save logs to IndexedDB (default: false) idbRetentionDays?: number; // Keep logs for X days (default: 7) idbMaxLogs?: number; // Max logs in IndexedDB (default: 5000) isDarkMode?: boolean; // Use dark theme colors (default: false) onError?: (error, context) => void; // Error callback errorReporter?: { captureException }; // External error reporter } ``` ### Methods #### Logging Methods ```typescript logger.trace(message: string, context?: LoggerContext) logger.debug(message: string, context?: LoggerContext) logger.info(message: string, context?: LoggerContext) logger.warn(message: string, context?: LoggerContext) logger.error(message: string, error?: Error, context?: LoggerContext) logger.fatal(message: string, error?: Error, context?: LoggerContext) ``` #### Configuration ```typescript // Configure globally logger.configure({ enableLogging: true, logLevel: 'debug' }); // Create temporary logger with different config const debugLogger = logger.withConfig({ logLevel: 'trace' }); debugLogger.debug('Detailed debug info'); logger.debug('Respects original config'); ``` #### Storage & Retrieval ```typescript // Get in-memory logs const logs = logger.getStoredLogs(); // Clear in-memory logs logger.clearStoredLogs(); // Get persisted logs from IndexedDB const persistedLogs = await logger.getPersistedLogs(); // Clear IndexedDB logs await logger.clearPersistedLogs(); // Download all logs as JSON await logger.downloadLogs('my-logs.json'); ``` #### Theme Management ```typescript // Set dark mode explicitly logger.setDarkMode(true); // Get current theme const isDark = logger.isDarkMode(); // Restore system preference detection logger.setDarkMode(undefined); ``` ## Usage Examples ### Example 1: Basic Logging with Context ```typescript import { Component, inject } from '@angular/core'; import { LoggerService } from '@sixbell-telco/sdk/utils/logger'; @Component({ selector: 'app-user-list', template: `<div>Users</div>`, }) export class UserListComponent { private logger = inject(LoggerService); loadUsers() { const context = { component: 'UserListComponent', action: 'loadUsers', }; this.logger.info('Loading users', context); try { // Load users... this.logger.info('Users loaded successfully', context); } catch (error) { this.logger.error('Failed to load users', error as Error, context); } } } ``` ### Example 2: Environment-Specific Configuration ```typescript // environment.ts export const environment = { production: false, logger: { enableLogging: true, logLevel: 'debug', showTimestamp: true, persistToIndexedDB: false, }, }; // environment.prod.ts export const environment = { production: true, logger: { enableLogging: true, logLevel: 'warn', showTimestamp: true, persistToIndexedDB: true, idbRetentionDays: 30, }, }; // main.ts import { environment } from './environments/environment'; import { provideLogger } from '@sixbell-telco/sdk/utils/logger'; bootstrapApplication(AppComponent, { providers: [provideLogger(environment.logger)], }); ``` ### Example 3: Error Reporting Integration ```typescript import { provideLogger } from '@sixbell-telco/sdk/utils/logger'; // With external error reporter (e.g., Sentry) bootstrapApplication(AppComponent, { providers: [ provideLogger({ enableLogging: true, errorReporter: { captureException: (error, context) => { // Send to Sentry, LogRocket, etc. console.log('Reporting error:', error, context); }, }, onError: (error, context) => { console.log('Error callback:', error, context); }, }), ], }); ``` ### Example 4: Silent Mode for Testing ```typescript describe('MyService', () => { let service: MyService; let logger: LoggerService; beforeEach(() => { TestBed.configureTestingModule({ providers: [ MyService, provideLogger({ enableLogging: true, silentMode: true, // No console output during tests logLevel: 'trace', }), ], }); logger = TestBed.inject(LoggerService); service = TestBed.inject(MyService); }); it('should log without console output', () => { service.doSomething(); const logs = logger.getStoredLogs(); expect(logs.length).toBeGreaterThan(0); }); }); ``` ### Example 5: Temporary Debug Logger ```typescript // In your service private logger = inject(LoggerService); debugComplexOperation() { // Use debug-level logger just for this operation const debugLogger = this.logger.withConfig({ logLevel: 'trace' }); debugLogger.trace('Step 1: Starting complex operation'); debugLogger.trace('Step 2: Processing data'); debugLogger.trace('Step 3: Finalizing'); // Regular logger respects original config this.logger.info('Complex operation completed'); } ``` ### Example 6: Download Logs for Debugging ```typescript // In a settings or debug component downloadApplicationLogs() { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const filename = `app-logs-${timestamp}.json`; this.logger.downloadLogs(filename); } ``` ## Logging Best Practices ### โœ… Do - **Use appropriate log levels**: Use `info` for normal flow, `warn` for recoverable issues, `error` for failures - **Add context**: Include component name and action to help debugging - **Log at boundaries**: Log when entering/exiting major functions or components - **Use descriptive messages**: Make it clear what happened - **Include errors properly**: Pass Error objects to error/fatal methods ```typescript // Good this.logger.info('User authenticated', { component: 'AuthService', action: 'login', userId: user.id, }); try { await this.api.fetch(); } catch (error) { this.logger.error('API request failed', error as Error, { component: 'DataService', action: 'fetch', }); } ``` ### โŒ Don't - **Avoid logging sensitive data**: Don't log passwords, tokens, or personal information - **Don't use error level for everything**: Use appropriate levels - **Don't log in tight loops**: Can impact performance - **Don't leave debug logs in production**: Use log level filtering instead ```typescript // Bad this.logger.error('Password received: ' + password); // Security issue! this.logger.error('Button clicked'); // Should be 'info' for (let i = 0; i < 1000000; i++) { this.logger.trace('Processing item ' + i); // Performance issue } ``` ## Color Scheme The logger automatically applies theme-aware colors to console output. ### Light Mode (Default) - Trace: Dark Gray - Debug: Dark Blue - Info: Dark Green - Warn: Dark Orange - Error: Dark Red - Fatal: White on Red ### Dark Mode - Trace: Light Gray - Debug: Light Blue - Info: Light Green - Warn: Light Orange - Error: Light Red - Fatal: White on Light Red ## Storage ### In-Memory Storage Logs are stored in memory by default (up to 1000 logs). Use `getStoredLogs()` to retrieve them. ### IndexedDB Persistence Enable persistent storage for logs that survive page refreshes: ```typescript provideLogger({ enableLogging: true, persistToIndexedDB: true, idbRetentionDays: 7, // Keep for 7 days idbMaxLogs: 5000, // Store max 5000 logs }); ``` **Note**: IndexedDB is asynchronous. Use `await logger.getPersistedLogs()` to retrieve stored logs. ## Testing The logger includes 50+ tests covering all functionality. Tests use Jest and ng-mocks patterns: ```typescript import { TestBed } from '@angular/core/testing'; import { LoggerService } from '@sixbell-telco/sdk/utils/logger'; import { provideLogger } from '@sixbell-telco/sdk/utils/logger'; describe('LoggerService', () => { let service: LoggerService; beforeEach(() => { TestBed.configureTestingModule({ providers: [provideLogger({ enableLogging: true, logLevel: 'trace' })], }); service = TestBed.inject(LoggerService); }); it('should log messages', () => { service.info('Test message'); const logs = service.getStoredLogs(); expect(logs[0].message).toBe('Test message'); }); }); ``` ## Common Issues ### Logs Not Appearing **Problem**: No logs in console - Check `enableLogging` is `true` - Check `logLevel` is set to capture your message level - Check `silentMode` is `false` ### IndexedDB Not Persisting **Problem**: Logs not saved to IndexedDB - Check `persistToIndexedDB` is `true` - Check browser supports IndexedDB (not disabled in settings) - Verify logs using browser DevTools โ†’ Application โ†’ IndexedDB โ†’ sixbell_ui_kit ### Performance Issues **Problem**: Console output is slow - Reduce `logLevel` to only log important messages - Use `silentMode: true` for high-frequency operations - Avoid logging large objects ## API Types ```typescript export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; export interface LoggerContext { component?: string; action?: string; timestamp?: number; [key: string]: unknown; // Custom properties } export interface LoggerConfig { enableLogging?: boolean; logLevel?: LogLevel; showTimestamp?: boolean; showDate?: boolean; silentMode?: boolean; persistToIndexedDB?: boolean; idbRetentionDays?: number; idbMaxLogs?: number; isDarkMode?: boolean; onError?: (error: Error, context: LoggerContext) => void; errorReporter?: { captureException: (error: Error, context?: LoggerContext) => void; }; } ``` IndexedDB requires modern browser support (IE not supported). ## Performance Considerations - **In-Memory Storage**: Max 1000 logs to prevent memory bloat - **IndexedDB**: Asynchronous, doesn't block main thread - **Console Output**: Can be disabled with `silentMode` - **Theme Detection**: Only initialized when logging is enabled ## Contributing When adding features to the logger: 1. Update types in `models/logger.ts` 2. Add constants in `constants.ts` 3. Update `LoggerService` implementation 4. Add tests in `logger.service.spec.ts` 5. Update provider tests in `logger.provider.spec.ts` 6. Update this README with examples ## Related Documentation - [UI Kit Overview](../../README.md) - [Theme Utility](../theme/README.md) - [Translation Utility](../translation/README.md)