Skip to content

Commit

Permalink
feat(platform-log-middleware): display error in log "request.end"
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakita committed Jun 12, 2023
1 parent a6b3170 commit ca216f6
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 35 deletions.
2 changes: 1 addition & 1 deletion packages/platform/platform-log-middleware/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
...require("@tsed/jest-config"),
coverageThreshold: {
global: {
branches: 92,
branches: 92.59,
functions: 100,
lines: 100,
statements: 100
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {Context} from "@tsed/platform-params";

export type LoggerRequestFields = ("reqId" | "method" | "url" | "headers" | "body" | "query" | "params" | "duration" | string)[];

export interface PlatformLogMiddlewareSettings {
Expand All @@ -6,15 +8,15 @@ export interface PlatformLogMiddlewareSettings {
*/
requestFields?: LoggerRequestFields;
/**
* Log all incoming request. By default is true and print the configured `logger.requestFields`.
* Log all incoming request. By default, is true and print the configured `logger.requestFields`.
*/
logRequest?: boolean;
/**
* Log start of all incoming request. By default is true
* Log start of all incoming request. By default, is false
*/
logStart?: boolean;
/**
* Log end of all incoming request. By default is true
* Log end of all incoming request. By default, is true
*/
logEnd?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {PlatformHandlerMetadata, PlatformTest} from "@tsed/common";
import {PlatformLogMiddleware} from "./PlatformLogMiddleware";

async function createMiddlewareFixture() {
async function createMiddlewareFixture({statusCode = 200, error}: {statusCode?: number; error?: any} = {}) {
const middleware = await PlatformTest.invoke<PlatformLogMiddleware>(PlatformLogMiddleware);

const ctx = PlatformTest.createRequestContext({
Expand All @@ -12,13 +12,16 @@ async function createMiddlewareFixture() {
originalUrl: undefined
}),
response: PlatformTest.createResponse({
statusCode: 200
statusCode,
error
})
},
endpoint: new Map(),
logger: PlatformTest.injector.logger
});

ctx.error = error;

ctx.handlerMetadata = new PlatformHandlerMetadata({
handler: () => {}
});
Expand Down Expand Up @@ -75,7 +78,8 @@ describe("PlatformLogMiddleware", () => {
reqId: "id",
url: "/originalUrl",
route: "/:id",
status: 200
status: 200,
state: "OK"
})
);
expect(PlatformTest.injector.logger.info).toHaveBeenCalledWith(
Expand Down Expand Up @@ -123,7 +127,8 @@ describe("PlatformLogMiddleware", () => {
reqId: "id",
url: "url",
status: 200,
data: "test"
data: "test",
state: "OK"
})
);
});
Expand Down Expand Up @@ -187,6 +192,33 @@ describe("PlatformLogMiddleware", () => {
})
);
});
it("should configure request and create context logger (error)", async () => {
// GIVEN
const {ctx, middleware} = await createMiddlewareFixture({
statusCode: 400,
error: new Error("Test")
});

// WHEN
middleware.use(ctx);

// THEN
(ctx.response.getRes().on as jest.Mock).mock.calls[0][1]();
// middleware.onLogEnd(request.$ctx as any);

// THEN
expect(PlatformTest.injector.logger.error).toHaveBeenCalledWith(
expect.objectContaining({
event: "request.end",
method: "GET",
reqId: "id",
url: "url",
status: 400,
error_name: "Error",
error_message: "Test"
})
);
});
});
describe("when no debug, log error", () => {
beforeEach(() =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {cleanObject} from "@tsed/core";
import {Constant} from "@tsed/di";
import {Middleware, MiddlewareMethods} from "@tsed/platform-middlewares";
import {Context} from "@tsed/platform-params";
Expand Down Expand Up @@ -38,6 +39,52 @@ export class PlatformLogMiddleware implements MiddlewareMethods {
ctx.response.onEnd(() => this.onLogEnd(ctx));
}

/**
* Called when the `$onResponse` is called by Ts.ED (through Express.end).
*/
onLogEnd(ctx: Context) {
const {logRequest, logEnd, logLevel} = this.settings;
const started = ctx.logStarted;

if (logEnd && started) {
if (ctx.response.statusCode >= 400) {
ctx.logger.error({
event: "request.end",
status: ctx.response.statusCode,
status_code: String(ctx.response.statusCode),
state: "KO",
...cleanObject({
error_name: ctx.error?.name,
error_message: ctx.error?.message,
error_errors: ctx.error?.errors,
error_stack: ctx.error?.stack,
error_body: ctx.error?.body,
error_headers: ctx.error?.headers
})
});
} else {
if (logLevel === "debug") {
ctx.logger.debug({
event: "request.end",
status: ctx.response.statusCode,
status_code: String(ctx.response.statusCode),
data: ctx.data,
state: "OK"
});
} else if (logRequest) {
ctx.logger.info({
event: "request.end",
status: ctx.response.statusCode,
status_code: String(ctx.response.statusCode),
state: "OK"
});
}
}
}

ctx.logger.flush();
}

/**
* The separate onLogStart() function will allow developer to overwrite the initial request log.
* @param ctx
Expand All @@ -60,33 +107,6 @@ export class PlatformLogMiddleware implements MiddlewareMethods {
}
}

/**
* Called when the `$onResponse` is called by Ts.ED (through Express.end).
*/
onLogEnd(ctx: Context) {
const {logRequest, logEnd, logLevel} = this.settings;
const started = ctx.logStarted;

if (logEnd && started) {
if (logLevel === "debug") {
ctx.logger.debug({
event: "request.end",
status: ctx.response.statusCode,
status_code: String(ctx.response.statusCode),
data: ctx.data
});
} else if (logRequest) {
ctx.logger.info({
event: "request.end",
status: ctx.response.statusCode,
status_code: String(ctx.response.statusCode)
});
}
}

ctx.logger.flush();
}

/**
* Attach all information that will be necessary to log the request. Attach a new `request.log` object.
*/
Expand Down

0 comments on commit ca216f6

Please sign in to comment.