# Logging Examples Concise real-world examples of logging patterns. ## 1. Component with Observable ```typescript import { Component, OnInit } from '@angular/core'; import { logger } from '@isa/core/logging'; @Component({ selector: 'app-product-list', standalone: true, }) export class ProductListComponent implements OnInit { #logger = logger({ component: 'ProductListComponent' }); constructor(private productService: ProductService) {} ngOnInit(): void { this.#logger.info('Component initialized'); this.loadProducts(); } private loadProducts(): void { this.productService.getProducts().subscribe({ next: (products) => { this.#logger.info('Products loaded', () => ({ count: products.length })); }, error: (error) => { this.#logger.error('Failed to load products', error); } }); } } ``` ## 2. Service with HTTP ```typescript import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { logger } from '@isa/core/logging'; import { catchError, tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class OrderService { private http = inject(HttpClient); #logger = logger({ service: 'OrderService' }); getOrder(id: string): Observable { this.#logger.debug('Fetching order', { id }); return this.http.get(`/api/orders/${id}`).pipe( tap((order) => this.#logger.info('Order fetched', () => ({ id, status: order.status }))), catchError((error) => { this.#logger.error('Fetch failed', error, () => ({ id, status: error.status })); throw error; }) ); } } ``` ## 3. Hierarchical Context ```typescript import { Component } from '@angular/core'; import { logger, provideLoggerContext } from '@isa/core/logging'; @Component({ selector: 'oms-return-process', standalone: true, providers: [ provideLoggerContext({ feature: 'returns', module: 'oms' }) ], }) export class ReturnProcessComponent { #logger = logger(() => ({ processId: this.currentProcessId, step: this.currentStep })); private currentProcessId = crypto.randomUUID(); private currentStep = 1; startProcess(orderId: string): void { // Logs include: feature, module, processId, step, orderId this.#logger.info('Process started', { orderId }); } } ``` ## 4. NgRx Effect ```typescript import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { logger } from '@isa/core/logging'; import { map, catchError, tap } from 'rxjs/operators'; import { of } from 'rxjs'; @Injectable() export class OrdersEffects { #logger = logger({ effect: 'OrdersEffects' }); loadOrders$ = createEffect(() => this.actions$.pipe( ofType(OrdersActions.loadOrders), tap((action) => this.#logger.debug('Loading orders', () => ({ page: action.page }))), mergeMap((action) => this.orderService.getOrders(action.filters).pipe( map((orders) => { this.#logger.info('Orders loaded', () => ({ count: orders.length })); return OrdersActions.loadOrdersSuccess({ orders }); }), catchError((error) => { this.#logger.error('Load failed', error); return of(OrdersActions.loadOrdersFailure({ error })); }) ) ) ) ); constructor( private actions$: Actions, private orderService: OrderService ) {} } ``` ## 5. Guard with Authorization ```typescript import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; import { logger } from '@isa/core/logging'; export const authGuard: CanActivateFn = (route, state) => { const authService = inject(AuthService); const router = inject(Router); const log = logger({ guard: 'AuthGuard' }); if (authService.isAuthenticated()) { log.debug('Access granted', () => ({ route: state.url })); return true; } log.warn('Access denied', () => ({ attemptedRoute: state.url, redirectTo: '/login' })); return router.createUrlTree(['/login']); }; ``` ## 6. HTTP Interceptor ```typescript import { HttpInterceptorFn } from '@angular/common/http'; import { inject } from '@angular/core'; import { tap, catchError } from 'rxjs/operators'; import { LoggingService } from '@isa/core/logging'; export const loggingInterceptor: HttpInterceptorFn = (req, next) => { const loggingService = inject(LoggingService); const startTime = performance.now(); loggingService.debug('HTTP Request', () => ({ method: req.method, url: req.url })); return next(req).pipe( tap((event) => { if (event.type === HttpEventType.Response) { loggingService.info('HTTP Response', () => ({ method: req.method, url: req.url, status: event.status, duration: `${(performance.now() - startTime).toFixed(2)}ms` })); } }), catchError((error) => { loggingService.error('HTTP Error', error, () => ({ method: req.method, url: req.url, status: error.status })); return throwError(() => error); }) ); }; ``` ## 7. Form Validation ```typescript import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { logger } from '@isa/core/logging'; @Component({ selector: 'shared-user-form', standalone: true, }) export class UserFormComponent implements OnInit { #logger = logger({ component: 'UserFormComponent' }); form!: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit(): void { this.form = this.fb.group({ name: ['', Validators.required], email: ['', [Validators.required, Validators.email]] }); } onSubmit(): void { if (this.form.invalid) { this.#logger.warn('Invalid form submission', () => ({ errors: this.getFormErrors() })); return; } this.#logger.info('Form submitted'); } private getFormErrors(): Record { const errors: Record = {}; Object.keys(this.form.controls).forEach((key) => { const control = this.form.get(key); if (control?.errors) errors[key] = control.errors; }); return errors; } } ``` ## 8. Async Progress Tracking ```typescript import { Injectable } from '@angular/core'; import { logger } from '@isa/core/logging'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class ImportService { #logger = logger({ service: 'ImportService' }); importData(file: File): Observable { const importId = crypto.randomUUID(); this.#logger.info('Import started', () => ({ importId, fileName: file.name, fileSize: file.size })); return this.processImport(file).pipe( tap((progress) => { if (progress % 25 === 0) { this.#logger.debug('Import progress', () => ({ importId, progress: `${progress}%` })); } }), tap({ complete: () => this.#logger.info('Import completed', { importId }), error: (error) => this.#logger.error('Import failed', error, { importId }) }) ); } private processImport(file: File): Observable { // Implementation } } ``` ## 9. Global Error Handler ```typescript import { Injectable, ErrorHandler } from '@angular/core'; import { logger } from '@isa/core/logging'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { #logger = logger({ handler: 'GlobalErrorHandler' }); handleError(error: Error): void { this.#logger.error('Uncaught error', error, () => ({ url: window.location.href, userAgent: navigator.userAgent, timestamp: new Date().toISOString() })); } } ``` ## 10. WebSocket Component ```typescript import { Component, OnInit, OnDestroy } from '@angular/core'; import { logger } from '@isa/core/logging'; import { Subject, takeUntil } from 'rxjs'; @Component({ selector: 'oms-live-orders', standalone: true, }) export class LiveOrdersComponent implements OnInit, OnDestroy { #logger = logger({ component: 'LiveOrdersComponent' }); private destroy$ = new Subject(); constructor(private wsService: WebSocketService) {} ngOnInit(): void { this.#logger.info('Connecting to WebSocket'); this.wsService.connect('orders').pipe( takeUntil(this.destroy$) ).subscribe({ next: (msg) => this.#logger.debug('Message received', () => ({ type: msg.type, orderId: msg.orderId })), error: (error) => this.#logger.error('WebSocket error', error), complete: () => this.#logger.info('WebSocket closed') }); } ngOnDestroy(): void { this.#logger.debug('Component destroyed'); this.destroy$.next(); this.destroy$.complete(); } } ```