#Insert into db from interceptor, middleware or filter

1 messages · Page 1 of 1 (latest)

hallow matrix
#

Is there a way to insert into the db using either the service or the entity provider from an interceptor, middleware and filter?
I went all day trying to do this from an interceptor and getting errors, then changing the interceptor into a middleware class based, then changing it to a functional middleware... I was all over the place. I can't find documentation on this. Any pointers apprecieted.

steep nebula
#

It's doable. What error were you getting in the interceptor?

hallow matrix
#

I’ll get back to you tomorrow. I deleted the branch and stating from new branch. I soon as I hit the error I’ll update this post. Thanks for prompt response.

hallow matrix
#

Ok I got this working with two interceptors and one filter. requestLoggerInterceptor, responseLoggerInterceptor, and loggerExceptionFilter. All of them are logging to the console and saving the log in the database. I have one question... why when I have an exception, the exception gets saved first in the database and then the requestInterceptor?

steep nebula
#

You shouldn't need two interceptors for request and response logging, that should be managable by just one.

As for the order of execution, that seems strange. Might be related to how things are written, but without seeing anything it's gonna be hard to say

hallow matrix
#

i figures and the reason is that I'm not awaiting the insert and sometimes one goes after the other

#

async nature of the operations

#

expected

steep nebula
#

Most likely, but I wouldn't be able to say without seeing how you have things written

hallow matrix
#

import the service, creating the payload after the log to the console and this.logEntryService(createLogEntryServiceDto)

#

it is interesting that you said that I should use two interceptors but they should live in the same file

#

🤔

steep nebula
#

I never said you should use two interceptors. I said you could use one to log both the request and response

hallow matrix
#

yeah

steep nebula
#

Unless they're wildly different processes, it's lumping the logging reponsibility to a single class, right?

#

And interceptors have a pre-controller and post-controller functionality, so it should be fine to do both there

hallow matrix
#

interesting

steep nebula
#

My OgmaInterceptor logs the request metadata such as who made the call, what endpoint, method, timing, and response size, in a single interceptor like this, and has customization to allow for logging extra info as well.

steep nebula
# hallow matrix I didn't know that

That's essentially what the simple LoggingInterceptor example in the docs shows:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before...');

    const now = Date.now();
    return next
      .handle()
      .pipe(
        tap(() => console.log(`After... ${Date.now() - now}ms`)),
      );
  }
}
hallow matrix
#

if I want to try/catch this interceptor just in case some code breaks, you would wrap the whole thing... if so what would you do in the catch to not crash the server?

steep nebula
#

Or you could let the exception filter take care of it, as interceptor errors (so long as async methods are awaited) traverse to the exception filter

#

If you don't await them you'll need to use a .catch() to ensure the promise rejection is handled

hallow matrix
#

the thing is that when I don't wrap the interceptor in a try/catch, postman hands waiting for a response

steep nebula
#

What does your interceptor look like?

hallow matrix
#

oh it was a try/catch in the filter

#

I removed the try/catch in the filter and now postman get the 500

steep nebula
#

Then what does the filter look like?

hallow matrix
#
@Catch()
export class LoggerExceptionFilter<T> implements ExceptionFilter {
  constructor(private readonly logEntryService: LogEntryService, private readonly jwtService: JwtService) {}
  catch(exception: T, host: ArgumentsHost) {
    try {
      const exceptionObject = Object.assign({}, exception);
      const exceptionResponse = exceptionObject['response'] ?? null;
      const exceptionStatusCode = exceptionResponse?.statusCode ?? 500;
      const ctx = host.switchToHttp();
      const req: Request = ctx.getRequest();
      const res: Response = ctx.getResponse();
      const now = new Date().toISOString();
      const adpost = chalk.red('[ADPOST]');
      const statusCode = exceptionStatusCode;
      const methodAndEndpoint = `[${chalk.yellow(req.method)}] ${statusCode} ${req.originalUrl}`;
      const errorPayloadString = `[${chalk.red('ERROR')}] ${JSON.stringify(exception)}`;
      const logString = `${adpost} ${now} ${methodAndEndpoint} ${errorPayloadString}`;
      console.log(logString);
​
      console.log('statusCode', exception);
      const errorPayload = Object.assign({}, exception);
​
      const user = this.jwtService.decode(this.getToken(req)) as User;
      const logEntryPayload: CreateLogEntryDto = {
        issuer_ip: req.socket.remoteAddress,
        level: Log.Level.ERROR,
        status_code: statusCode,
        method: req.method,
        coordinates: null,
        endpoint: req.originalUrl,
        incoming_payload: null,
        error_payload: errorPayload,
        user_uuid: user ? user.uuid : null,
        email: user ? user.email : null,
        role: user ? user.role.value : null,
      };
      this.logEntryService.create(logEntryPayload);

      return res.status(Number(statusCode)).json(exception['response']);
    } catch (err) {
      console.error(err);
    }
  }
  private getToken(req: Request) {...}
  private maskPassword(payload: object) {...});
    }
    return payload;
  }
}
steep nebula
#

You should make sure that when you catch you still res.send() something back

hallow matrix
#

now is working but that I can't get the exception to get the error object when the error is not and HttpException. That's why I'm trying to Obeject.assign({}, exception);

hallow matrix
#

Question… when you put the response logger in the same interceptor… does the interceptor waits for the handler to finished everything has to do and then able to get the payload going back to the client?

#

My guess is that the response goes inside the return next()

steep nebula
hallow matrix
#

If I creat two interceptors, one for logging and another to do something different, when I register them in app.module, both are going to be provide: APP_INTERCEPTOR?

steep nebula
#

Yep