@sixbell-telco/sdk
Version:
A collection of reusable components designed for use in Sixbell Telco Angular projects
540 lines (419 loc) โข 14.1 kB
Markdown
# 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)