Skip to content

Commit

Permalink
feat(api): add request logging
Browse files Browse the repository at this point in the history
  • Loading branch information
wessberg committed May 19, 2021
1 parent 3fc2308 commit a58e2c5
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 55 deletions.
120 changes: 120 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@rollup/plugin-json": "4.1.0",
"@types/express": "4.17.11",
"@types/mime": "2.0.3",
"@types/morgan": "1.9.2",
"@types/node": "15.3.0",
"@types/node-fetch": "2.5.10",
"@types/semver": "7.3.6",
Expand Down Expand Up @@ -107,6 +108,7 @@
"http-status-codes": "2.1.4",
"intersection-observer": "0.12.0",
"mime": "2.5.2",
"morgan": "1.10.0",
"mutationobserver-shim": "0.3.7",
"node.parentelement": "1.0.2",
"perfnow": "0.2.0",
Expand Down
10 changes: 9 additions & 1 deletion src/api/server/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import express, {Express} from "express";
import morgan from "morgan";
import {ApiControllers, IServer, ServerOptions} from "./i-server";
import {IMetricsService} from "../../service/metrics/i-metrics-service";
import {createServer as createHttpServer, Server as HttpServer} from "http";
Expand All @@ -23,6 +24,13 @@ export class Server implements IServer {
// Options
app.enable("etag");

// Add request logging
app.use(
morgan("combined", {
skip: () => this.config.logLevel === "silent"
})
);

// Setup CORS.
app.use((_, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
Expand Down Expand Up @@ -55,7 +63,7 @@ export class Server implements IServer {
: createHttpServer(this.app);

server.listen(port, host, () => {
this.loggerService.log(`${"https" in options && options.https ? "Https" : "Http"} server started on host ${host} and port ${port}`);
this.loggerService.info(`${"https" in options && options.https ? "Https" : "Http"} server started on host ${host} and port ${port}`);
});

this.server = server;
Expand Down
15 changes: 15 additions & 0 deletions src/api/util/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {ApiMethod, ContentType} from "../server/i-server";
import {ContentEncodingKind} from "../../encoding/content-encoding-kind";
import {LogLevel} from "../../service/logger/i-logger-service";

export function parseApiMethod(method: string): ApiMethod | undefined {
const uppercased = method.toUpperCase();
Expand Down Expand Up @@ -27,6 +28,20 @@ export function parseContentEncodingKind(encoding: string | undefined): ContentE
}
}

export function parseLogLevel(level: string | undefined): LogLevel | undefined {
if (level == null) return undefined;
const lowercased = level.toUpperCase();
switch (lowercased) {
case "silent":
case "info":
case "verbose":
case "debug":
return lowercased;
default:
return undefined;
}
}

/**
* Picks the most favorable encoding to use from the given Set of encodings
*/
Expand Down
12 changes: 4 additions & 8 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import {environment} from "../environment/environment";
import {readFileSync} from "fs";
import {Buffer} from "buffer";
import {booleanize} from "../api/util";
import {LogLevel} from "../service/logger/i-logger-service";
import {parseLogLevel} from "../api/util/util";

export interface Config {
sentryDsn: string | undefined;
production: boolean;
development: boolean;
staging: boolean;
logLevel: LogLevel;
testing: boolean;
debug: boolean;
verbose: boolean;
clearCache: boolean;
https: boolean;
port: number;
Expand All @@ -21,12 +20,9 @@ export interface Config {

export const config: Config = {
sentryDsn: environment.SENTRY_DSN,
development: environment.NODE_ENV == null || environment.NODE_ENV === "" || environment.NODE_ENV.toLowerCase() === "development",
staging: environment.NODE_ENV != null && environment.NODE_ENV.toLowerCase() === "staging",
production: environment.NODE_ENV != null && environment.NODE_ENV.toLowerCase() === "production",
testing: booleanize(environment.TESTING),
debug: booleanize(environment.DEBUG),
verbose: booleanize(environment.VERBOSE),
logLevel: parseLogLevel(environment.LOG_LEVEL) ?? "info",
clearCache: booleanize(environment.CLEAR_CACHE),
https: booleanize(environment.HTTPS),
host: environment.HOST,
Expand Down
3 changes: 1 addition & 2 deletions src/environment/environment-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ export const environmentDefaults = {
SENTRY_DSN: undefined as string | undefined,
KEY: undefined as string | undefined,
CERT: undefined as string | undefined,
LOG_LEVEL: "info",
NODE_ENV: "development",
TESTING: "false",
DEBUG: "false",
VERBOSE: "false",
HTTPS: "false",
CLEAR_CACHE: "false",
HOST: "0.0.0.0",
Expand Down
15 changes: 11 additions & 4 deletions src/service/logger/i-logger-service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

export type LogLevel = "silent" | "info" | "verbose" | "debug";

export const logLevelHierarchy = {
silent: 0,
info: 1,
verbose: 2,
debug: 3
};

export interface ILoggerService {
log(...messages: any[]): any[];
debug(...messages: any[]): any[];
info(...messages: any[]): any[];
verbose(...messages: any[]): any[];
setDebug(debug: boolean): void;
setVerbose(verbose: boolean): void;
debug(...messages: any[]): any[];
}
Loading

0 comments on commit a58e2c5

Please sign in to comment.