Skip to content

Commit

Permalink
chore: use structured logs
Browse files Browse the repository at this point in the history
  • Loading branch information
svedova committed Apr 19, 2024
1 parent ea8046a commit 043af3f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
3 changes: 2 additions & 1 deletion src/response.ts
@@ -1,3 +1,4 @@
import type { Log } from "./utils/logger";
import { Socket } from "node:net";
import { ServerResponse } from "node:http";
import httpParse from "./http-parser";
Expand All @@ -10,7 +11,7 @@ export interface ServerlessResponse {
status?: number;
statusMessage?: string;
headers?: Record<string, string | string[]>;
logs?: string;
logs?: Log[];
}

class Response extends ServerResponse {
Expand Down
28 changes: 19 additions & 9 deletions src/utils/callbacks/api.spec.ts
Expand Up @@ -10,7 +10,18 @@ jest.mock("~/utils/filesys", () => ({
},
}));

const originalDateNow = Date.now;
const ts = 1487076708000;

describe("utils/callback/api.ts", () => {
beforeEach(() => {
Date.now = jest.fn(() => ts); //14.02.2017
});

afterEach(() => {
Date.now = originalDateNow;
});

describe("handleApi", () => {
const exampleRequest = {
method: "GET",
Expand Down Expand Up @@ -53,17 +64,16 @@ describe("utils/callback/api.ts", () => {
test("should handle returning a response body", async () => {
const response = await handleApi(exampleRequest, "/");

const expectedLogs =
"stdout:this is an info\n" +
"stdout:this info log should be captured\n" +
"stdout:this is another info\n" +
"stderr:this error log should be captured\n" +
"stdout:this comes from process.stdout.write";

expect(response).toEqual({
body: "Hello world",
status: 201,
logs: expectedLogs,
logs: [
{ ts, msg: "this is an info\n", level: "info" },
{ ts, msg: "this info log should be captured\n", level: "info" },
{ ts, msg: "this is another info\n", level: "info" },
{ ts, msg: "this error log should be captured\n", level: "error" },
{ ts, msg: "this comes from process.stdout.write", level: "info" },
],
headers: {
"X-Custom-Header": "Sample Project",
},
Expand Down Expand Up @@ -94,7 +104,7 @@ describe("utils/callback/api.ts", () => {
buffer: "SGkgd29ybGQ=",
status: 200,
statusMessage: "OK",
logs: "stdout:captured logs\n",
logs: [{ ts, msg: "captured logs\n", level: "info" }],
headers: {
connection: "close",
date: expect.any(String),
Expand Down
29 changes: 20 additions & 9 deletions src/utils/logger.ts
Expand Up @@ -4,40 +4,51 @@ const originalConsole = console;
const originalStdout = process.stdout.write;
const originalStderr = process.stderr.write;

export interface Log {
level: "info" | "error";
msg: string;
ts: number;
}

export class Logger {
stdout: string[] = [];
stdout: Log[] = [];

constructor() {
const stdout = this.streamWithContext("stdout");
const stderr = this.streamWithContext("stderr");
const stdout = this.streamWithContext("info");
const stderr = this.streamWithContext("error");

// @ts-ignore
process.stdout.write = stdout.write.bind(stdout);
// @ts-ignore
process.stderr.write = stderr.write.bind(stdout);

console = new console.Console(
this.streamWithContext("stdout"),
this.streamWithContext("stderr")
this.streamWithContext("info"),
this.streamWithContext("error")
);
}

streamWithContext(level: "stderr" | "stdout") {
streamWithContext(level: "info" | "error") {
return new stream.Writable({
write: (
chunk: any,
_: BufferEncoding,
callback: (error?: Error | null) => void
): void => {
this.stdout.push(`${level}:${chunk.toString()}`);
this.stdout.push({
ts: Date.now(),
msg: chunk.toString(),
level,
});

callback(null);
},
});
}

logs(): string {
logs(): Log[] {
this.restore();
return this.stdout.join("");
return this.stdout;
}

restore() {
Expand Down

0 comments on commit 043af3f

Please sign in to comment.