Angular Logging Http Interceptor

By Arvind Rai, January 26, 2024
This page will walk through Angular logging Http Interceptor example. Angular provides HttpInterceptor interface that is used to intercept HttpRequest and handle them. HttpInterceptor provides intercept() method that generally intercepts outgoing request before calling next interceptor. intercept() method accepts HttpRequest and HttpHandler as arguments. To create interceptor, we need to create a service that will implement HttpInterceptor and define intercept() method. Here on this page we will create an interceptor for logging. We will log request method, request URL and request completion time with success or failure message.

1. Create Logging Interceptor

Angular HttpInterceptor provides intercept() method to intercept outgoing request. To create a logging interceptor we need to create a service that will implement HttpInterceptor interface.
logging-interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http';
import { finalize, tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const startTime = Date.now();
    let status: string;

    return next.handle(req).pipe(
        tap(
          event => {
            status = '';
            if (event instanceof HttpResponse) {
              status = 'succeeded';
            }
          },
          error => status = 'failed'
        ),
        finalize(() => {
          const elapsedTime = Date.now() - startTime;
          const message = req.method + " " + req.urlWithParams +" "+ status 
          + " in " + elapsedTime + "ms";
          
          this.logDetails(message);
        })
    );
  }
  private logDetails(msg: string) {
    console.log(msg);
  }
} 
HttpRequest: It is an outgoing HTTP request. It provides getters to fetch request properties such as method, urlWithParams etc.
HttpHandler: It transforms an HttpRequest into a stream of HttpEvent. HttpHandler provides handle() method to dispatch request from first interceptor to second and so on.
HttpResponse: It is a full HTTP response. It has getter methods such as body, headers, status, url etc.

Find RxJsObservable operators used in our example.
pipe(): It runs functional operators into a chain.
tap(): It performs a side effect for every emission on the source Observable and returns Observable identical to the source, if there is no error.
finalize(): It calls specified function when the source terminates on complete or error and returns Observable identical to the source.

2. Configure Interceptor with Provider

Interceptors are configured with provider as following.
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true } 
As there can be more than one HTTP interceptor and we need to maintain its order, so it is better to create a const array as following.
export const httpInterceptorProviders = [
  { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
]; 
Now configure it with providers attribute.
@NgModule({
  providers: [
      httpInterceptorProviders
  ],
  ------
})
export class AppModule { } 

3. Complete Example

logging-interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http';
import { finalize, tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const startTime = Date.now();
    let status: string;

    return next.handle(req).pipe(
        tap(
          event => {
            status = '';
            if (event instanceof HttpResponse) {
              status = 'succeeded';
            }
          },
          error => status = 'failed'
        ),
        finalize(() => {
          const elapsedTime = Date.now() - startTime;
          const message = req.method + " " + req.urlWithParams +" "+ status 
          + " in " + elapsedTime + "ms";
          
          this.logDetails(message);
        })
    );
  }
  private logDetails(msg: string) {
    console.log(msg);
  }
} 
index.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { LoggingInterceptor } from './logging-interceptor';

export const httpInterceptorProviders = [
  { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
]; 
book.ts
export interface Book {
   id: number;
   name: string;
   category: string;
   year: string;
} 
book.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Book } from './book';

@Injectable()
export class BookService {
    constructor(private http: HttpClient) { }

    bookUrl = "/api/books";	
    getBooks(): Observable<Book[]> {
        return this.http.get<Book[]>(this.bookUrl);
    }
}
book.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { BookService } from './book.service';
import { Book } from './book';

@Component({
   selector: 'app-book',
   templateUrl: './book.component.html'
})
export class BookComponent implements OnInit { 
   books$: Observable<Book[]>

   constructor(private bookService: BookService) { }

   ngOnInit() {
      this.getBooks();	
   }
   getBooks() {
      this.books$ = this.bookService.getBooks();
   }
}
book.component.html
<h3>Book Details</h3>
<ul>
  <li *ngFor="let book of books$ | async" >
    Id: {{book.id}}, Name: {{book.name}}, Category: {{book.category}}, Year: {{book.year}}
  </li>
</ul> 
test-data.ts
import { InMemoryDbService } from 'angular-in-memory-web-api';

export class TestData implements InMemoryDbService {
  createDb() {
    let bookDetails = [
      { id: '101', name: 'Angular 2 by Krishna', category: 'Angular', year: '2015' },
      { id: '102', name: 'AngularJS by Krishna', category: 'Angular', year: '2015' }
    ];
    return { books: bookDetails };
  }
} 
app.component.ts
import { Component } from '@angular/core';

@Component({
   selector: 'app-root',
   template: `
	<app-book></app-book>
    `
})
export class AppComponent { 
} 
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent }  from './app.component';
import { BookComponent }  from './book.component';
import { BookService } from './book.service';
import { httpInterceptorProviders } from './http-interceptors/index';

//For InMemory testing
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { TestData } from './test-data';

@NgModule({
  imports: [     
      BrowserModule,
      HttpClientModule,
      InMemoryWebApiModule.forRoot(TestData)		
  ],
  declarations: [
      AppComponent,
      BookComponent
  ],
  providers: [
      BookService,
      httpInterceptorProviders
  ],
  bootstrap: [
      AppComponent
  ]
})
export class AppModule { } 

4. Run Application

To run the application, find the steps.
1. Install Angular CLI, find the link.
2. Install Angular In-Memory Web API.
npm i angular-in-memory-web-api --save 
3. Download source code using download link given below on this page and run the application using ng serve command.
4. Access the URL http://localhost:4200
Find the output in console.
GET /api/books succeeded in 506ms 

5. References

HttpInterceptor
HttpClient

6. Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us