Add Logger

This commit is contained in:
2022-03-25 13:49:06 +01:00
parent 479d5b77e6
commit d0f35e1af6
7 changed files with 207 additions and 45 deletions

View File

@ -100,12 +100,6 @@
"@typescript-eslint/no-require-imports":"error", "@typescript-eslint/no-require-imports":"error",
"@typescript-eslint/no-this-alias":"error", "@typescript-eslint/no-this-alias":"error",
"@typescript-eslint/no-throw-literal":"error", "@typescript-eslint/no-throw-literal":"error",
"@typescript-eslint/no-type-alias":[
"error",
{
"allowAliases":"always"
}
],
"@typescript-eslint/no-unsafe-call":"error", "@typescript-eslint/no-unsafe-call":"error",
"@typescript-eslint/no-unsafe-member-access":"error", "@typescript-eslint/no-unsafe-member-access":"error",
"@typescript-eslint/no-unsafe-return":"error", "@typescript-eslint/no-unsafe-return":"error",
@ -159,8 +153,9 @@
} }
], ],
"no-unused-vars":"off", "no-unused-vars":"off",
"unused-imports/no-unused-vars": "off",
"unused-imports/no-unused-imports":"error", "unused-imports/no-unused-imports":"error",
"unused-imports/no-unused-vars":[ "@typescript-eslint/no-unused-vars":[
"warn", "warn",
{ {
"vars":"all", "vars":"all",
@ -171,5 +166,6 @@
], ],
"indent": "off", "indent": "off",
"@typescript-eslint/indent": ["error", 2], "@typescript-eslint/indent": ["error", 2],
"import/no-unresolved": ["off"]
} }
} }

View File

@ -25,6 +25,7 @@
"dependencies": { "dependencies": {
"@gquittet/graceful-server": "^2.5.2", "@gquittet/graceful-server": "^2.5.2",
"fastify": "^3.25.3", "fastify": "^3.25.3",
"fastify-plugin": "^3.0.0",
"fastify-sensible": "^3.1.2", "fastify-sensible": "^3.1.2",
"winston": "^3.4.0" "winston": "^3.4.0"
}, },

View File

