mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Added error logging guidelines and best practices to code style documentation.
- 📚 **Docs**: Introduced error logging section with guidelines - ✨ **Feature**: Added context-aware logging examples - 🛠️ **Refactor**: Improved structure for error handling practices
This commit is contained in:
@@ -487,6 +487,203 @@ function getUser(id) {
|
||||
}
|
||||
```
|
||||
|
||||
## Error Logging
|
||||
|
||||
Proper error logging is critical for diagnosing issues in production applications. Always use the `@isa/core/logging` module for logging throughout the application.
|
||||
|
||||
### Basic Logging Guidelines
|
||||
|
||||
- Always use the appropriate log level for the situation:
|
||||
- `trace` - For fine-grained debugging information
|
||||
- `debug` - For development-time debugging information
|
||||
- `info` - For general runtime information
|
||||
- `warn` - For potential issues that don't interrupt operation
|
||||
- `error` - For errors that affect functionality
|
||||
|
||||
### Setting Up Logging
|
||||
|
||||
Use the logger factory function to create loggers in your components and services:
|
||||
|
||||
```typescript
|
||||
import { logger } from '@isa/core/logging';
|
||||
|
||||
@Component({
|
||||
selector: 'app-example',
|
||||
templateUrl: './example.component.html',
|
||||
})
|
||||
export class ExampleComponent implements OnInit {
|
||||
// Create a private logger instance
|
||||
#logger = logger();
|
||||
|
||||
constructor(private userService: UserService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.#logger.info('Component initialized');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Context-Aware Logging
|
||||
|
||||
Always provide relevant context when logging:
|
||||
|
||||
```typescript
|
||||
// Good - With detailed context
|
||||
this.#logger.error(
|
||||
'Failed to load user data',
|
||||
error,
|
||||
{ userId: '123', attempt: 2, source: 'UserProfileComponent' }
|
||||
);
|
||||
|
||||
// Bad - No context for troubleshooting
|
||||
this.#logger.error('Failed to load user data');
|
||||
```
|
||||
|
||||
### Component and Service Level Context
|
||||
|
||||
Use the `provideLoggerContext` to set component-level context:
|
||||
|
||||
```typescript
|
||||
@Component({
|
||||
selector: 'app-user-profile',
|
||||
templateUrl: './user-profile.component.html',
|
||||
providers: [
|
||||
provideLoggerContext({
|
||||
component: 'UserProfile',
|
||||
section: 'Account'
|
||||
})
|
||||
]
|
||||
})
|
||||
export class UserProfileComponent {
|
||||
#logger = logger();
|
||||
|
||||
// All logs from this component will include the context
|
||||
updateProfile(): void {
|
||||
this.#logger.info('Updating user profile');
|
||||
// Log output will include { component: 'UserProfile', section: 'Account' }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling Best Practices
|
||||
|
||||
1. **Always log the original Error object**:
|
||||
|
||||
```typescript
|
||||
// Good - Includes the original error with stack trace
|
||||
try {
|
||||
// risky operation
|
||||
} catch (error) {
|
||||
this.#logger.error('Operation failed', error, { context: 'additional data' });
|
||||
}
|
||||
|
||||
// Bad - Loses the stack trace and error details
|
||||
try {
|
||||
// risky operation
|
||||
} catch (error) {
|
||||
this.#logger.error(`Operation failed: ${error}`);
|
||||
}
|
||||
```
|
||||
|
||||
2. **Structure error handling with contextual information**:
|
||||
|
||||
```typescript
|
||||
saveData(data: UserData): void {
|
||||
this.userService.save(data).pipe(
|
||||
catchError((error) => {
|
||||
this.#logger.error(
|
||||
'Failed to save user data',
|
||||
error,
|
||||
{
|
||||
userId: data.id,
|
||||
dataSize: JSON.stringify(data).length,
|
||||
operation: 'saveData'
|
||||
}
|
||||
);
|
||||
|
||||
// Handle the error appropriately
|
||||
return throwError(() => new Error('Failed to save data'));
|
||||
})
|
||||
).subscribe();
|
||||
}
|
||||
```
|
||||
|
||||
3. **Use log levels appropriately**:
|
||||
|
||||
```typescript
|
||||
// Debug information during development
|
||||
this.#logger.debug('Processing data batch', { batchSize: items.length });
|
||||
|
||||
// General information during runtime
|
||||
this.#logger.info('User logged in', { userId: user.id });
|
||||
|
||||
// Potential issues that don't break functionality
|
||||
this.#logger.warn('API response slow', { responseTime: '2500ms', endpoint: '/users' });
|
||||
|
||||
// Errors that affect functionality
|
||||
this.#logger.error('Payment processing failed', error, { orderId: order.id });
|
||||
```
|
||||
|
||||
4. **In RxJS operators, use tap for logging**:
|
||||
|
||||
```typescript
|
||||
return this.http.get<User[]>('/api/users').pipe(
|
||||
tap({
|
||||
next: (users) => this.#logger.info('Users loaded', { count: users.length }),
|
||||
error: (error) => this.#logger.error('Failed to load users', error)
|
||||
}),
|
||||
catchError((error) => {
|
||||
this.#logger.error('Error in users API call', error, { retry: true });
|
||||
return this.fallbackUserService.getUsers();
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
5. **Log lifecycle events when relevant**:
|
||||
|
||||
```typescript
|
||||
export class ImportantComponent implements OnInit, OnDestroy {
|
||||
#logger = logger();
|
||||
|
||||
ngOnInit(): void {
|
||||
this.#logger.debug('Component initialized');
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.#logger.debug('Component destroyed');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Considerations
|
||||
|
||||
- Avoid expensive operations in log messages in production:
|
||||
|
||||
```typescript
|
||||
// Bad - Performs expensive operation even if debug level is disabled
|
||||
this.#logger.debug('Data state:', JSON.stringify(this.largeDataObject));
|
||||
|
||||
// Good - Only performs expensive operation if needed
|
||||
if (isDevMode()) {
|
||||
this.#logger.debug('Data state:', { data: this.largeDataObject });
|
||||
}
|
||||
```
|
||||
|
||||
- Consider log level in production environments:
|
||||
|
||||
```typescript
|
||||
// In app.config.ts
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// Other providers...
|
||||
provideLogging(
|
||||
withLogLevel(isDevMode() ? LogLevel.Debug : LogLevel.Warn),
|
||||
withSink(ConsoleLogSink)
|
||||
)
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
## Project-Specific Preferences
|
||||
|
||||
- **Frameworks**: Follow best practices for Nx, Angular, date-fns, Ngrx, RxJs and Zod.
|
||||
|
||||
Reference in New Issue
Block a user