This commit is contained in:
Shinwoo PARK 2023-12-10 17:13:04 +09:00
parent f13a1d4c63
commit c792dbdcd6
6 changed files with 601 additions and 135 deletions

31
dist/README.md vendored
View File

@ -1,10 +1,28 @@
# NestLoggedDecorators # NestLoggedDecorators
This package provides some decorations to make NestJS logging simpler. This package provides some decorations to make NestJS logging simpler.
It only uses Logger provided by @nestjs/common package and some dependencies required for nestjs. It only uses Logger provided by @nestjs/common package and some dependencies required for nestjs.
> TODO: Improve README, providing Quickstart section, add wiki to github
## How to use ## How to use
### Installation
npm:
```sh
npm i nestlogged
```
yarn:
```sh
yarn add nestlogged
```
### Route Logging ### Route Logging
```ts ```ts
import { Controller, Get } from "@nestjs/common"; import { Controller, Get } from "@nestjs/common";
import { LoggedRoute } from "nlogdec"; import { LoggedRoute } from "nlogdec";
@ -21,7 +39,7 @@ export class WhateverController {
} }
``` ```
``` ```md
[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController//you/like (whateverYouLikeImpl) [Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController//you/like (whateverYouLikeImpl)
[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] RETURNED RESPONSE WhateverController//you/like (whateverYouLikeImpl) [Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] RETURNED RESPONSE WhateverController//you/like (whateverYouLikeImpl)
``` ```
@ -46,7 +64,7 @@ export class WhateverController {
} }
``` ```
``` ```md
[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController//you/like (whateverYouLikeImpl) [Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController//you/like (whateverYouLikeImpl)
[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] WHILE HTTP WhateverController//you/like (whateverYouLikeImpl) ERROR BadRequestException: I don't like this [Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] WHILE HTTP WhateverController//you/like (whateverYouLikeImpl) ERROR BadRequestException: I don't like this
``` ```
@ -71,7 +89,7 @@ export class WhateverController {
} }
``` ```
``` ```md
[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController/you/like (whateverYouLikeImpl) [Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController/you/like (whateverYouLikeImpl)
[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] WHILE HTTP WhateverController/you/like (whateverYouLikeImpl) ERROR BadRequestException: I don't like this [Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] WHILE HTTP WhateverController/you/like (whateverYouLikeImpl) ERROR BadRequestException: I don't like this
``` ```
@ -81,6 +99,7 @@ You feel the change?
Logged path is slightly changed from `WhateverController//you/like` to `WhateverController/you/like`. Logged path is slightly changed from `WhateverController//you/like` to `WhateverController/you/like`.
### Function Logging ### Function Logging
```ts ```ts
import { LoggedFunction } from "nlogdec"; import { LoggedFunction } from "nlogdec";
@ -92,7 +111,7 @@ export async function doILikeThis(stuff: "apple" | "banana"): "yes" | "no" {
LoggedFunction decorator will log function calls and returns for you. LoggedFunction decorator will log function calls and returns for you.
**Note: This decorator is expected to be used with a class method. You can't use this outside of class** > Note: This decorator is expected to be used with a class method. You can't use this outside of class
Like `LoggedRoute` decorator, it will automatically catch all exceptions, log it, and throw it again. Like `LoggedRoute` decorator, it will automatically catch all exceptions, log it, and throw it again.
@ -111,7 +130,8 @@ export async function doILikeThis(
doILikeThis("apple") doILikeThis("apple")
``` ```
```
```md
HIT HTTP WhateverController//you/like (whateverYouLikeImpl) WITH stuff="apple" HIT HTTP WhateverController//you/like (whateverYouLikeImpl) WITH stuff="apple"
``` ```
@ -121,6 +141,7 @@ The name of parameter is decided by the first parameter of LoggedParam decorator
This decorator also can be used with `LoggedRoute`. This decorator also can be used with `LoggedRoute`.
### Class Logging ### Class Logging
You can make all method in injectable classes to logged function. You can make all method in injectable classes to logged function.
```ts ```ts

4
dist/package.json vendored
View File

@ -1,6 +1,6 @@
{ {
"name": "nlogdec", "name": "nestlogged",
"version": "1.2.3", "version": "1.0.0",
"description": "A NestJS Logger Decorator Library", "description": "A NestJS Logger Decorator Library",
"main": "lib/index.js", "main": "lib/index.js",
"repository": "https://github.com/worplo/nestlogged", "repository": "https://github.com/worplo/nestlogged",

View File

@ -6,7 +6,12 @@ import {
ScopeOptions, ScopeOptions,
} from "@nestjs/common"; } from "@nestjs/common";
import { ScopedLogger } from "./logger"; import { ScopedLogger } from "./logger";
import { LoggedParamReflectData } from "./reflected"; import {
LoggedParamReflectData,
ScopeKeyReflectData,
forceScopeKey,
scopeKey,
} from "./reflected";
import { loggedParam, scopedLogger } from "./reflected"; import { loggedParam, scopedLogger } from "./reflected";
import objectContainedLogged from "./functions"; import objectContainedLogged from "./functions";
import { RequestMethod } from "@nestjs/common"; import { RequestMethod } from "@nestjs/common";
@ -36,7 +41,9 @@ function loggerInit(_target: any) {
} }
} }
export function LoggedInjectable(options?: ScopeOptions) { export function LoggedInjectable(
options?: ScopeOptions & { verbose?: boolean }
) {
return (target: any) => { return (target: any) => {
loggerInit(target.prototype); loggerInit(target.prototype);
@ -52,7 +59,8 @@ export function LoggedInjectable(options?: ScopeOptions) {
const all = Reflect.getMetadataKeys(target.prototype[method]).map( const all = Reflect.getMetadataKeys(target.prototype[method]).map(
(k) => [k, Reflect.getMetadata(k, target.prototype[method])] (k) => [k, Reflect.getMetadata(k, target.prototype[method])]
); );
logger.log(`LoggedFunction applied to ${method}`); if (options && options.verbose)
logger.log(`LoggedFunction applied to ${method}`);
LoggedFunction(target.prototype, method, { LoggedFunction(target.prototype, method, {
value: target.prototype[method], value: target.prototype[method],
}); });
@ -71,7 +79,7 @@ export function LoggedController(
prefix: string | string[] prefix: string | string[]
): (target: any) => void; ): (target: any) => void;
export function LoggedController( export function LoggedController(
options: ControllerOptions options: ControllerOptions & { verbose?: boolean }
): (target: any) => void; ): (target: any) => void;
export function LoggedController(param?: any): (target: any) => void { export function LoggedController(param?: any): (target: any) => void {
@ -82,6 +90,11 @@ export function LoggedController(param?: any): (target: any) => void {
const methods = Object.getOwnPropertyNames(target.prototype); const methods = Object.getOwnPropertyNames(target.prototype);
let verbose =
typeof param === "object" && Object.keys(param).includes("verbose")
? param.verbose
: false;
methods.forEach((method) => { methods.forEach((method) => {
if ( if (
method !== "constructor" && method !== "constructor" &&
@ -95,9 +108,10 @@ export function LoggedController(param?: any): (target: any) => void {
const all = Reflect.getMetadataKeys(target.prototype[method]).map( const all = Reflect.getMetadataKeys(target.prototype[method]).map(
(k) => [k, Reflect.getMetadata(k, target.prototype[method])] (k) => [k, Reflect.getMetadata(k, target.prototype[method])]
); );
logger.log( if (verbose)
`LoggedRoute applied to ${method} (${RevRequestMethod[httpMethod]} ${path})` logger.log(
); `LoggedRoute applied to ${method} (${RevRequestMethod[httpMethod]} ${path})`
);
LoggedRoute()(target.prototype, method, { LoggedRoute()(target.prototype, method, {
value: target.prototype[method], value: target.prototype[method],
}); });
@ -111,6 +125,126 @@ export function LoggedController(param?: any): (target: any) => void {
}; };
} }
interface FunctionMetadata {
scopedLoggerInjectableParam?: number;
scopeKeys?: ScopeKeyReflectData[];
shouldScoped?: boolean;
loggedParams?: LoggedParamReflectData[];
}
function overrideBuild<F extends Array<any>, R>(
originalFunction: (...args: F) => Promise<R>,
baseLogger: Logger,
metadatas: FunctionMetadata,
key: string,
route?: {
fullRoute: string;
}
) {
return async function (...args: F) {
let injectedLogger: Logger = baseLogger;
if (typeof metadatas.scopedLoggerInjectableParam !== "undefined") {
if (
args.length <= metadatas.scopedLoggerInjectableParam ||
!(args[metadatas.scopedLoggerInjectableParam] instanceof ScopedLogger)
) {
args[metadatas.scopedLoggerInjectableParam] = new ScopedLogger(
baseLogger,
key
);
} else {
args[metadatas.scopedLoggerInjectableParam] = new ScopedLogger(
args[metadatas.scopedLoggerInjectableParam],
key
);
}
injectedLogger = args[metadatas.scopedLoggerInjectableParam];
if (Array.isArray(metadatas.scopeKeys)) {
const scopeKeyResults: { error: boolean; value: string }[] =
metadatas.scopeKeys.map((key) => {
const argsValue = args[key.index];
if (!key.path) {
if (!metadatas.shouldScoped || argsValue) {
return { error: false, value: `${key.name}=${argsValue}` };
} else {
return {
error: true,
value: `ScopeKey in ShouldScope cannot be falsy value (${argsValue})`,
};
}
}
try {
const reduceResult = key.path.reduce((base, keyPath) => {
if (
typeof base !== "object" ||
!Object.keys(base).includes(keyPath)
)
throw new Error(
`Cannot find key ${keyPath} in ${
typeof base === "object" ? JSON.stringify(base) : base
}`
);
return base[keyPath];
}, argsValue);
return { error: false, value: `${key.name}=${reduceResult}` };
} catch (e) {
return { error: true, value: e.message };
}
});
const successResults = scopeKeyResults.filter((v) => v.error === false);
if (successResults.length === 0) {
if (metadatas.shouldScoped) {
scopeKeyResults.forEach((v) => injectedLogger.warn(v.value));
}
} else {
(injectedLogger as ScopedLogger).addScope(successResults[0].value);
}
}
}
injectedLogger.log(
`${route ? "HIT HTTP" : "CALL"} ${
route ? `${route.fullRoute} (${key})` : key
} ${
metadatas.loggedParams && metadatas.loggedParams.length > 0
? "WITH " +
(
await Promise.all(
metadatas.loggedParams.map(
async ({ name, index, include, exclude }) =>
name +
"=" +
(await objectContainedLogged(args[index], {
include,
exclude,
}))
)
)
).join(", ")
: ""
}`
);
try {
const r: R = await originalFunction.call(this, ...args);
injectedLogger.log(
route
? `RETURNED RESPONSE ${route.fullRoute} (${key})`
: `RETURNED ${key}`
);
return r;
} catch (e) {
injectedLogger.error(
`WHILE ${route ? `HTTP ${route.fullRoute} (${key})` : key} ERROR ${e}`
);
throw e;
}
};
}
export function LoggedFunction<F extends Array<any>, R>( export function LoggedFunction<F extends Array<any>, R>(
_target: any, _target: any,
key: string, key: string,
@ -129,67 +263,40 @@ export function LoggedFunction<F extends Array<any>, R>(
return; return;
} }
_target[key] = async function (...args: F) { const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata( scopedLogger,
scopedLogger, _target,
_target, key
key );
);
if ( const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
typeof scopedLoggerInjectableParam !== "undefined" && loggedParam,
(args.length <= scopedLoggerInjectableParam || _target,
!(args[scopedLoggerInjectableParam] instanceof ScopedLogger)) key
) { );
args[scopedLoggerInjectableParam] = new ScopedLogger(logger, key);
} else if (typeof scopedLoggerInjectableParam !== "undefined") {
args[scopedLoggerInjectableParam] = new ScopedLogger(
args[scopedLoggerInjectableParam],
key
);
}
const injectedLogger = const scopeKeys: ScopeKeyReflectData[] = Reflect.getOwnMetadata(
typeof scopedLoggerInjectableParam !== "undefined" scopeKey,
? args[scopedLoggerInjectableParam] _target,
: logger; key
);
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata( const shouldScoped: boolean = Reflect.getOwnMetadata(forceScopeKey, fn);
loggedParam,
_target,
key
);
injectedLogger.log( const overrideFunction = overrideBuild(
`CALL ${key} ${ fn,
loggedParams && loggedParams.length > 0 logger,
? "WITH " + {
( scopedLoggerInjectableParam,
await Promise.all( loggedParams,
loggedParams.map( scopeKeys,
async ({ name, index, include, exclude }) => shouldScoped,
name + },
"=" + key
(await objectContainedLogged(args[index], { );
include,
exclude,
}))
)
)
).join(", ")
: ""
}`
);
try { _target[key] = overrideFunction;
const r: R = await fn.call(this, ...args); descriptor.value = overrideFunction;
injectedLogger.log(`RETURNED ${key}`);
return r;
} catch (e) {
injectedLogger.error(`WHILE ${key} ERROR ${e}`);
throw e;
}
};
} }
export function LoggedRoute<F extends Array<any>, R>(route?: string) { export function LoggedRoute<F extends Array<any>, R>(route?: string) {
@ -204,13 +311,6 @@ export function LoggedRoute<F extends Array<any>, R>(route?: string) {
const fn = descriptor.value; const fn = descriptor.value;
const httpPath: string = Reflect.getMetadata("path", fn);
const httpMethod: RequestMethod = Reflect.getMetadata("method", fn);
const fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${
RevRequestMethod[httpMethod]
}]`;
if (!fn || typeof fn !== "function") { if (!fn || typeof fn !== "function") {
logger.warn( logger.warn(
`LoggedRoute decorator applied to non-function property: ${key}` `LoggedRoute decorator applied to non-function property: ${key}`
@ -218,63 +318,46 @@ export function LoggedRoute<F extends Array<any>, R>(route?: string) {
return; return;
} }
_target[key] = async function (...args: F) { const httpPath: string = Reflect.getMetadata("path", fn);
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata( const httpMethod: RequestMethod = Reflect.getMetadata("method", fn);
scopedLogger,
_target,
key
);
if ( const fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${
typeof scopedLoggerInjectableParam !== "undefined" && RevRequestMethod[httpMethod]
(args.length <= scopedLoggerInjectableParam || }]`;
!(args[scopedLoggerInjectableParam] instanceof ScopedLogger))
) { const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
args[scopedLoggerInjectableParam] = new ScopedLogger(logger, fullRoute); scopedLogger,
_target,
key
);
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
loggedParam,
_target,
key
);
const scopeKeys: ScopeKeyReflectData[] = Reflect.getOwnMetadata(
scopeKey,
_target,
key
);
const shouldScoped: boolean = Reflect.getOwnMetadata(forceScopeKey, fn);
const overrideFunction = overrideBuild(
fn,
logger,
{
scopedLoggerInjectableParam,
loggedParams,
scopeKeys,
shouldScoped,
},
key,
{
fullRoute,
} }
);
const injectedLogger =
typeof scopedLoggerInjectableParam !== "undefined"
? args[scopedLoggerInjectableParam]
: logger;
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
loggedParam,
_target,
key
);
injectedLogger.log(
`HIT HTTP ${fullRoute} (${key}) ${
loggedParams && loggedParams.length > 0
? "WITH " +
(
await Promise.all(
loggedParams.map(
async ({ name, index, include, exclude }) =>
name +
"=" +
(await objectContainedLogged(args[index], {
include,
exclude,
}))
)
)
).join(", ")
: ""
}`
);
try {
const r: R = await fn.call(this, ...args);
injectedLogger.log(`RETURNED RESPONSE ${fullRoute} (${key})`);
return r;
} catch (e) {
injectedLogger.error(`WHILE HTTP ${fullRoute} (${key}) ERROR ${e}`);
throw e;
}
};
return [httpPath, httpMethod];
}; };
} }

View File

@ -11,6 +11,10 @@ export class ScopedLogger extends Logger {
super(); super();
} }
public addScope(scopeId: string) {
this.scopeId = scopeId;
}
private scopedLog(method: LogLevel) { private scopedLog(method: LogLevel) {
return (message: string) => { return (message: string) => {
this.logger[method]( this.logger[method](

View File

@ -5,8 +5,17 @@ export interface LoggedParamReflectData {
exclude?: string[]; exclude?: string[];
} }
export const scopedLogger = Symbol("scopedLogger"); export interface ScopeKeyReflectData {
export const loggedParam = Symbol("loggedParam"); name: string;
index: number;
path?: string[];
priority?: number;
}
export const scopedLogger = Symbol("nlogdec-scopedLogger");
export const loggedParam = Symbol("nlogdec-loggedParam");
export const scopeKey = Symbol("nlogdec-scopeKey");
export const forceScopeKey = Symbol("nlogdec-forceScopeKey");
export function InjectLogger( export function InjectLogger(
target: any, target: any,
@ -34,6 +43,7 @@ export function LoggedParam(
existingLoggedParams.push({ existingLoggedParams.push({
name, name,
index: parameterIndex, index: parameterIndex,
// If path is provided in string[] type, convert it to string path because it is used in string type
include: include:
options && options &&
options.includePath && options.includePath &&
@ -52,3 +62,38 @@ export function LoggedParam(
); );
}; };
} }
export function ScopeKey(
name: string,
options?: { path?: string | string[]; priority?: number }
) {
return (
target: any,
propertyKey: string | symbol,
parameterIndex: number
) => {
const existingScopeKeys: ScopeKeyReflectData[] =
Reflect.getOwnMetadata(scopeKey, target, propertyKey) || [];
existingScopeKeys.push({
name,
index: parameterIndex,
path: Array.isArray(options?.path)
? options.path
: options?.path?.split("."),
priority: options?.priority,
});
existingScopeKeys.sort((a, b) => (b.priority ?? 1) - (a.priority ?? 1));
Reflect.defineMetadata(scopeKey, existingScopeKeys, target, propertyKey);
};
}
export function ShouldScoped(
_target: any,
_key: string,
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>
) {
Reflect.defineMetadata(forceScopeKey, true, descriptor.value);
}

View File

@ -0,0 +1,313 @@
import { LoggedFunction, LoggedInjectable } from "../logged";
import { ScopedLogger } from "../logger";
import {
InjectLogger,
LoggedParam,
ScopeKey,
ShouldScoped,
} from "../reflected";
type TestObject = {
a: string;
b: { c: string; f: number };
d: [number, string];
e: { p: string; g: number };
};
const testObject: TestObject = {
a: "asdf",
b: { c: "zxcv", f: 1 },
d: [2, "qwer"],
e: { p: "uiop", g: 3 },
};
@LoggedInjectable()
class LoggedClass {
async testParameterLoggingWithoutInjection(@LoggedParam("key") key: number) {
console.log(key);
}
async testMultiParameterLoggingWithoutInjection(
@LoggedParam("key") key: number,
@LoggedParam("key2") key2: string
) {
console.log(key, key2);
}
async testParameterLoggingWithInjection(
@LoggedParam("key") key: number,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key.toString());
}
async testMultiParameterLoggingWithInjection(
@LoggedParam("key") key: number,
@LoggedParam("key2") key2: string,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key.toString() + key2);
}
async testObjectParameterLogging(
@LoggedParam("key") key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testObjectParameterDotIncludeLogging(
@LoggedParam("key", { includePath: ["a", "b.c", "d.0", "e"] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testObjectParameterArrayIncludeLogging(
@LoggedParam("key", { includePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testObjectParameterDotExcludeLogging(
@LoggedParam("key", { excludePath: ["a", "b.c", "d.0", "e"] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testObjectParameterArrayExcludeLogging(
@LoggedParam("key", { excludePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testScopedLogging(
@LoggedParam("key") @ScopeKey("scopekey") key: string,
@LoggedParam("key2") key2: number,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key + key2.toString());
}
async testPathScopedLogging(
@LoggedParam("key") @ScopeKey("scopekey", { path: "b.c" }) key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testOrScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey-a", { path: "a" })
@ScopeKey("scopekey-b", { path: "b" })
key: { a: string } | { b: string },
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testPriorityScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey-a", { path: "a", priority: 0.5 })
@ScopeKey("scopekey-b", { path: "b" }) // default 1
key: { a?: string; b?: string },
// if both a and b are undefined, set scope to nothing
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
async testOptionalScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey")
key?: string,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key);
}
@ShouldScoped // Warn if there is no valid scopekey
async testShouldScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey")
key?: string,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key);
}
}
class LoggedMethodsClass {
@LoggedFunction
async testParameterLoggingWithoutInjection(@LoggedParam("key") key: number) {
console.log(key);
}
@LoggedFunction
async testMultiParameterLoggingWithoutInjection(
@LoggedParam("key") key: number,
@LoggedParam("key2") key2: string
) {
console.log(key, key2);
}
@LoggedFunction
async testParameterLoggingWithInjection(
@LoggedParam("key") key: number,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key.toString());
}
@LoggedFunction
async testMultiParameterLoggingWithInjection(
@LoggedParam("key") key: number,
@LoggedParam("key2") key2: string,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key.toString() + key2);
}
@LoggedFunction
async testObjectParameterLogging(
@LoggedParam("key") key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testObjectParameterDotIncludeLogging(
@LoggedParam("key", { includePath: ["a", "b.c", "d.0", "e"] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testObjectParameterArrayIncludeLogging(
@LoggedParam("key", { includePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testObjectParameterDotExcludeLogging(
@LoggedParam("key", { excludePath: ["a", "b.c", "d.0", "e"] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testObjectParameterArrayExcludeLogging(
@LoggedParam("key", { excludePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testScopedLogging(
@LoggedParam("key") @ScopeKey("scopekey") key: string,
@LoggedParam("key2") key2: number,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key + key2.toString());
}
@LoggedFunction
async testPathScopedLogging(
@LoggedParam("key") @ScopeKey("scopekey", { path: "b.c" }) key: TestObject,
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testOrScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey-a", { path: "a" })
@ScopeKey("scopekey-b", { path: "b" })
key: { a: string } | { b: string },
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testPriorityScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey-a", { path: "a", priority: 0.5 })
@ScopeKey("scopekey-b", { path: "b" }) // default 1
key: { a?: string; b?: string },
// if both a and b are undefined, set scope to nothing
@InjectLogger logger?: ScopedLogger
) {
logger.log(JSON.stringify(key));
}
@LoggedFunction
async testOptionalScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey")
key?: string,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key);
}
@LoggedFunction
@ShouldScoped // Warn if there is no valid scopekey
async testShouldScopedLogging(
@LoggedParam("key")
@ScopeKey("scopekey")
key?: string,
@InjectLogger logger?: ScopedLogger
) {
logger.log(key);
}
}
/**
* Choose Class to Test
*/
// const tester = new LoggedClass();
const tester = new LoggedMethodsClass();
/**
* Choose Method to Test
*/
// tester.testParameterLoggingWithoutInjection(1);
// tester.testMultiParameterLoggingWithoutInjection(1, "asdf");
// tester.testParameterLoggingWithInjection(1);
// tester.testMultiParameterLoggingWithInjection(1, "asdf");
// tester.testObjectParameterLogging(testObject);
// tester.testObjectParameterDotIncludeLogging(testObject);
// tester.testObjectParameterArrayIncludeLogging(testObject);
// tester.testObjectParameterDotExcludeLogging(testObject);
// tester.testObjectParameterArrayExcludeLogging(testObject);
// tester.testScopedLogging("asdf", 2);
// tester.testPathScopedLogging(testObject);
// tester.testOrScopedLogging({ a: "asdf" });
// tester.testOrScopedLogging({ b: "qwer" });
// tester.testPriorityScopedLogging({ a: "asdf", b: "qwer" });
// tester.testPriorityScopedLogging({ a: "asdf" });
// tester.testPriorityScopedLogging({ b: "qwer" });
// tester.testPriorityScopedLogging({});
// tester.testOptionalScopedLogging("asdf");
// tester.testOptionalScopedLogging();
// tester.testShouldScopedLogging("asdf");
tester.testShouldScopedLogging();