@ -0,0 +1,155 @@
/* eslint-disable @typescript-eslint/require-await */
import { FastifyLogFn, FastifyLoggerInstance, FastifyPluginAsync, FastifyRequest} from "fastify";
import fastifyPlugin from "fastify-plugin";
import { Bindings } from "fastify/types/logger";
import getlogger from "./logger";
import chalk from "chalk";
const logger = getlogger("fastify");
const customLogger: FastifyLoggerInstance = {
info: function (obj: unknown, msg?: string, ...args: unknown[]): void {
if(typeof obj === "string")
logger.info(obj, msg, ...args);
else if(msg)
logger.info(msg, obj, ...args);
} as FastifyLogFn,
warn: function (obj: unknown, msg?: string, ...args: unknown[]): void {
if(typeof obj === "string")
logger.warning(obj, msg, ...args);
else if(msg)
logger.warning(msg, obj, ...args);
} as FastifyLogFn,
error: function (obj: unknown, msg?: string, ...args: unknown[]): void {
if(typeof obj === "string")
logger.error(obj, msg, ...args);
else if(msg)
logger.error(msg, obj, ...args);
} as FastifyLogFn,
fatal: function (obj: unknown, msg?: string, ...args: unknown[]): void {
if(typeof obj === "string")
logger.fatal(obj, msg, ...args);
else if(msg)
logger.fatal(msg, obj, ...args);
} as FastifyLogFn,
trace: function (obj: unknown, msg?: string, ...args: unknown[]): void {
if(typeof obj === "string")
logger.trace(obj, msg, ...args);
else if(msg)
logger.trace(msg, obj, ...args);
} as FastifyLogFn,
debug: function (obj: unknown, msg?: string, ...args: unknown[]): void {
if(typeof obj === "string")
logger.debug(obj, msg, ...args);
else if(msg)
logger.debug(msg, obj, ...args);
} as FastifyLogFn,
child: function (_bindings: Bindings): FastifyLoggerInstance {
return customLogger;
},
setBindings: function (_bindings: Bindings): void {
// OK
}
};
export type FastifyRequestLoggerOptions = {
logBody?: boolean;
ignoredPaths?: Array<string>;
};
export const plugin: FastifyPluginAsync<FastifyRequestLoggerOptions> = async (fastify, options = {}): Promise<void> => {
const {
logBody = true,
ignoredPaths = [],
} = options;
const isIgnoredRequest = (request: FastifyRequest): boolean => {
const { routerPath } = request;
if (ignoredPaths.includes(routerPath)) {
return true;
}
return false;
};
fastify.addHook("onRequest", async (request) => {
if (isIgnoredRequest(request)) {
return;
}
const id = request.id;
const method = request.method;
const referrer = (request.headers["Referer"] ?? (request.headers["referer"]) ?? request.headers["Refferer"]) ?? request.headers["refferer"];
const remoteAddr = request.ip;
const remoteUser = "???";
const url = request.url;
const httpVersion = request.raw.httpVersion;
const userAgent = request.headers["User-Agents"];
const contentLength = request.headers["content-length"];
request.log.info(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} HTTP/${httpVersion} - ${chalk.blue(remoteAddr)} ${remoteUser} - ${referrer} - ${contentLength} bytes [${id}]`);
request.log.trace(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} ${userAgent} [${id}]`);
request.log.info(
`${chalk.bold.yellow("←")}${chalk.yellow(request.method)}:${chalk.green(
request.url
)} request from ip ${chalk.blue(request.ip)}${
contentLength ? ` with a ${chalk.yellow(contentLength)}-length body` : ""
}`
);
request.log.trace("Request trace %s", JSON.stringify({header: request.headers, body: request.body}));
});
fastify.addHook("preHandler", async (request) => {
if (isIgnoredRequest(request)) {
return;
}
const id = request.id;
const method = request.method;
// const referrer = (request.headers["Referer"] ?? (request.headers["referer"]) ?? request.headers["Refferer"]) ?? request.headers["refferer"];
const remoteAddr = request.ip;
const remoteUser = "???";
const url = request.url;
const httpVersion = request.raw.httpVersion;
const userAgent = request.headers["User-Agents"];
if (request.body && logBody) {
request.log.debug("Request body: %s", {body: request.body });
}
});
fastify.addHook("onResponse", async (request, reply) => {
if (isIgnoredRequest(request)) {
return;
}
const id = request.id;
const method = request.method;
const remoteAddr = request.ip;
const remoteUser = "???";
const responseTime = Math.ceil(reply.getResponseTime());
const status = reply.statusCode + "";
const url = request.url;
const httpVersion = request.raw.httpVersion;
const contentLength = reply.getHeaders()["content-length"] ?? -1;
const statusColor = function (status: string): string {
if(status.startsWith("2"))
return chalk.green(status);
if(status.startsWith("3"))
return chalk.blue(status);
if(status.startsWith("4"))
return chalk.yellow(status);
if(status.startsWith("5"))
return chalk.red(status);
return status;
};
request.log.info(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} ${statusColor(status)} HTTP/${httpVersion} - ${chalk.blue(remoteAddr)} ${remoteUser} - ${contentLength} bytes ${responseTime} ms [${id}]`);
});
};
declare module "fastify" {
interface FastifyLoggerInstance {
setBindings(bindings: Bindings): void;
}
}
export const fastifyRequestLogger = fastifyPlugin(plugin, {
fastify: "3.x",
name: "fastify-request-logger",
});
export const fastifyLogger = customLogger;

View File

@ -5,9 +5,32 @@ const { combine, timestamp, label, printf, errors, splat } = format;
// Custom logging format // Custom logging format
const customFormat = printf(({ level, message, label, timestamp, stack }) => { const customFormat = printf(({ level, message, label, timestamp, stack }) => {
return `${timestamp} [${label || "-"}] ${level}: ${message} ${stack || ""}`; return `${level}\t ${timestamp} · ${label || "-"}: ${message} ${stack || ""}`;
}); });
const myCustomLevels = {
levels: {
alert: 0,
fatal: 1,
error: 2,
warning: 3,
verbose: 4,
info: 5,
debug: 6,
trace: 7
},
colors: {
alert: "magentaBG white",
fatal: "redBG white",
error: "red",
warning: "yellow",
verbose: "green",
info: "blue",
debug: "cyan",
trace: "cyanBG black"
}
};
// Custom combined logging format: // Custom combined logging format:
const customCombinedFormat = (module: string): Format => const customCombinedFormat = (module: string): Format =>
combine( combine(
@ -25,15 +48,19 @@ const customTransports = (): Transport[] => [new transports.Console()];
// Container to provide different pre-configured loggers // Container to provide different pre-configured loggers
const logContainer = new winston.Container(); const logContainer = new winston.Container();
winston.addColors(myCustomLevels.colors);
// Default logger for modules: // Default logger for modules:
const getLogger = (module: string): Logger => { const getLogger = (module: string): Logger & Record<keyof typeof myCustomLevels["levels"], winston.LeveledLogMethod> => {
if (!logContainer.has(module)) { if (!logContainer.has(module)) {
logContainer.add(module, { logContainer.add(module, {
level: "trace",
levels: myCustomLevels.levels,
format: customCombinedFormat(module), format: customCombinedFormat(module),
transports: customTransports() transports: customTransports()
}); });
} }
return logContainer.get(module); return logContainer.get(module) as Logger & Record<keyof typeof myCustomLevels["levels"], winston.LeveledLogMethod>;
}; };
export default getLogger; export default getLogger;

View File

@ -1,63 +1,45 @@
import Fastify from "fastify"; import Fastify from "fastify";
import fastifySensible from "fastify-sensible"; import fastifySensible from "fastify-sensible";
import GracefulServer from "@gquittet/graceful-server"; import GracefulServer from "@gquittet/graceful-server";
import getlogger, {defaultLogger} from "@logger"; import getlogger from "@logger";
import {fastifyLogger, fastifyRequestLogger} from "@logger/fastifyLogger";
const fastify = Fastify({ const fastify = Fastify({
logger: true logger: fastifyLogger,
disableRequestLogging: true
}); });
fastify.register(fastifySensible); await fastify.register(fastifyRequestLogger, {logBody: true});
await fastify.register(fastifySensible);
const gracefulServer = GracefulServer(fastify.server); const gracefulServer = GracefulServer(fastify.server);
gracefulServer.on(GracefulServer.READY, () => { gracefulServer.on(GracefulServer.READY, () => {
console.log("Server is ready"); getlogger("server").info("Server is ready");
}); });
gracefulServer.on(GracefulServer.SHUTTING_DOWN, () => { gracefulServer.on(GracefulServer.SHUTTING_DOWN, () => {
console.log("Server is shutting down"); getlogger("server").info("Server is shutting down");
}); });
gracefulServer.on(GracefulServer.SHUTDOWN, error => { gracefulServer.on(GracefulServer.SHUTDOWN, (error: {message: string}) => {
console.log("Server is down because of", error.message); getlogger("server").info("Server is down because of", error.message);
process.exit(); process.exit();
}); });
// Declare a route // Declare a route
fastify.get("/", function (request, reply) { fastify.get("/", function (request, reply) {
reply.send({ hello: "world" }); void reply.send({ hello: "world" });
}); });
// Run the server! // Run the server!
const start = async () => { const start = async (): Promise<void> => {
try { try {
await fastify.listen(3000); const port = 3000;
await fastify.listen(port);
gracefulServer.setReady(); gracefulServer.setReady();
} catch (err) { } catch (err) {
fastify.log.error(err); fastify.log.error(err);
process.exit(1); process.exit(1);
} }
}; };
start(); await start();
const c = function (): void {
const v = function (): void {
throw new Error("Oh no!");
};
return v();
};
const abc = getlogger("abc");
abc.info("Ich bin ein Test!");
abc.warn("Ich bin ein Test!");
try {
c();
}
catch (e) {
abc.warn(e);
}
const xyz = getlogger("xyz");
xyz.error("Ich bin ein Test!");
xyz.error("Ich bin ein '%s' Test!", "test");
defaultLogger.error("Ich bin ein Test!");

View File

@ -10,7 +10,8 @@
"baseUrl": "./src/", "baseUrl": "./src/",
"paths": { "paths": {
"@abc/*": ["abc/*"], "@abc/*": ["abc/*"],
"@logger": ["framework/logger/logger"] "@logger": ["framework/logger/logger"],
"@logger/*": ["framework/logger/*"]
} }
}, },
"include": ["src/**/*.ts"], "include": ["src/**/*.ts"],

View File

@ -771,7 +771,7 @@ fastify-error@^0.3.0:
fastify-plugin@^3.0.0: fastify-plugin@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz" resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.0.tgz#cf1b8c8098e3b5a7c8c30e6aeb06903370c054ca"
integrity sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w== integrity sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==
fastify-sensible@^3.1.2: fastify-sensible@^3.1.2: